diff options
| author | django-bot <ops@djangoproject.com> | 2023-03-01 13:35:43 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-03-01 13:39:03 +0100 |
| commit | 62510f01e76ad0526c94ea6d1bc6399c1ddf3df4 (patch) | |
| tree | 79844be246eba809a4ca09c6f4c3448f2276321a /docs/topics/http | |
| parent | 32f224e359c68e70e3f9a230be0265dcd6677079 (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.txt | 1 | ||||
| -rw-r--r-- | docs/topics/http/file-uploads.txt | 59 | ||||
| -rw-r--r-- | docs/topics/http/middleware.txt | 18 | ||||
| -rw-r--r-- | docs/topics/http/sessions.txt | 45 | ||||
| -rw-r--r-- | docs/topics/http/shortcuts.txt | 40 | ||||
| -rw-r--r-- | docs/topics/http/urls.txt | 147 | ||||
| -rw-r--r-- | docs/topics/http/views.txt | 32 |
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 |
