diff options
| author | Jake Howard <git@theorangeone.net> | 2025-06-10 23:00:25 +0100 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2025-06-16 09:25:25 +0200 |
| commit | 12c1557060fc94fe5e1fbddc4578a4e29d38f77c (patch) | |
| tree | f18ff6aa25490320e7cb0445cd952e28af6e3fd5 /django/http/request.py | |
| parent | 8e2249bc79a74d96f9ad20c89f82a89c78d4b648 (diff) | |
Fixed #36447 -- Selected preferred media type based on quality.
When matching which entry in the `Accept` header should be used for
a given media type, the specificity matters. However once those are
resolved, only the quality matters when selecting preference.
Regression in c075508b4de8edf9db553b409f8a8ed2f26ecead.
Thank you to Anders Kaseorg for the report.
Diffstat (limited to 'django/http/request.py')
| -rw-r--r-- | django/http/request.py | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/django/http/request.py b/django/http/request.py index c26a4954d1..daaf3748cc 100644 --- a/django/http/request.py +++ b/django/http/request.py @@ -90,7 +90,7 @@ class HttpRequest: @cached_property def accepted_types(self): - """Return a list of MediaType instances, in order of preference.""" + """Return a list of MediaType instances, in order of preference (quality).""" header_value = self.headers.get("Accept", "*/*") return sorted( ( @@ -98,19 +98,30 @@ class HttpRequest: for token in header_value.split(",") if token.strip() and (media_type := MediaType(token)).quality != 0 ), + key=operator.attrgetter("quality", "specificity"), + reverse=True, + ) + + @cached_property + def accepted_types_by_precedence(self): + """ + Return a list of MediaType instances, in order of precedence (specificity). + """ + return sorted( + self.accepted_types, key=operator.attrgetter("specificity", "quality"), reverse=True, ) def accepted_type(self, media_type): """ - Return the preferred MediaType instance which matches the given media type. + Return the MediaType instance which best matches the given media type. """ media_type = MediaType(media_type) return next( ( accepted_type - for accepted_type in self.accepted_types + for accepted_type in self.accepted_types_by_precedence if media_type.match(accepted_type) ), None, @@ -130,7 +141,7 @@ class HttpRequest: if not desired_types: return None - # Of the desired media types, select the one which is most desirable. + # Of the desired media types, select the one which is preferred. return min(desired_types, key=lambda t: self.accepted_types.index(t[0]))[1] def accepts(self, media_type): |
