summaryrefslogtreecommitdiff
path: root/docs/topics/class-based-views/generic-editing.txt
diff options
context:
space:
mode:
authorJake Howard <git@theorangeone.net>2024-07-26 12:34:42 +0100
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2024-09-09 12:02:18 +0200
commite161bd4657177f0e723a14a6e414884363b31a5d (patch)
treefbc9c862c2caad8cfa36537d108e1a9ddc281474 /docs/topics/class-based-views/generic-editing.txt
parent826ef006681eae1e9b4bd0e4f18fa13713025cba (diff)
Fixed #35631 -- Added HttpRequest.get_preferred_type().
Diffstat (limited to 'docs/topics/class-based-views/generic-editing.txt')
-rw-r--r--docs/topics/class-based-views/generic-editing.txt53
1 files changed, 53 insertions, 0 deletions
diff --git a/docs/topics/class-based-views/generic-editing.txt b/docs/topics/class-based-views/generic-editing.txt
index 5841c703f6..4310ae9dcc 100644
--- a/docs/topics/class-based-views/generic-editing.txt
+++ b/docs/topics/class-based-views/generic-editing.txt
@@ -273,3 +273,56 @@ works with an API-based workflow as well as 'normal' form POSTs::
class AuthorCreateView(JsonableResponseMixin, CreateView):
model = Author
fields = ["name"]
+
+The above example assumes that if the client supports ``text/html``, that they
+would prefer it. However, this may not always be true. When requesting a
+``.css`` file, many browsers will send the header
+``Accept: text/css,*/*;q=0.1``, indicating that they would prefer CSS, but
+anything else is fine. This means ``request.accepts("text/html") will be
+``True``.
+
+To determine the correct format, taking into consideration the client's
+preference, use :func:`django.http.HttpRequest.get_preferred_type`::
+
+ class JsonableResponseMixin:
+ """
+ Mixin to add JSON support to a form.
+ Must be used with an object-based FormView (e.g. CreateView).
+ """
+
+ accepted_media_types = ["text/html", "application/json"]
+
+ def dispatch(self, request, *args, **kwargs):
+ if request.get_preferred_type(self.accepted_media_types) is None:
+ # No format in common.
+ return HttpResponse(
+ status_code=406, headers={"Accept": ",".join(self.accepted_media_types)}
+ )
+
+ return super().dispatch(request, *args, **kwargs)
+
+ def form_invalid(self, form):
+ response = super().form_invalid(form)
+ accepted_type = request.get_preferred_type(self.accepted_media_types)
+ if accepted_type == "text/html":
+ return response
+ elif accepted_type == "application/json":
+ return JsonResponse(form.errors, status=400)
+
+ def form_valid(self, form):
+ # We make sure to call the parent's form_valid() method because
+ # it might do some processing (in the case of CreateView, it will
+ # call form.save() for example).
+ response = super().form_valid(form)
+ accepted_type = request.get_preferred_type(self.accepted_media_types)
+ if accepted_type == "text/html":
+ return response
+ elif accepted_type == "application/json":
+ data = {
+ "pk": self.object.pk,
+ }
+ return JsonResponse(data)
+
+.. versionchanged:: 5.2
+
+ The :meth:`.HttpRequest.get_preferred_type` method was added.