mirror of
https://github.com/django/django.git
synced 2025-09-26 12:09:19 +00:00
Refs #30997 -- Added HttpRequest.accepts().
This commit is contained in:
parent
cf493e5c81
commit
d66d72f956
5 changed files with 192 additions and 12 deletions
|
@ -406,6 +406,29 @@ Methods
|
|||
Returns ``True`` if the request is secure; that is, if it was made with
|
||||
HTTPS.
|
||||
|
||||
.. method:: HttpRequest.accepts(mime_type)
|
||||
|
||||
.. versionadded:: 3.1
|
||||
|
||||
Returns ``True`` if the request ``Accept`` header matches the ``mime_type``
|
||||
argument::
|
||||
|
||||
>>> request.accepts('text/html')
|
||||
True
|
||||
|
||||
Most browsers send ``Accept: */*`` by default, so this would return
|
||||
``True`` for all content types. Setting an explicit ``Accept`` header in
|
||||
API requests can be useful for returning a different content type for those
|
||||
consumers only. See :ref:`content-negotiation-example` of using
|
||||
``accepts()`` to return different content to API consumers.
|
||||
|
||||
If a response varies depending on the content of the ``Accept`` header and
|
||||
you are using some form of caching like Django's :mod:`cache middleware
|
||||
<django.middleware.cache>`, you should decorate the view with
|
||||
:func:`vary_on_headers('Accept')
|
||||
<django.views.decorators.vary.vary_on_headers>` so that the responses are
|
||||
properly cached.
|
||||
|
||||
.. method:: HttpRequest.is_ajax()
|
||||
|
||||
Returns ``True`` if the request was made via an ``XMLHttpRequest``, by
|
||||
|
|
|
@ -282,6 +282,9 @@ Requests and Responses
|
|||
now allow using ``samesite='None'`` (string) to explicitly state that the
|
||||
cookie is sent with all same-site and cross-site requests.
|
||||
|
||||
* The new :meth:`.HttpRequest.accepts` method returns whether the request
|
||||
accepts the given MIME type according to the ``Accept`` HTTP header.
|
||||
|
||||
Serialization
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -222,41 +222,43 @@ to edit, and override
|
|||
aren't logged in from accessing the form. If you omit that, you'll need to
|
||||
handle unauthorized users in :meth:`~.ModelFormMixin.form_valid()`.
|
||||
|
||||
AJAX example
|
||||
============
|
||||
.. _content-negotiation-example:
|
||||
|
||||
Content negotiation example
|
||||
===========================
|
||||
|
||||
Here is an example showing how you might go about implementing a form that
|
||||
works for AJAX requests as well as 'normal' form POSTs::
|
||||
works with an API-based workflow as well as 'normal' form POSTs::
|
||||
|
||||
from django.http import JsonResponse
|
||||
from django.views.generic.edit import CreateView
|
||||
from myapp.models import Author
|
||||
|
||||
class AjaxableResponseMixin:
|
||||
class JsonableResponseMixin:
|
||||
"""
|
||||
Mixin to add AJAX support to a form.
|
||||
Mixin to add JSON support to a form.
|
||||
Must be used with an object-based FormView (e.g. CreateView)
|
||||
"""
|
||||
def form_invalid(self, form):
|
||||
response = super().form_invalid(form)
|
||||
if self.request.is_ajax():
|
||||
return JsonResponse(form.errors, status=400)
|
||||
else:
|
||||
if self.request.accepts('text/html'):
|
||||
return response
|
||||
else:
|
||||
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)
|
||||
if self.request.is_ajax():
|
||||
if self.request.accepts('text/html'):
|
||||
return response
|
||||
else:
|
||||
data = {
|
||||
'pk': self.object.pk,
|
||||
}
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
return response
|
||||
|
||||
class AuthorCreate(AjaxableResponseMixin, CreateView):
|
||||
class AuthorCreate(JsonableResponseMixin, CreateView):
|
||||
model = Author
|
||||
fields = ['name']
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue