mirror of https://github.com/django/django.git
Refs #30997 -- Removed HttpRequest.is_ajax() usage.
This commit is contained in:
parent
5d654e1e71
commit
7fa0fa45c5
|
@ -48,12 +48,12 @@ def technical_500_response(request, exc_type, exc_value, tb, status_code=500):
|
|||
the values returned from sys.exc_info() and friends.
|
||||
"""
|
||||
reporter = get_exception_reporter_class(request)(request, exc_type, exc_value, tb)
|
||||
if request.is_ajax():
|
||||
text = reporter.get_traceback_text()
|
||||
return HttpResponse(text, status=status_code, content_type='text/plain; charset=utf-8')
|
||||
else:
|
||||
if request.accepts('text/html'):
|
||||
html = reporter.get_traceback_html()
|
||||
return HttpResponse(html, status=status_code, content_type='text/html')
|
||||
else:
|
||||
text = reporter.get_traceback_text()
|
||||
return HttpResponse(text, status=status_code, content_type='text/plain; charset=utf-8')
|
||||
|
||||
|
||||
@functools.lru_cache()
|
||||
|
|
|
@ -33,7 +33,7 @@ def set_language(request):
|
|||
"""
|
||||
next_url = request.POST.get('next', request.GET.get('next'))
|
||||
if (
|
||||
(next_url or not request.is_ajax()) and
|
||||
(next_url or request.accepts('text/html')) and
|
||||
not url_has_allowed_host_and_scheme(
|
||||
url=next_url,
|
||||
allowed_hosts={request.get_host()},
|
||||
|
|
|
@ -388,6 +388,11 @@ Miscellaneous
|
|||
Django 3.1, the first request to any previously cached template fragment will
|
||||
be a cache miss.
|
||||
|
||||
* The logic behind the decision to return a redirection fallback or a 204 HTTP
|
||||
response from the :func:`~django.views.i18n.set_language` view is now based
|
||||
on the ``Accept`` HTTP header instead of the ``X-Requested-With`` HTTP header
|
||||
presence.
|
||||
|
||||
* The compatibility imports of ``django.core.exceptions.EmptyResultSet`` in
|
||||
``django.db.models.query``, ``django.db.models.sql``, and
|
||||
``django.db.models.sql.datastructures`` are removed.
|
||||
|
|
|
@ -1803,9 +1803,18 @@ redirect to that URL will be performed. Otherwise, Django may fall back to
|
|||
redirecting the user to the URL from the ``Referer`` header or, if it is not
|
||||
set, to ``/``, depending on the nature of the request:
|
||||
|
||||
* For AJAX requests, the fallback will be performed only if the ``next``
|
||||
parameter was set. Otherwise a 204 status code (No Content) will be returned.
|
||||
* For non-AJAX requests, the fallback will always be performed.
|
||||
* If the request accepts HTML content (based on its ``Accept`` HTTP header),
|
||||
the fallback will always be performed.
|
||||
|
||||
* If the request doesn't accept HTML, the fallback will be performed only if
|
||||
the ``next`` parameter was set. Otherwise a 204 status code (No Content) will
|
||||
be returned.
|
||||
|
||||
.. versionchanged:: 3.1
|
||||
|
||||
In older versions, the distinction for the fallback is based on whether the
|
||||
``X-Requested-With`` header is set to the value ``XMLHttpRequest``. This is
|
||||
set by the jQuery ``ajax()`` method.
|
||||
|
||||
Here's example HTML template code:
|
||||
|
||||
|
|
|
@ -159,11 +159,11 @@ Use the ``django.test.Client`` class to make requests.
|
|||
|
||||
>>> c = Client()
|
||||
>>> c.get('/customers/details/', {'name': 'fred', 'age': 7},
|
||||
... HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
... HTTP_ACCEPT='application/json')
|
||||
|
||||
...will send the HTTP header ``HTTP_X_REQUESTED_WITH`` to the
|
||||
details view, which is a good way to test code paths that use the
|
||||
:meth:`django.http.HttpRequest.is_ajax()` method.
|
||||
...will send the HTTP header ``HTTP_ACCEPT`` to the details view, which
|
||||
is a good way to test code paths that use the
|
||||
:meth:`django.http.HttpRequest.accepts()` method.
|
||||
|
||||
.. admonition:: CGI specification
|
||||
|
||||
|
|
|
@ -1247,7 +1247,7 @@ class ExceptionReporterFilterTests(ExceptionReportTestMixin, LoggingCaptureMixin
|
|||
response = self.client.get(
|
||||
'/raises500/',
|
||||
HTTP_SECRET_HEADER='super_secret',
|
||||
HTTP_X_REQUESTED_WITH='XMLHttpRequest',
|
||||
HTTP_ACCEPT='application/json',
|
||||
)
|
||||
self.assertNotIn(b'super_secret', response.content)
|
||||
|
||||
|
@ -1289,17 +1289,17 @@ class CustomExceptionReporterFilterTests(SimpleTestCase):
|
|||
)
|
||||
|
||||
|
||||
class AjaxResponseExceptionReporterFilter(ExceptionReportTestMixin, LoggingCaptureMixin, SimpleTestCase):
|
||||
class NonHTMLResponseExceptionReporterFilter(ExceptionReportTestMixin, LoggingCaptureMixin, SimpleTestCase):
|
||||
"""
|
||||
Sensitive information can be filtered out of error reports.
|
||||
|
||||
Here we specifically test the plain text 500 debug-only error page served
|
||||
when it has been detected the request was sent by JS code. We don't check
|
||||
for (non)existence of frames vars in the traceback information section of
|
||||
the response content because we don't include them in these error pages.
|
||||
The plain text 500 debug-only error page is served when it has been
|
||||
detected the request doesn't accept HTML content. Don't check for
|
||||
(non)existence of frames vars in the traceback information section of the
|
||||
response content because they're not included in these error pages.
|
||||
Refs #14614.
|
||||
"""
|
||||
rf = RequestFactory(HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
rf = RequestFactory(HTTP_ACCEPT='application/json')
|
||||
|
||||
def test_non_sensitive_request(self):
|
||||
"""
|
||||
|
@ -1346,8 +1346,8 @@ class AjaxResponseExceptionReporterFilter(ExceptionReportTestMixin, LoggingCaptu
|
|||
self.verify_unsafe_response(custom_exception_reporter_filter_view, check_for_vars=False)
|
||||
|
||||
@override_settings(DEBUG=True, ROOT_URLCONF='view_tests.urls')
|
||||
def test_ajax_response_encoding(self):
|
||||
response = self.client.get('/raises500/', HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
def test_non_html_response_encoding(self):
|
||||
response = self.client.get('/raises500/', HTTP_ACCEPT='application/json')
|
||||
self.assertEqual(response['Content-Type'], 'text/plain; charset=utf-8')
|
||||
|
||||
|
||||
|
|
|
@ -111,11 +111,12 @@ class SetLanguageTests(TestCase):
|
|||
|
||||
def test_setlang_performs_redirect_for_ajax_if_explicitly_requested(self):
|
||||
"""
|
||||
The set_language view redirects to the "next" parameter for AJAX calls.
|
||||
The set_language view redirects to the "next" parameter for requests
|
||||
not accepting HTML response content.
|
||||
"""
|
||||
lang_code = self._get_inactive_language_code()
|
||||
post_data = {'language': lang_code, 'next': '/'}
|
||||
response = self.client.post('/i18n/setlang/', post_data, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
response = self.client.post('/i18n/setlang/', post_data, HTTP_ACCEPT='application/json')
|
||||
self.assertRedirects(response, '/')
|
||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
||||
with ignore_warnings(category=RemovedInDjango40Warning):
|
||||
|
@ -123,12 +124,12 @@ class SetLanguageTests(TestCase):
|
|||
|
||||
def test_setlang_doesnt_perform_a_redirect_to_referer_for_ajax(self):
|
||||
"""
|
||||
The set_language view doesn't redirect to the HTTP referer header for
|
||||
AJAX calls.
|
||||
The set_language view doesn't redirect to the HTTP referer header if
|
||||
the request doesn't accept HTML response content.
|
||||
"""
|
||||
lang_code = self._get_inactive_language_code()
|
||||
post_data = {'language': lang_code}
|
||||
headers = {'HTTP_REFERER': '/', 'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'}
|
||||
headers = {'HTTP_REFERER': '/', 'HTTP_ACCEPT': 'application/json'}
|
||||
response = self.client.post('/i18n/setlang/', post_data, **headers)
|
||||
self.assertEqual(response.status_code, 204)
|
||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
||||
|
@ -137,11 +138,12 @@ class SetLanguageTests(TestCase):
|
|||
|
||||
def test_setlang_doesnt_perform_a_default_redirect_for_ajax(self):
|
||||
"""
|
||||
The set_language view returns 204 for AJAX calls by default.
|
||||
The set_language view returns 204 by default for requests not accepting
|
||||
HTML response content.
|
||||
"""
|
||||
lang_code = self._get_inactive_language_code()
|
||||
post_data = {'language': lang_code}
|
||||
response = self.client.post('/i18n/setlang/', post_data, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
response = self.client.post('/i18n/setlang/', post_data, HTTP_ACCEPT='application/json')
|
||||
self.assertEqual(response.status_code, 204)
|
||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
||||
with ignore_warnings(category=RemovedInDjango40Warning):
|
||||
|
@ -149,11 +151,12 @@ class SetLanguageTests(TestCase):
|
|||
|
||||
def test_setlang_unsafe_next_for_ajax(self):
|
||||
"""
|
||||
The fallback to root URL for the set_language view works for AJAX calls.
|
||||
The fallback to root URL for the set_language view works for requests
|
||||
not accepting HTML response content.
|
||||
"""
|
||||
lang_code = self._get_inactive_language_code()
|
||||
post_data = {'language': lang_code, 'next': '//unsafe/redirection/'}
|
||||
response = self.client.post('/i18n/setlang/', post_data, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
response = self.client.post('/i18n/setlang/', post_data, HTTP_ACCEPT='application/json')
|
||||
self.assertEqual(response.url, '/')
|
||||
self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, lang_code)
|
||||
|
||||
|
|
Loading…
Reference in New Issue