summaryrefslogtreecommitdiff
path: root/docs/topics/http
diff options
context:
space:
mode:
authordjango-bot <ops@djangoproject.com>2023-03-01 13:35:43 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-03-01 13:39:03 +0100
commit62510f01e76ad0526c94ea6d1bc6399c1ddf3df4 (patch)
tree79844be246eba809a4ca09c6f4c3448f2276321a /docs/topics/http
parent32f224e359c68e70e3f9a230be0265dcd6677079 (diff)
[4.2.x] Fixed #34140 -- Reformatted code blocks in docs with blacken-docs.
Diffstat (limited to 'docs/topics/http')
-rw-r--r--docs/topics/http/decorators.txt1
-rw-r--r--docs/topics/http/file-uploads.txt59
-rw-r--r--docs/topics/http/middleware.txt18
-rw-r--r--docs/topics/http/sessions.txt45
-rw-r--r--docs/topics/http/shortcuts.txt40
-rw-r--r--docs/topics/http/urls.txt147
-rw-r--r--docs/topics/http/views.txt32
7 files changed, 196 insertions, 146 deletions
diff --git a/docs/topics/http/decorators.txt b/docs/topics/http/decorators.txt
index 5165765eea..3481eefb3c 100644
--- a/docs/topics/http/decorators.txt
+++ b/docs/topics/http/decorators.txt
@@ -24,6 +24,7 @@ a :class:`django.http.HttpResponseNotAllowed` if the conditions are not met.
from django.views.decorators.http import require_http_methods
+
@require_http_methods(["GET", "POST"])
def my_view(request):
# I can assume now that only GET or POST requests make it this far
diff --git a/docs/topics/http/file-uploads.txt b/docs/topics/http/file-uploads.txt
index 94b74321fa..7bd071d6c9 100644
--- a/docs/topics/http/file-uploads.txt
+++ b/docs/topics/http/file-uploads.txt
@@ -26,6 +26,7 @@ Consider a form containing a :class:`~django.forms.FileField`:
from django import forms
+
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50)
file = forms.FileField()
@@ -55,15 +56,16 @@ described in :ref:`binding-uploaded-files`. This would look something like:
# Imaginary function to handle an uploaded file.
from somewhere import handle_uploaded_file
+
def upload_file(request):
- if request.method == 'POST':
+ if request.method == "POST":
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
- handle_uploaded_file(request.FILES['file'])
- return HttpResponseRedirect('/success/url/')
+ handle_uploaded_file(request.FILES["file"])
+ return HttpResponseRedirect("/success/url/")
else:
form = UploadFileForm()
- return render(request, 'upload.html', {'form': form})
+ return render(request, "upload.html", {"form": form})
Notice that we have to pass :attr:`request.FILES <django.http.HttpRequest.FILES>`
into the form's constructor; this is how file data gets bound into a form.
@@ -71,7 +73,7 @@ into the form's constructor; this is how file data gets bound into a form.
Here's a common way you might handle an uploaded file::
def handle_uploaded_file(f):
- with open('some/file/name.txt', 'wb+') as destination:
+ with open("some/file/name.txt", "wb+") as destination:
for chunk in f.chunks():
destination.write(chunk)
@@ -95,16 +97,17 @@ corresponding :class:`~django.db.models.FileField` when calling
from django.shortcuts import render
from .forms import ModelFormWithFileField
+
def upload_file(request):
- if request.method == 'POST':
+ if request.method == "POST":
form = ModelFormWithFileField(request.POST, request.FILES)
if form.is_valid():
# file is saved
form.save()
- return HttpResponseRedirect('/success/url/')
+ return HttpResponseRedirect("/success/url/")
else:
form = ModelFormWithFileField()
- return render(request, 'upload.html', {'form': form})
+ return render(request, "upload.html", {"form": form})
If you are constructing an object manually, you can assign the file object from
:attr:`request.FILES <django.http.HttpRequest.FILES>` to the file field in the
@@ -115,16 +118,17 @@ model::
from .forms import UploadFileForm
from .models import ModelWithFileField
+
def upload_file(request):
- if request.method == 'POST':
+ if request.method == "POST":
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
- instance = ModelWithFileField(file_field=request.FILES['file'])
+ instance = ModelWithFileField(file_field=request.FILES["file"])
instance.save()
- return HttpResponseRedirect('/success/url/')
+ return HttpResponseRedirect("/success/url/")
else:
form = UploadFileForm()
- return render(request, 'upload.html', {'form': form})
+ return render(request, "upload.html", {"form": form})
If you are constructing an object manually outside of a request, you can assign
a :class:`~django.core.files.File` like object to the
@@ -133,9 +137,10 @@ a :class:`~django.core.files.File` like object to the
from django.core.management.base import BaseCommand
from django.core.files.base import ContentFile
+
class MyCommand(BaseCommand):
def handle(self, *args, **options):
- content_file = ContentFile(b'Hello world!', name='hello-world.txt')
+ content_file = ContentFile(b"Hello world!", name="hello-world.txt")
instance = ModelWithFileField(file_field=content_file)
instance.save()
@@ -150,8 +155,11 @@ HTML attribute of field's widget:
from django import forms
+
class FileFieldForm(forms.Form):
- file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
+ file_field = forms.FileField(
+ widget=forms.ClearableFileInput(attrs={"multiple": True})
+ )
Then override the ``post`` method of your
:class:`~django.views.generic.edit.FormView` subclass to handle multiple file
@@ -163,15 +171,16 @@ uploads:
from django.views.generic.edit import FormView
from .forms import FileFieldForm
+
class FileFieldFormView(FormView):
form_class = FileFieldForm
- template_name = 'upload.html' # Replace with your template.
- success_url = '...' # Replace with your URL or reverse().
+ template_name = "upload.html" # Replace with your template.
+ success_url = "..." # Replace with your URL or reverse().
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
- files = request.FILES.getlist('file_field')
+ files = request.FILES.getlist("file_field")
if form.is_valid():
for f in files:
... # Do something with each file.
@@ -189,8 +198,10 @@ handler* -- a small class that handles file data as it gets uploaded. Upload
handlers are initially defined in the :setting:`FILE_UPLOAD_HANDLERS` setting,
which defaults to::
- ["django.core.files.uploadhandler.MemoryFileUploadHandler",
- "django.core.files.uploadhandler.TemporaryFileUploadHandler"]
+ [
+ "django.core.files.uploadhandler.MemoryFileUploadHandler",
+ "django.core.files.uploadhandler.TemporaryFileUploadHandler",
+ ]
Together :class:`MemoryFileUploadHandler` and
:class:`TemporaryFileUploadHandler` provide Django's default file upload
@@ -276,14 +287,16 @@ list::
from django.views.decorators.csrf import csrf_exempt, csrf_protect
+
@csrf_exempt
def upload_file_view(request):
request.upload_handlers.insert(0, ProgressBarUploadHandler(request))
return _upload_file_view(request)
+
@csrf_protect
def _upload_file_view(request):
- ... # Process request
+ ... # Process request
If you are using a class-based view, you will need to use
:func:`~django.views.decorators.csrf.csrf_exempt` on its
@@ -295,13 +308,13 @@ list::
from django.views import View
from django.views.decorators.csrf import csrf_exempt, csrf_protect
- @method_decorator(csrf_exempt, name='dispatch')
- class UploadFileView(View):
+ @method_decorator(csrf_exempt, name="dispatch")
+ class UploadFileView(View):
def setup(self, request, *args, **kwargs):
request.upload_handlers.insert(0, ProgressBarUploadHandler(request))
super().setup(request, *args, **kwargs)
@method_decorator(csrf_protect)
def post(self, request, *args, **kwargs):
- ... # Process request
+ ... # Process request
diff --git a/docs/topics/http/middleware.txt b/docs/topics/http/middleware.txt
index 9a20106618..9b4bd12a7b 100644
--- a/docs/topics/http/middleware.txt
+++ b/docs/topics/http/middleware.txt
@@ -111,13 +111,13 @@ example, here's the default value created by :djadmin:`django-admin
startproject <startproject>`::
MIDDLEWARE = [
- 'django.middleware.security.SecurityMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+ "django.middleware.security.SecurityMiddleware",
+ "django.contrib.sessions.middleware.SessionMiddleware",
+ "django.middleware.common.CommonMiddleware",
+ "django.middleware.csrf.CsrfViewMiddleware",
+ "django.contrib.auth.middleware.AuthenticationMiddleware",
+ "django.contrib.messages.middleware.MessageMiddleware",
+ "django.middleware.clickjacking.XFrameOptionsMiddleware",
]
A Django installation doesn't require any middleware — :setting:`MIDDLEWARE`
@@ -344,16 +344,19 @@ Here's an example of how to create a middleware function that supports both::
from asgiref.sync import iscoroutinefunction
from django.utils.decorators import sync_and_async_middleware
+
@sync_and_async_middleware
def simple_middleware(get_response):
# One-time configuration and initialization goes here.
if iscoroutinefunction(get_response):
+
async def middleware(request):
# Do something here!
response = await get_response(request)
return response
else:
+
def middleware(request):
# Do something here!
response = get_response(request)
@@ -376,6 +379,7 @@ instances are correctly marked as coroutine functions::
from asgiref.sync import iscoroutinefunction, markcoroutinefunction
+
class AsyncMiddleware:
async_capable = True
sync_capable = False
diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt
index cfc22bee52..4961d6c205 100644
--- a/docs/topics/http/sessions.txt
+++ b/docs/topics/http/sessions.txt
@@ -362,11 +362,11 @@ Bundled serializers
.. code-block:: pycon
>>> # initial assignment
- >>> request.session[0] = 'bar'
+ >>> request.session[0] = "bar"
>>> # subsequent requests following serialization & deserialization
>>> # of session data
>>> request.session[0] # KeyError
- >>> request.session['0']
+ >>> request.session["0"]
'bar'
Similarly, data that can't be encoded in JSON, such as non-UTF8 bytes like
@@ -427,19 +427,19 @@ This simplistic view sets a ``has_commented`` variable to ``True`` after a user
posts a comment. It doesn't let a user post a comment more than once::
def post_comment(request, new_comment):
- if request.session.get('has_commented', False):
+ if request.session.get("has_commented", False):
return HttpResponse("You've already commented.")
c = comments.Comment(comment=new_comment)
c.save()
- request.session['has_commented'] = True
- return HttpResponse('Thanks for your comment!')
+ request.session["has_commented"] = True
+ return HttpResponse("Thanks for your comment!")
This simplistic view logs in a "member" of the site::
def login(request):
- m = Member.objects.get(username=request.POST['username'])
- if m.check_password(request.POST['password']):
- request.session['member_id'] = m.id
+ m = Member.objects.get(username=request.POST["username"])
+ if m.check_password(request.POST["password"]):
+ request.session["member_id"] = m.id
return HttpResponse("You're logged in.")
else:
return HttpResponse("Your username and password didn't match.")
@@ -448,7 +448,7 @@ This simplistic view logs in a "member" of the site::
def logout(request):
try:
- del request.session['member_id']
+ del request.session["member_id"]
except KeyError:
pass
return HttpResponse("You're logged out.")
@@ -481,15 +481,16 @@ Here's a typical usage example::
from django.http import HttpResponse
from django.shortcuts import render
+
def login(request):
- if request.method == 'POST':
+ if request.method == "POST":
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return HttpResponse("You're logged in.")
else:
return HttpResponse("Please enable cookies and try again.")
request.session.set_test_cookie()
- return render(request, 'foo/login_form.html')
+ return render(request, "foo/login_form.html")
Using sessions out of views
===========================
@@ -514,12 +515,12 @@ An API is available to manipulate session data outside of a view:
>>> from django.contrib.sessions.backends.db import SessionStore
>>> s = SessionStore()
>>> # stored as seconds since epoch since datetimes are not serializable in JSON.
- >>> s['last_login'] = 1376587691
+ >>> s["last_login"] = 1376587691
>>> s.create()
>>> s.session_key
'2b1189a188b44ad18c35e113ac6ceead'
- >>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead')
- >>> s['last_login']
+ >>> s = SessionStore(session_key="2b1189a188b44ad18c35e113ac6ceead")
+ >>> s["last_login"]
1376587691
``SessionStore.create()`` is designed to create a new session (i.e. one not
@@ -537,7 +538,7 @@ access sessions using the normal Django database API:
.. code-block:: pycon
>>> from django.contrib.sessions.models import Session
- >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
+ >>> s = Session.objects.get(pk="2b1189a188b44ad18c35e113ac6ceead")
>>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)
@@ -561,17 +562,17 @@ modified -- that is if any of its dictionary values have been assigned or
deleted::
# Session is modified.
- request.session['foo'] = 'bar'
+ request.session["foo"] = "bar"
# Session is modified.
- del request.session['foo']
+ del request.session["foo"]
# Session is modified.
- request.session['foo'] = {}
+ request.session["foo"] = {}
# Gotcha: Session is NOT modified, because this alters
# request.session['foo'] instead of request.session.
- request.session['foo']['bar'] = 'baz'
+ request.session["foo"]["bar"] = "baz"
In the last case of the above example, we can tell the session object
explicitly that it has been modified by setting the ``modified`` attribute on
@@ -829,6 +830,7 @@ to query the database for all active sessions for an account)::
from django.contrib.sessions.base_session import AbstractBaseSession
from django.db import models
+
class CustomSession(AbstractBaseSession):
account_id = models.IntegerField(null=True, db_index=True)
@@ -836,6 +838,7 @@ to query the database for all active sessions for an account)::
def get_session_store_class(cls):
return SessionStore
+
class SessionStore(DBStore):
@classmethod
def get_model_class(cls):
@@ -844,7 +847,7 @@ to query the database for all active sessions for an account)::
def create_model_instance(self, data):
obj = super().create_model_instance(data)
try:
- account_id = int(data.get('_auth_user_id'))
+ account_id = int(data.get("_auth_user_id"))
except (ValueError, TypeError):
account_id = None
obj.account_id = account_id
@@ -855,7 +858,7 @@ a custom one based on ``cached_db``, you should override the cache key prefix
in order to prevent a namespace clash::
class SessionStore(CachedDBStore):
- cache_key_prefix = 'mysessions.custom_cached_db_backend'
+ cache_key_prefix = "mysessions.custom_cached_db_backend"
# ...
diff --git a/docs/topics/http/shortcuts.txt b/docs/topics/http/shortcuts.txt
index b28533147b..f3cbd151aa 100644
--- a/docs/topics/http/shortcuts.txt
+++ b/docs/topics/http/shortcuts.txt
@@ -64,22 +64,29 @@ MIME type :mimetype:`application/xhtml+xml`::
from django.shortcuts import render
+
def my_view(request):
# View code here...
- return render(request, 'myapp/index.html', {
- 'foo': 'bar',
- }, content_type='application/xhtml+xml')
+ return render(
+ request,
+ "myapp/index.html",
+ {
+ "foo": "bar",
+ },
+ content_type="application/xhtml+xml",
+ )
This example is equivalent to::
from django.http import HttpResponse
from django.template import loader
+
def my_view(request):
# View code here...
- t = loader.get_template('myapp/index.html')
- c = {'foo': 'bar'}
- return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')
+ t = loader.get_template("myapp/index.html")
+ c = {"foo": "bar"}
+ return HttpResponse(t.render(c, request), content_type="application/xhtml+xml")
``redirect()``
==============
@@ -114,6 +121,7 @@ You can use the :func:`redirect` function in a number of ways.
from django.shortcuts import redirect
+
def my_view(request):
...
obj = MyModel.objects.get(...)
@@ -125,21 +133,21 @@ You can use the :func:`redirect` function in a number of ways.
def my_view(request):
...
- return redirect('some-view-name', foo='bar')
+ return redirect("some-view-name", foo="bar")
#. By passing a hardcoded URL to redirect to:
::
def my_view(request):
...
- return redirect('/some/url/')
+ return redirect("/some/url/")
This also works with full URLs:
::
def my_view(request):
...
- return redirect('https://example.com/')
+ return redirect("https://example.com/")
By default, :func:`redirect` returns a temporary redirect. All of the above
forms accept a ``permanent`` argument; if set to ``True`` a permanent redirect
@@ -183,6 +191,7 @@ The following example gets the object with the primary key of 1 from
from django.shortcuts import get_object_or_404
+
def my_view(request):
obj = get_object_or_404(MyModel, pk=1)
@@ -190,6 +199,7 @@ This example is equivalent to::
from django.http import Http404
+
def my_view(request):
try:
obj = MyModel.objects.get(pk=1)
@@ -200,12 +210,12 @@ The most common use case is to pass a :class:`~django.db.models.Model`, as
shown above. However, you can also pass a
:class:`~django.db.models.query.QuerySet` instance::
- queryset = Book.objects.filter(title__startswith='M')
+ queryset = Book.objects.filter(title__startswith="M")
get_object_or_404(queryset, pk=1)
The above example is a bit contrived since it's equivalent to doing::
- get_object_or_404(Book, title__startswith='M', pk=1)
+ get_object_or_404(Book, title__startswith="M", pk=1)
but it can be useful if you are passed the ``queryset`` variable from somewhere
else.
@@ -214,13 +224,13 @@ Finally, you can also use a :class:`~django.db.models.Manager`. This is useful
for example if you have a
:ref:`custom manager<custom-managers>`::
- get_object_or_404(Book.dahl_objects, title='Matilda')
+ get_object_or_404(Book.dahl_objects, title="Matilda")
You can also use
:class:`related managers<django.db.models.fields.related.RelatedManager>`::
- author = Author.objects.get(name='Roald Dahl')
- get_object_or_404(author.book_set, title='Matilda')
+ author = Author.objects.get(name="Roald Dahl")
+ get_object_or_404(author.book_set, title="Matilda")
Note: As with ``get()``, a
:class:`~django.core.exceptions.MultipleObjectsReturned` exception
@@ -257,6 +267,7 @@ The following example gets all published objects from ``MyModel``::
from django.shortcuts import get_list_or_404
+
def my_view(request):
my_objects = get_list_or_404(MyModel, published=True)
@@ -264,6 +275,7 @@ This example is equivalent to::
from django.http import Http404
+
def my_view(request):
my_objects = list(MyModel.objects.filter(published=True))
if not my_objects:
diff --git a/docs/topics/http/urls.txt b/docs/topics/http/urls.txt
index 2734882f72..d8de9635ec 100644
--- a/docs/topics/http/urls.txt
+++ b/docs/topics/http/urls.txt
@@ -75,10 +75,10 @@ Here's a sample URLconf::
from . import views
urlpatterns = [
- path('articles/2003/', views.special_case_2003),
- path('articles/<int:year>/', views.year_archive),
- path('articles/<int:year>/<int:month>/', views.month_archive),
- path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
+ path("articles/2003/", views.special_case_2003),
+ path("articles/<int:year>/", views.year_archive),
+ path("articles/<int:year>/<int:month>/", views.month_archive),
+ path("articles/<int:year>/<int:month>/<slug:slug>/", views.article_detail),
]
Notes:
@@ -160,13 +160,13 @@ A converter is a class that includes the following:
For example::
class FourDigitYearConverter:
- regex = '[0-9]{4}'
+ regex = "[0-9]{4}"
def to_python(self, value):
return int(value)
def to_url(self, value):
- return '%04d' % value
+ return "%04d" % value
Register custom converter classes in your URLconf using
:func:`~django.urls.register_converter`::
@@ -175,12 +175,12 @@ Register custom converter classes in your URLconf using
from . import converters, views
- register_converter(converters.FourDigitYearConverter, 'yyyy')
+ register_converter(converters.FourDigitYearConverter, "yyyy")
urlpatterns = [
- path('articles/2003/', views.special_case_2003),
- path('articles/<yyyy:year>/', views.year_archive),
- ...
+ path("articles/2003/", views.special_case_2003),
+ path("articles/<yyyy:year>/", views.year_archive),
+ ...,
]
Using regular expressions
@@ -201,10 +201,13 @@ Here's the example URLconf from earlier, rewritten using regular expressions::
from . import views
urlpatterns = [
- path('articles/2003/', views.special_case_2003),
- re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
- re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
- re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),
+ path("articles/2003/", views.special_case_2003),
+ re_path(r"^articles/(?P<year>[0-9]{4})/$", views.year_archive),
+ re_path(r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.month_archive),
+ re_path(
+ r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$",
+ views.article_detail,
+ ),
]
This accomplishes roughly the same thing as the previous example, except:
@@ -246,8 +249,8 @@ following URL patterns which optionally take a page argument::
from django.urls import re_path
urlpatterns = [
- re_path(r'^blog/(page-([0-9]+)/)?$', blog_articles), # bad
- re_path(r'^comments/(?:page-(?P<page_number>[0-9]+)/)?$', comments), # good
+ re_path(r"^blog/(page-([0-9]+)/)?$", blog_articles), # bad
+ re_path(r"^comments/(?:page-(?P<page_number>[0-9]+)/)?$", comments), # good
]
Both patterns use nested arguments and will resolve: for example,
@@ -299,10 +302,11 @@ Here's an example URLconf and view::
from . import views
urlpatterns = [
- path('blog/', views.page),
- path('blog/page<int:num>/', views.page),
+ path("blog/", views.page),
+ path("blog/page<int:num>/", views.page),
]
+
# View (in blog/views.py)
def page(request, num=1):
# Output the appropriate page of blog entries, according to num.
@@ -368,8 +372,8 @@ itself. It includes a number of other URLconfs::
urlpatterns = [
# ... snip ...
- path('community/', include('aggregator.urls')),
- path('contact/', include('contact.urls')),
+ path("community/", include("aggregator.urls")),
+ path("contact/", include("contact.urls")),
# ... snip ...
]
@@ -386,15 +390,15 @@ Another possibility is to include additional URL patterns by using a list of
from credit import views as credit_views
extra_patterns = [
- path('reports/', credit_views.report),
- path('reports/<int:id>/', credit_views.report),
- path('charge/', credit_views.charge),
+ path("reports/", credit_views.report),
+ path("reports/<int:id>/", credit_views.report),
+ path("charge/", credit_views.charge),
]
urlpatterns = [
- path('', main_views.homepage),
- path('help/', include('apps.help.urls')),
- path('credit/', include(extra_patterns)),
+ path("", main_views.homepage),
+ path("help/", include("apps.help.urls")),
+ path("credit/", include(extra_patterns)),
]
In this example, the ``/credit/reports/`` URL will be handled by the
@@ -407,10 +411,10 @@ prefix is used repeatedly. For example, consider this URLconf::
from . import views
urlpatterns = [
- path('<page_slug>-<page_id>/history/', views.history),
- path('<page_slug>-<page_id>/edit/', views.edit),
- path('<page_slug>-<page_id>/discuss/', views.discuss),
- path('<page_slug>-<page_id>/permissions/', views.permissions),
+ path("<page_slug>-<page_id>/history/", views.history),
+ path("<page_slug>-<page_id>/edit/", views.edit),
+ path("<page_slug>-<page_id>/discuss/", views.discuss),
+ path("<page_slug>-<page_id>/permissions/", views.permissions),
]
We can improve this by stating the common path prefix only once and grouping
@@ -420,12 +424,17 @@ the suffixes that differ::
from . import views
urlpatterns = [
- path('<page_slug>-<page_id>/', include([
- path('history/', views.history),
- path('edit/', views.edit),
- path('discuss/', views.discuss),
- path('permissions/', views.permissions),
- ])),
+ path(
+ "<page_slug>-<page_id>/",
+ include(
+ [
+ path("history/", views.history),
+ path("edit/", views.edit),
+ path("discuss/", views.discuss),
+ path("permissions/", views.permissions),
+ ]
+ ),
+ ),
]
.. _`Django website`: https://www.djangoproject.com/
@@ -440,7 +449,7 @@ the following example is valid::
from django.urls import include, path
urlpatterns = [
- path('<username>/blog/', include('foo.urls.blog')),
+ path("<username>/blog/", include("foo.urls.blog")),
]
# In foo/urls/blog.py
@@ -448,8 +457,8 @@ the following example is valid::
from . import views
urlpatterns = [
- path('', views.blog.index),
- path('archive/', views.blog.archive),
+ path("", views.blog.index),
+ path("archive/", views.blog.archive),
]
In the above example, the captured ``"username"`` variable is passed to the
@@ -473,7 +482,7 @@ For example::
from . import views
urlpatterns = [
- path('blog/<int:year>/', views.year_archive, {'foo': 'bar'}),
+ path("blog/<int:year>/", views.year_archive, {"foo": "bar"}),
]
In this example, for a request to ``/blog/2005/``, Django will call
@@ -504,7 +513,7 @@ Set one::
from django.urls import include, path
urlpatterns = [
- path('blog/', include('inner'), {'blog_id': 3}),
+ path("blog/", include("inner"), {"blog_id": 3}),
]
# inner.py
@@ -512,8 +521,8 @@ Set one::
from mysite import views
urlpatterns = [
- path('archive/', views.archive),
- path('about/', views.about),
+ path("archive/", views.archive),
+ path("about/", views.about),
]
Set two::
@@ -523,15 +532,15 @@ Set two::
from mysite import views
urlpatterns = [
- path('blog/', include('inner')),
+ path("blog/", include("inner")),
]
# inner.py
from django.urls import path
urlpatterns = [
- path('archive/', views.archive, {'blog_id': 3}),
- path('about/', views.about, {'blog_id': 3}),
+ path("archive/", views.archive, {"blog_id": 3}),
+ path("about/", views.about, {"blog_id": 3}),
]
Note that extra options will *always* be passed to *every* line in the included
@@ -596,9 +605,9 @@ Consider again this URLconf entry::
from . import views
urlpatterns = [
- #...
- path('articles/<int:year>/', views.year_archive, name='news-year-archive'),
- #...
+ # ...
+ path("articles/<int:year>/", views.year_archive, name="news-year-archive"),
+ # ...
]
According to this design, the URL for the archive corresponding to year *nnnn*
@@ -621,11 +630,12 @@ Or in Python code::
from django.http import HttpResponseRedirect
from django.urls import reverse
+
def redirect_to_year(request):
# ...
year = 2006
# ...
- return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
+ return HttpResponseRedirect(reverse("news-year-archive", args=(year,)))
If, for some reason, it was decided that the URLs where content for yearly
article archives are published at should be changed then you would only need to
@@ -773,8 +783,8 @@ displaying polls.
from django.urls import include, path
urlpatterns = [
- path('author-polls/', include('polls.urls', namespace='author-polls')),
- path('publisher-polls/', include('polls.urls', namespace='publisher-polls')),
+ path("author-polls/", include("polls.urls", namespace="author-polls")),
+ path("publisher-polls/", include("polls.urls", namespace="publisher-polls")),
]
.. code-block:: python
@@ -784,11 +794,11 @@ displaying polls.
from . import views
- app_name = 'polls'
+ app_name = "polls"
urlpatterns = [
- path('', views.IndexView.as_view(), name='index'),
- path('<int:pk>/', views.DetailView.as_view(), name='detail'),
- ...
+ path("", views.IndexView.as_view(), name="index"),
+ path("<int:pk>/", views.DetailView.as_view(), name="detail"),
+ ...,
]
Using this setup, the following lookups are possible:
@@ -800,7 +810,7 @@ Using this setup, the following lookups are possible:
In the method of a class-based view::
- reverse('polls:index', current_app=self.request.resolver_match.namespace)
+ reverse("polls:index", current_app=self.request.resolver_match.namespace)
and in the template:
@@ -843,11 +853,11 @@ not the list of ``urlpatterns`` itself.
from . import views
- app_name = 'polls'
+ app_name = "polls"
urlpatterns = [
- path('', views.IndexView.as_view(), name='index'),
- path('<int:pk>/', views.DetailView.as_view(), name='detail'),
- ...
+ path("", views.IndexView.as_view(), name="index"),
+ path("<int:pk>/", views.DetailView.as_view(), name="detail"),
+ ...,
]
.. code-block:: python
@@ -856,7 +866,7 @@ not the list of ``urlpatterns`` itself.
from django.urls import include, path
urlpatterns = [
- path('polls/', include('polls.urls')),
+ path("polls/", include("polls.urls")),
]
The URLs defined in ``polls.urls`` will have an application namespace ``polls``.
@@ -877,13 +887,16 @@ For example::
from . import views
- polls_patterns = ([
- path('', views.IndexView.as_view(), name='index'),
- path('<int:pk>/', views.DetailView.as_view(), name='detail'),
- ], 'polls')
+ polls_patterns = (
+ [
+ path("", views.IndexView.as_view(), name="index"),
+ path("<int:pk>/", views.DetailView.as_view(), name="detail"),
+ ],
+ "polls",
+ )
urlpatterns = [
- path('polls/', include(polls_patterns)),
+ path("polls/", include(polls_patterns)),
]
This will include the nominated URL patterns into the given application
diff --git a/docs/topics/http/views.txt b/docs/topics/http/views.txt
index c1b6e93f34..2985bfb72b 100644
--- a/docs/topics/http/views.txt
+++ b/docs/topics/http/views.txt
@@ -20,6 +20,7 @@ Here's a view that returns the current date and time, as an HTML document::
from django.http import HttpResponse
import datetime
+
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
@@ -70,12 +71,13 @@ example::
from django.http import HttpResponse, HttpResponseNotFound
+
def my_view(request):
# ...
if foo:
- return HttpResponseNotFound('<h1>Page not found</h1>')
+ return HttpResponseNotFound("<h1>Page not found</h1>")
else:
- return HttpResponse('<h1>Page was found</h1>')
+ return HttpResponse("<h1>Page was found</h1>")
There isn't a specialized subclass for every possible HTTP response code,
since many of them aren't going to be that common. However, as documented in
@@ -85,6 +87,7 @@ to create a return class for any status code you like. For example::
from django.http import HttpResponse
+
def my_view(request):
# ...
@@ -102,7 +105,7 @@ The ``Http404`` exception
When you return an error such as :class:`~django.http.HttpResponseNotFound`,
you're responsible for defining the HTML of the resulting error page::
- return HttpResponseNotFound('<h1>Page not found</h1>')
+ return HttpResponseNotFound("<h1>Page not found</h1>")
For convenience, and because it's a good idea to have a consistent 404 error page
across your site, Django provides an ``Http404`` exception. If you raise
@@ -115,12 +118,13 @@ Example usage::
from django.shortcuts import render
from polls.models import Poll
+
def detail(request, poll_id):
try:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404("Poll does not exist")
- return render(request, 'polls/detail.html', {'poll': p})
+ return render(request, "polls/detail.html", {"poll": p})
In order to show customized HTML when Django returns a 404, you can create an
HTML template named ``404.html`` and place it in the top level of your
@@ -145,22 +149,22 @@ effect).
The :func:`~django.views.defaults.page_not_found` view is overridden by
:data:`~django.conf.urls.handler404`::
- handler404 = 'mysite.views.my_custom_page_not_found_view'
+ handler404 = "mysite.views.my_custom_page_not_found_view"
The :func:`~django.views.defaults.server_error` view is overridden by
:data:`~django.conf.urls.handler500`::
- handler500 = 'mysite.views.my_custom_error_view'
+ handler500 = "mysite.views.my_custom_error_view"
The :func:`~django.views.defaults.permission_denied` view is overridden by
:data:`~django.conf.urls.handler403`::
- handler403 = 'mysite.views.my_custom_permission_denied_view'
+ handler403 = "mysite.views.my_custom_permission_denied_view"
The :func:`~django.views.defaults.bad_request` view is overridden by
:data:`~django.conf.urls.handler400`::
- handler400 = 'mysite.views.my_custom_bad_request_view'
+ handler400 = "mysite.views.my_custom_bad_request_view"
.. seealso::
@@ -180,7 +184,7 @@ in a test view. For example::
def response_error_handler(request, exception=None):
- return HttpResponse('Error handler content', status=403)
+ return HttpResponse("Error handler content", status=403)
def permission_denied_view(request):
@@ -188,7 +192,7 @@ in a test view. For example::
urlpatterns = [
- path('403/', permission_denied_view),
+ path("403/", permission_denied_view),
]
handler403 = response_error_handler
@@ -197,11 +201,10 @@ in a test view. For example::
# ROOT_URLCONF must specify the module that contains handler403 = ...
@override_settings(ROOT_URLCONF=__name__)
class CustomErrorHandlerTests(SimpleTestCase):
-
def test_handler_renders_template_response(self):
- response = self.client.get('/403/')
+ response = self.client.get("/403/")
# Make assertions on the response here. For example:
- self.assertContains(response, 'Error handler content', status_code=403)
+ self.assertContains(response, "Error handler content", status_code=403)
.. _async-views:
@@ -219,9 +222,10 @@ Here's an example of an async view::
import datetime
from django.http import HttpResponse
+
async def current_datetime(request):
now = datetime.datetime.now()
- html = '<html><body>It is now %s.</body></html>' % now
+ html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
You can read more about Django's async support, and how to best use async