Browse Source

Fixed #34140 -- Reformatted code blocks in docs with blacken-docs.

django-bot 2 years ago
parent
commit
14459f80ee
100 changed files with 2617 additions and 2027 deletions
  1. 2 1
      docs/faq/models.txt
  2. 7 6
      docs/howto/auth-remote-user.txt
  3. 4 3
      docs/howto/csrf.txt
  4. 3 0
      docs/howto/custom-file-storage.txt
  5. 23 12
      docs/howto/custom-lookups.txt
  6. 15 11
      docs/howto/custom-management-commands.txt
  7. 27 20
      docs/howto/custom-model-fields.txt
  8. 23 25
      docs/howto/custom-template-backend.txt
  9. 57 39
      docs/howto/custom-template-tags.txt
  10. 1 0
      docs/howto/deployment/asgi/index.txt
  11. 6 4
      docs/howto/deployment/checklist.txt
  12. 2 1
      docs/howto/deployment/wsgi/apache-auth.txt
  13. 1 0
      docs/howto/deployment/wsgi/index.txt
  14. 18 14
      docs/howto/error-reporting.txt
  15. 3 2
      docs/howto/legacy-databases.txt
  16. 39 43
      docs/howto/logging.txt
  17. 16 11
      docs/howto/outputting-csv.txt
  18. 2 1
      docs/howto/outputting-pdf.txt
  19. 5 5
      docs/howto/overriding-templates.txt
  20. 2 2
      docs/howto/static-files/index.txt
  21. 51 45
      docs/howto/writing-migrations.txt
  22. 22 18
      docs/internals/contributing/writing-code/coding-style.txt
  23. 4 1
      docs/internals/contributing/writing-code/submitting-patches.txt
  24. 7 3
      docs/internals/contributing/writing-code/unit-tests.txt
  25. 1 1
      docs/internals/contributing/writing-documentation.txt
  26. 2 2
      docs/intro/contributing.txt
  27. 17 12
      docs/intro/overview.txt
  28. 2 2
      docs/intro/reusable-apps.txt
  29. 3 3
      docs/intro/tutorial01.txt
  30. 15 13
      docs/intro/tutorial02.txt
  31. 28 21
      docs/intro/tutorial03.txt
  32. 26 20
      docs/intro/tutorial04.txt
  33. 25 24
      docs/intro/tutorial05.txt
  34. 25 20
      docs/intro/tutorial07.txt
  35. 10 6
      docs/ref/applications.txt
  36. 21 13
      docs/ref/class-based-views/base.txt
  37. 39 25
      docs/ref/class-based-views/generic-date-based.txt
  38. 6 6
      docs/ref/class-based-views/generic-display.txt
  39. 13 7
      docs/ref/class-based-views/generic-editing.txt
  40. 1 1
      docs/ref/class-based-views/index.txt
  41. 1 1
      docs/ref/class-based-views/mixins-multiple-object.txt
  42. 3 2
      docs/ref/class-based-views/mixins-simple.txt
  43. 5 2
      docs/ref/clickjacking.txt
  44. 66 45
      docs/ref/contrib/admin/actions.txt
  45. 6 3
      docs/ref/contrib/admin/admindocs.txt
  46. 17 17
      docs/ref/contrib/admin/filters.txt
  47. 196 122
      docs/ref/contrib/admin/index.txt
  48. 18 16
      docs/ref/contrib/contenttypes.txt
  49. 25 18
      docs/ref/contrib/flatpages.txt
  50. 32 13
      docs/ref/contrib/gis/db-api.txt
  51. 2 4
      docs/ref/contrib/gis/feeds.txt
  52. 2 2
      docs/ref/contrib/gis/forms-api.txt
  53. 9 8
      docs/ref/contrib/gis/functions.txt
  54. 94 85
      docs/ref/contrib/gis/gdal.txt
  55. 5 5
      docs/ref/contrib/gis/geoip2.txt
  56. 14 12
      docs/ref/contrib/gis/geoquerysets.txt
  57. 34 27
      docs/ref/contrib/gis/geos.txt
  58. 2 5
      docs/ref/contrib/gis/install/postgis.txt
  59. 1 1
      docs/ref/contrib/gis/install/spatialite.txt
  60. 14 13
      docs/ref/contrib/gis/layermapping.txt
  61. 10 10
      docs/ref/contrib/gis/measure.txt
  62. 5 3
      docs/ref/contrib/gis/model-api.txt
  63. 11 21
      docs/ref/contrib/gis/serializers.txt
  64. 9 9
      docs/ref/contrib/gis/testing.txt
  65. 61 57
      docs/ref/contrib/gis/tutorial.txt
  66. 27 19
      docs/ref/contrib/messages.txt
  67. 20 16
      docs/ref/contrib/postgres/aggregates.txt
  68. 20 16
      docs/ref/contrib/postgres/constraints.txt
  69. 2 2
      docs/ref/contrib/postgres/expressions.txt
  70. 91 79
      docs/ref/contrib/postgres/fields.txt
  71. 22 20
      docs/ref/contrib/postgres/forms.txt
  72. 6 6
      docs/ref/contrib/postgres/indexes.txt
  73. 1 1
      docs/ref/contrib/postgres/lookups.txt
  74. 7 8
      docs/ref/contrib/postgres/operations.txt
  75. 59 47
      docs/ref/contrib/postgres/search.txt
  76. 4 4
      docs/ref/contrib/redirects.txt
  77. 65 34
      docs/ref/contrib/sitemaps.txt
  78. 24 14
      docs/ref/contrib/sites.txt
  79. 9 5
      docs/ref/contrib/staticfiles.txt
  80. 53 44
      docs/ref/contrib/syndication.txt
  81. 4 1
      docs/ref/csrf.txt
  82. 44 42
      docs/ref/databases.txt
  83. 9 9
      docs/ref/django-admin.txt
  84. 2 2
      docs/ref/files/file.txt
  85. 127 92
      docs/ref/forms/api.txt
  86. 61 41
      docs/ref/forms/fields.txt
  87. 2 1
      docs/ref/forms/renderers.txt
  88. 37 29
      docs/ref/forms/validation.txt
  89. 43 28
      docs/ref/forms/widgets.txt
  90. 76 75
      docs/ref/logging.txt
  91. 1 0
      docs/ref/middleware.txt
  92. 16 12
      docs/ref/migration-operations.txt
  93. 1 0
      docs/ref/models/class.txt
  94. 64 56
      docs/ref/models/conditional-expressions.txt
  95. 9 7
      docs/ref/models/constraints.txt
  96. 237 179
      docs/ref/models/database-functions.txt
  97. 99 88
      docs/ref/models/expressions.txt
  98. 93 65
      docs/ref/models/fields.txt
  99. 3 3
      docs/ref/models/indexes.txt
  100. 63 38
      docs/ref/models/instances.txt

+ 2 - 1
docs/faq/models.txt

@@ -33,12 +33,13 @@ same interface on each member of the ``connections`` dictionary:
 .. code-block:: pycon
 
     >>> from django.db import connections
-    >>> connections['my_db_alias'].queries
+    >>> connections["my_db_alias"].queries
 
 If you need to clear the query list manually at any point in your functions,
 call ``reset_queries()``, like this::
 
     from django.db import reset_queries
+
     reset_queries()
 
 Can I use Django with a preexisting database?

+ 7 - 6
docs/howto/auth-remote-user.txt

@@ -33,10 +33,10 @@ First, you must add the
 :class:`django.contrib.auth.middleware.AuthenticationMiddleware`::
 
     MIDDLEWARE = [
-        '...',
-        'django.contrib.auth.middleware.AuthenticationMiddleware',
-        'django.contrib.auth.middleware.RemoteUserMiddleware',
-        '...',
+        "...",
+        "django.contrib.auth.middleware.AuthenticationMiddleware",
+        "django.contrib.auth.middleware.RemoteUserMiddleware",
+        "...",
     ]
 
 Next, you must replace the :class:`~django.contrib.auth.backends.ModelBackend`
@@ -44,7 +44,7 @@ with :class:`~django.contrib.auth.backends.RemoteUserBackend` in the
 :setting:`AUTHENTICATION_BACKENDS` setting::
 
     AUTHENTICATION_BACKENDS = [
-        'django.contrib.auth.backends.RemoteUserBackend',
+        "django.contrib.auth.backends.RemoteUserBackend",
     ]
 
 With this setup, ``RemoteUserMiddleware`` will detect the username in
@@ -81,8 +81,9 @@ If your authentication mechanism uses a custom HTTP header and not
 
     from django.contrib.auth.middleware import RemoteUserMiddleware
 
+
     class CustomHeaderMiddleware(RemoteUserMiddleware):
-        header = 'HTTP_AUTHUSER'
+        header = "HTTP_AUTHUSER"
 
 .. warning::
 

+ 4 - 3
docs/howto/csrf.txt

@@ -205,6 +205,7 @@ will require a CSRF token to be inserted you should use the
   from django.views.decorators.cache import cache_page
   from django.views.decorators.csrf import csrf_protect
 
+
   @cache_page(60 * 15)
   @csrf_protect
   def my_view(request):
@@ -280,17 +281,17 @@ path within it that needs protection. Example::
 
     from django.views.decorators.csrf import csrf_exempt, csrf_protect
 
+
     @csrf_exempt
     def my_view(request):
-
         @csrf_protect
         def protected_path(request):
             do_something()
 
         if some_condition():
-           return protected_path(request)
+            return protected_path(request)
         else:
-           do_something_else()
+            do_something_else()
 
 Protecting a page that uses AJAX without an HTML form
 -----------------------------------------------------

+ 3 - 0
docs/howto/custom-file-storage.txt

@@ -13,6 +13,7 @@ You'll need to follow these steps:
 
         from django.core.files.storage import Storage
 
+
         class MyStorage(Storage):
             ...
 
@@ -22,6 +23,7 @@ You'll need to follow these steps:
         from django.conf import settings
         from django.core.files.storage import Storage
 
+
         class MyStorage(Storage):
             def __init__(self, option=None):
                 if not option:
@@ -135,4 +137,5 @@ Storages are then accessed by alias from from the
 :data:`django.core.files.storage.storages` dictionary::
 
     from django.core.files.storage import storages
+
     example_storage = storages["example"]

+ 23 - 12
docs/howto/custom-lookups.txt

@@ -28,14 +28,15 @@ lookup, then we need to tell Django about it::
 
   from django.db.models import Lookup
 
+
   class NotEqual(Lookup):
-      lookup_name = 'ne'
+      lookup_name = "ne"
 
       def as_sql(self, compiler, connection):
           lhs, lhs_params = self.process_lhs(compiler, connection)
           rhs, rhs_params = self.process_rhs(compiler, connection)
           params = lhs_params + rhs_params
-          return '%s <> %s' % (lhs, rhs), params
+          return "%s <> %s" % (lhs, rhs), params
 
 To register the ``NotEqual`` lookup we will need to call ``register_lookup`` on
 the field class we want the lookup to be available for. In this case, the lookup
@@ -43,12 +44,14 @@ makes sense on all ``Field`` subclasses, so we register it with ``Field``
 directly::
 
   from django.db.models import Field
+
   Field.register_lookup(NotEqual)
 
 Lookup registration can also be done using a decorator pattern::
 
     from django.db.models import Field
 
+
     @Field.register_lookup
     class NotEqualLookup(Lookup):
         ...
@@ -115,13 +118,15 @@ function ``ABS()`` to transform the value before comparison::
 
   from django.db.models import Transform
 
+
   class AbsoluteValue(Transform):
-      lookup_name = 'abs'
-      function = 'ABS'
+      lookup_name = "abs"
+      function = "ABS"
 
 Next, let's register it for ``IntegerField``::
 
   from django.db.models import IntegerField
+
   IntegerField.register_lookup(AbsoluteValue)
 
 We can now run the queries we had before.
@@ -167,9 +172,10 @@ be done by adding an ``output_field`` attribute to the transform::
 
     from django.db.models import FloatField, Transform
 
+
     class AbsoluteValue(Transform):
-        lookup_name = 'abs'
-        function = 'ABS'
+        lookup_name = "abs"
+        function = "ABS"
 
         @property
         def output_field(self):
@@ -197,14 +203,16 @@ The implementation is::
 
   from django.db.models import Lookup
 
+
   class AbsoluteValueLessThan(Lookup):
-      lookup_name = 'lt'
+      lookup_name = "lt"
 
       def as_sql(self, compiler, connection):
           lhs, lhs_params = compiler.compile(self.lhs.lhs)
           rhs, rhs_params = self.process_rhs(compiler, connection)
           params = lhs_params + rhs_params + lhs_params + rhs_params
-          return '%s < %s AND %s > -%s' % (lhs, rhs, lhs, rhs), params
+          return "%s < %s AND %s > -%s" % (lhs, rhs, lhs, rhs), params
+
 
   AbsoluteValue.register_lookup(AbsoluteValueLessThan)
 
@@ -252,14 +260,16 @@ this transformation should apply to both ``lhs`` and ``rhs``::
 
   from django.db.models import Transform
 
+
   class UpperCase(Transform):
-      lookup_name = 'upper'
-      function = 'UPPER'
+      lookup_name = "upper"
+      function = "UPPER"
       bilateral = True
 
 Next, let's register it::
 
   from django.db.models import CharField, TextField
+
   CharField.register_lookup(UpperCase)
   TextField.register_lookup(UpperCase)
 
@@ -287,7 +297,8 @@ We can change the behavior on a specific backend by creating a subclass of
           lhs, lhs_params = self.process_lhs(compiler, connection)
           rhs, rhs_params = self.process_rhs(compiler, connection)
           params = lhs_params + rhs_params
-          return '%s != %s' % (lhs, rhs), params
+          return "%s != %s" % (lhs, rhs), params
+
 
   Field.register_lookup(MySQLNotEqual)
 
@@ -310,7 +321,7 @@ would override ``get_lookup`` with something like::
 
     class CoordinatesField(Field):
         def get_lookup(self, lookup_name):
-            if lookup_name.startswith('x'):
+            if lookup_name.startswith("x"):
                 try:
                     dimension = int(lookup_name.removeprefix("x"))
                 except ValueError:

+ 15 - 11
docs/howto/custom-management-commands.txt

@@ -49,14 +49,15 @@ look like this::
     from django.core.management.base import BaseCommand, CommandError
     from polls.models import Question as Poll
 
+
     class Command(BaseCommand):
-        help = 'Closes the specified poll for voting'
+        help = "Closes the specified poll for voting"
 
         def add_arguments(self, parser):
-            parser.add_argument('poll_ids', nargs='+', type=int)
+            parser.add_argument("poll_ids", nargs="+", type=int)
 
         def handle(self, *args, **options):
-            for poll_id in options['poll_ids']:
+            for poll_id in options["poll_ids"]:
                 try:
                     poll = Poll.objects.get(pk=poll_id)
                 except Poll.DoesNotExist:
@@ -65,7 +66,9 @@ look like this::
                 poll.opened = False
                 poll.save()
 
-                self.stdout.write(self.style.SUCCESS('Successfully closed poll "%s"' % poll_id))
+                self.stdout.write(
+                    self.style.SUCCESS('Successfully closed poll "%s"' % poll_id)
+                )
 
 .. _management-commands-output:
 
@@ -78,7 +81,7 @@ look like this::
     character, it will be added automatically, unless you specify the ``ending``
     parameter::
 
-        self.stdout.write("Unterminated line", ending='')
+        self.stdout.write("Unterminated line", ending="")
 
 The new custom command can be called using ``python manage.py closepoll
 <poll_ids>``.
@@ -101,18 +104,18 @@ options can be added in the :meth:`~BaseCommand.add_arguments` method like this:
     class Command(BaseCommand):
         def add_arguments(self, parser):
             # Positional arguments
-            parser.add_argument('poll_ids', nargs='+', type=int)
+            parser.add_argument("poll_ids", nargs="+", type=int)
 
             # Named (optional) arguments
             parser.add_argument(
-                '--delete',
-                action='store_true',
-                help='Delete poll instead of closing it',
+                "--delete",
+                action="store_true",
+                help="Delete poll instead of closing it",
             )
 
         def handle(self, *args, **options):
             # ...
-            if options['delete']:
+            if options["delete"]:
                 poll.delete()
             # ...
 
@@ -138,6 +141,7 @@ decorator on your :meth:`~BaseCommand.handle` method::
 
     from django.core.management.base import BaseCommand, no_translations
 
+
     class Command(BaseCommand):
         ...
 
@@ -230,7 +234,7 @@ All attributes can be set in your derived class and can be used in
     An instance attribute that helps create colored output when writing to
     ``stdout`` or ``stderr``. For example::
 
-        self.stdout.write(self.style.SUCCESS('...'))
+        self.stdout.write(self.style.SUCCESS("..."))
 
     See :ref:`syntax-coloring` to learn how to modify the color palette and to
     see the available styles (use uppercased versions of the "roles" described

+ 27 - 20
docs/howto/custom-model-fields.txt

@@ -162,12 +162,12 @@ behave like any existing field, so we'll subclass directly from
 
     from django.db import models
 
-    class HandField(models.Field):
 
+    class HandField(models.Field):
         description = "A hand of cards (bridge style)"
 
         def __init__(self, *args, **kwargs):
-            kwargs['max_length'] = 104
+            kwargs["max_length"] = 104
             super().__init__(*args, **kwargs)
 
 Our ``HandField`` accepts most of the standard field options (see the list
@@ -259,10 +259,10 @@ we can drop it from the keyword arguments for readability::
 
     from django.db import models
 
-    class HandField(models.Field):
 
+    class HandField(models.Field):
         def __init__(self, *args, **kwargs):
-            kwargs['max_length'] = 104
+            kwargs["max_length"] = 104
             super().__init__(*args, **kwargs)
 
         def deconstruct(self):
@@ -277,6 +277,7 @@ such as when the default value is being used::
 
     from django.db import models
 
+
     class CommaSepField(models.Field):
         "Implements comma-separated storage of lists"
 
@@ -288,7 +289,7 @@ such as when the default value is being used::
             name, path, args, kwargs = super().deconstruct()
             # Only include kwarg if it's not the default
             if self.separator != ",":
-                kwargs['separator'] = self.separator
+                kwargs["separator"] = self.separator
             return name, path, args, kwargs
 
 More complex examples are beyond the scope of this document, but remember -
@@ -326,7 +327,6 @@ no-op ``AlterField`` operations.
 For example::
 
     class CommaSepField(models.Field):
-
         @property
         def non_db_attrs(self):
             return super().non_db_attrs + ("separator",)
@@ -353,6 +353,7 @@ reference it::
     class CustomCharField(models.CharField):
         ...
 
+
     class CustomTextField(models.TextField):
         ...
 
@@ -397,9 +398,10 @@ subclass ``Field`` and implement the :meth:`~Field.db_type` method, like so::
 
     from django.db import models
 
+
     class MytypeField(models.Field):
         def db_type(self, connection):
-            return 'mytype'
+            return "mytype"
 
 Once you have ``MytypeField``, you can use it in any model, just like any other
 ``Field`` type::
@@ -419,10 +421,10 @@ For example::
 
     class MyDateField(models.Field):
         def db_type(self, connection):
-            if connection.vendor == 'mysql':
-                return 'datetime'
+            if connection.vendor == "mysql":
+                return "datetime"
             else:
-                return 'timestamp'
+                return "timestamp"
 
 The :meth:`~Field.db_type` and :meth:`~Field.rel_db_type` methods are called by
 Django when the framework constructs the ``CREATE TABLE`` statements for your
@@ -442,7 +444,8 @@ sense to have a ``CharMaxlength25Field``, shown here::
     # This is a silly example of hard-coded parameters.
     class CharMaxlength25Field(models.Field):
         def db_type(self, connection):
-            return 'char(25)'
+            return "char(25)"
+
 
     # In the model:
     class MyModel(models.Model):
@@ -460,7 +463,8 @@ time -- i.e., when the class is instantiated. To do that, implement
             super().__init__(*args, **kwargs)
 
         def db_type(self, connection):
-            return 'char(%s)' % self.max_length
+            return "char(%s)" % self.max_length
+
 
     # In the model:
     class MyModel(models.Model):
@@ -481,10 +485,10 @@ need the foreign keys that point to that field to use the same data type::
     # MySQL unsigned integer (range 0 to 4294967295).
     class UnsignedAutoField(models.AutoField):
         def db_type(self, connection):
-            return 'integer UNSIGNED AUTO_INCREMENT'
+            return "integer UNSIGNED AUTO_INCREMENT"
 
         def rel_db_type(self, connection):
-            return 'integer UNSIGNED'
+            return "integer UNSIGNED"
 
 .. _converting-values-to-python-objects:
 
@@ -522,15 +526,17 @@ instances::
     from django.db import models
     from django.utils.translation import gettext_lazy as _
 
+
     def parse_hand(hand_string):
         """Takes a string of cards and splits into a full hand."""
-        p1 = re.compile('.{26}')
-        p2 = re.compile('..')
+        p1 = re.compile(".{26}")
+        p2 = re.compile("..")
         args = [p2.findall(x) for x in p1.findall(hand_string)]
         if len(args) != 4:
             raise ValidationError(_("Invalid input for a Hand instance"))
         return Hand(*args)
 
+
     class HandField(models.Field):
         # ...
 
@@ -569,8 +575,9 @@ For example::
         # ...
 
         def get_prep_value(self, value):
-            return ''.join([''.join(l) for l in (value.north,
-                    value.east, value.south, value.west)])
+            return "".join(
+                ["".join(l) for l in (value.north, value.east, value.south, value.west)]
+            )
 
 .. warning::
 
@@ -653,7 +660,7 @@ as::
         def formfield(self, **kwargs):
             # This is a fairly standard way to set up some defaults
             # while letting the caller override them.
-            defaults = {'form_class': MyFormField}
+            defaults = {"form_class": MyFormField}
             defaults.update(kwargs)
             return super().formfield(**defaults)
 
@@ -680,7 +687,7 @@ For example::
         # ...
 
         def get_internal_type(self):
-            return 'CharField'
+            return "CharField"
 
 No matter which database backend we are using, this will mean that
 :djadmin:`migrate` and other SQL commands create the right column type for

+ 23 - 25
docs/howto/custom-template-backend.txt

@@ -19,14 +19,13 @@ fictional ``foobar`` template library::
 
 
     class FooBar(BaseEngine):
-
         # Name of the subdirectory containing the templates for this engine
         # inside an installed application.
-        app_dirname = 'foobar'
+        app_dirname = "foobar"
 
         def __init__(self, params):
             params = params.copy()
-            options = params.pop('OPTIONS').copy()
+            options = params.pop("OPTIONS").copy()
             super().__init__(params)
 
             self.engine = foobar.Engine(**options)
@@ -47,7 +46,6 @@ fictional ``foobar`` template library::
 
 
     class Template:
-
         def __init__(self, template):
             self.template = template
 
@@ -55,9 +53,9 @@ fictional ``foobar`` template library::
             if context is None:
                 context = {}
             if request is not None:
-                context['request'] = request
-                context['csrf_input'] = csrf_input_lazy(request)
-                context['csrf_token'] = csrf_token_lazy(request)
+                context["request"] = request
+                context["csrf_input"] = csrf_input_lazy(request)
+                context["csrf_token"] = csrf_token_lazy(request)
             return self.template.render(context)
 
 See `DEP 182`_ for more information.
@@ -127,25 +125,25 @@ a :class:`dict` with the following values:
 Given the above template error, ``template_debug`` would look like::
 
     {
-        'name': '/path/to/template.html',
-        'message': "Invalid block tag: 'syntax'",
-        'source_lines': [
-            (1, 'some\n'),
-            (2, 'lines\n'),
-            (3, 'before\n'),
-            (4, 'Hello {% syntax error %} {{ world }}\n'),
-            (5, 'some\n'),
-            (6, 'lines\n'),
-            (7, 'after\n'),
-            (8, ''),
+        "name": "/path/to/template.html",
+        "message": "Invalid block tag: 'syntax'",
+        "source_lines": [
+            (1, "some\n"),
+            (2, "lines\n"),
+            (3, "before\n"),
+            (4, "Hello {% syntax error %} {{ world }}\n"),
+            (5, "some\n"),
+            (6, "lines\n"),
+            (7, "after\n"),
+            (8, ""),
         ],
-        'line': 4,
-        'before': 'Hello ',
-        'during': '{% syntax error %}',
-        'after': ' {{ world }}\n',
-        'total': 9,
-        'bottom': 9,
-        'top': 1,
+        "line": 4,
+        "before": "Hello ",
+        "during": "{% syntax error %}",
+        "after": " {{ world }}\n",
+        "total": 9,
+        "bottom": 9,
+        "top": 1,
     }
 
 .. _template-origin-api:

+ 57 - 39
docs/howto/custom-template-tags.txt

@@ -111,7 +111,7 @@ Here's an example filter definition::
 
     def cut(value, arg):
         """Removes all values of arg from the given string"""
-        return value.replace(arg, '')
+        return value.replace(arg, "")
 
 And here's an example of how that filter would be used:
 
@@ -122,7 +122,7 @@ And here's an example of how that filter would be used:
 Most filters don't take arguments. In this case, leave the argument out of your
 function::
 
-    def lower(value): # Only one argument.
+    def lower(value):  # Only one argument.
         """Converts a string into all lowercase"""
         return value.lower()
 
@@ -134,8 +134,8 @@ Registering custom filters
 Once you've written your filter definition, you need to register it with
 your ``Library`` instance, to make it available to Django's template language::
 
-    register.filter('cut', cut)
-    register.filter('lower', lower)
+    register.filter("cut", cut)
+    register.filter("lower", lower)
 
 The ``Library.filter()`` method takes two arguments:
 
@@ -145,9 +145,10 @@ The ``Library.filter()`` method takes two arguments:
 
 You can use ``register.filter()`` as a decorator instead::
 
-    @register.filter(name='cut')
+    @register.filter(name="cut")
     def cut(value, arg):
-        return value.replace(arg, '')
+        return value.replace(arg, "")
+
 
     @register.filter
     def lower(value):
@@ -175,6 +176,7 @@ convert an object to its string value before being passed to your function::
 
     register = template.Library()
 
+
     @register.filter
     @stringfilter
     def lower(value):
@@ -242,7 +244,7 @@ Template filter code falls into one of two situations:
 
        @register.filter(is_safe=True)
        def add_xx(value):
-           return '%sxx' % value
+           return "%sxx" % value
 
    When this filter is used in a template where auto-escaping is enabled,
    Django will escape the output whenever the input is not already marked
@@ -300,6 +302,7 @@ Template filter code falls into one of two situations:
 
       register = template.Library()
 
+
       @register.filter(needs_autoescape=True)
       def initial_letter_filter(text, autoescape=True):
           first, other = text[0], text[1:]
@@ -307,7 +310,7 @@ Template filter code falls into one of two situations:
               esc = conditional_escape
           else:
               esc = lambda x: x
-          result = '<strong>%s</strong>%s' % (esc(first), esc(other))
+          result = "<strong>%s</strong>%s" % (esc(first), esc(other))
           return mark_safe(result)
 
    The ``needs_autoescape`` flag and the ``autoescape`` keyword argument mean
@@ -345,12 +348,10 @@ Template filter code falls into one of two situations:
 
         from django.template.defaultfilters import linebreaksbr, urlize
 
+
         @register.filter(needs_autoescape=True)
         def urlize_and_linebreaks(text, autoescape=True):
-            return linebreaksbr(
-                urlize(text, autoescape=autoescape),
-                autoescape=autoescape
-            )
+            return linebreaksbr(urlize(text, autoescape=autoescape), autoescape=autoescape)
 
     Then:
 
@@ -378,7 +379,7 @@ objects, you'll usually register it with the ``expects_localtime`` flag set to
         try:
             return 9 <= value.hour < 17
         except AttributeError:
-            return ''
+            return ""
 
 When this flag is set, if the first argument to your filter is a time zone
 aware datetime, Django will convert it to the current time zone before passing
@@ -421,6 +422,7 @@ Our ``current_time`` function could thus be written like this::
 
     register = template.Library()
 
+
     @register.simple_tag
     def current_time(format_string):
         return datetime.datetime.now().strftime(format_string)
@@ -450,7 +452,7 @@ If your template tag needs to access the current context, you can use the
 
     @register.simple_tag(takes_context=True)
     def current_time(context, format_string):
-        timezone = context['timezone']
+        timezone = context["timezone"]
         return your_get_current_time_method(timezone, format_string)
 
 Note that the first argument *must* be called ``context``.
@@ -460,9 +462,10 @@ on :ref:`inclusion tags<howto-custom-template-tags-inclusion-tags>`.
 
 If you need to rename your tag, you can provide a custom name for it::
 
-    register.simple_tag(lambda x: x - 1, name='minusone')
+    register.simple_tag(lambda x: x - 1, name="minusone")
 
-    @register.simple_tag(name='minustwo')
+
+    @register.simple_tag(name="minustwo")
     def some_function(value):
         return value - 2
 
@@ -471,8 +474,8 @@ arguments. For example::
 
     @register.simple_tag
     def my_tag(a, b, *args, **kwargs):
-        warning = kwargs['warning']
-        profile = kwargs['profile']
+        warning = kwargs["warning"]
+        profile = kwargs["profile"]
         ...
         return ...
 
@@ -537,7 +540,7 @@ for the template fragment. Example::
 
     def show_results(poll):
         choices = poll.choice_set.all()
-        return {'choices': choices}
+        return {"choices": choices}
 
 Next, create the template used to render the tag's output. This template is a
 fixed feature of the tag: the tag writer specifies it, not the template
@@ -557,7 +560,7 @@ in a file called ``results.html`` in a directory that's searched by the
 template loader, we'd register the tag like this::
 
     # Here, register is a django.template.Library instance, as before
-    @register.inclusion_tag('results.html')
+    @register.inclusion_tag("results.html")
     def show_results(poll):
         ...
 
@@ -565,7 +568,8 @@ Alternatively it is possible to register the inclusion tag using a
 :class:`django.template.Template` instance::
 
     from django.template.loader import get_template
-    t = get_template('results.html')
+
+    t = get_template("results.html")
     register.inclusion_tag(t)(show_results)
 
 ...when first creating the function.
@@ -581,11 +585,11 @@ For example, say you're writing an inclusion tag that will always be used in a
 context that contains ``home_link`` and ``home_title`` variables that point
 back to the main page. Here's what the Python function would look like::
 
-    @register.inclusion_tag('link.html', takes_context=True)
+    @register.inclusion_tag("link.html", takes_context=True)
     def jump_link(context):
         return {
-            'link': context['home_link'],
-            'title': context['home_title'],
+            "link": context["home_link"],
+            "title": context["home_title"],
         }
 
 Note that the first parameter to the function *must* be called ``context``.
@@ -615,10 +619,10 @@ only difference between this case and the previous ``inclusion_tag`` example.
 ``inclusion_tag`` functions may accept any number of positional or keyword
 arguments. For example::
 
-    @register.inclusion_tag('my_template.html')
+    @register.inclusion_tag("my_template.html")
     def my_tag(a, b, *args, **kwargs):
-        warning = kwargs['warning']
-        profile = kwargs['profile']
+        warning = kwargs["warning"]
+        profile = kwargs["profile"]
         ...
         return ...
 
@@ -678,6 +682,7 @@ object::
 
     from django import template
 
+
     def do_current_time(parser, token):
         try:
             # split_contents() knows not to split quoted strings.
@@ -737,6 +742,7 @@ Continuing the above example, we need to define ``CurrentTimeNode``::
     import datetime
     from django import template
 
+
     class CurrentTimeNode(template.Node):
         def __init__(self, format_string):
             self.format_string = format_string
@@ -788,17 +794,18 @@ The ``__init__`` method for the ``Context`` class takes a parameter called
 
     from django.template import Context
 
+
     def render(self, context):
         # ...
-        new_context = Context({'var': obj}, autoescape=context.autoescape)
+        new_context = Context({"var": obj}, autoescape=context.autoescape)
         # ... Do something with new_context ...
 
 This is not a very common situation, but it's useful if you're rendering a
 template yourself. For example::
 
     def render(self, context):
-        t = context.template.engine.get_template('small_fragment.html')
-        return t.render(Context({'var': obj}, autoescape=context.autoescape))
+        t = context.template.engine.get_template("small_fragment.html")
+        return t.render(Context({"var": obj}, autoescape=context.autoescape))
 
 If we had neglected to pass in the current ``context.autoescape`` value to our
 new ``Context`` in this example, the results would have *always* been
@@ -834,6 +841,7 @@ A naive implementation of ``CycleNode`` might look something like this::
     import itertools
     from django import template
 
+
     class CycleNode(template.Node):
         def __init__(self, cyclevars):
             self.cycle_iter = itertools.cycle(cyclevars)
@@ -897,7 +905,7 @@ Finally, register the tag with your module's ``Library`` instance, as explained
 in :ref:`writing custom template tags<howto-writing-custom-template-tags>`
 above. Example::
 
-    register.tag('current_time', do_current_time)
+    register.tag("current_time", do_current_time)
 
 The ``tag()`` method takes two arguments:
 
@@ -912,6 +920,7 @@ As with filter registration, it is also possible to use this as a decorator::
     def do_current_time(parser, token):
         ...
 
+
     @register.tag
     def shout(parser, token):
         ...
@@ -949,6 +958,7 @@ Now your tag should begin to look like this::
 
     from django import template
 
+
     def do_format_time(parser, token):
         try:
             # split_contents() knows not to split quoted strings.
@@ -980,7 +990,7 @@ be resolved, and then call ``variable.resolve(context)``. So, for example::
                 actual_date = self.date_to_be_formatted.resolve(context)
                 return actual_date.strftime(self.format_string)
             except template.VariableDoesNotExist:
-                return ''
+                return ""
 
 Variable resolution will throw a ``VariableDoesNotExist`` exception if it
 cannot resolve the string passed to it in the current context of the page.
@@ -1000,12 +1010,14 @@ outputting it::
     import datetime
     from django import template
 
+
     class CurrentTimeNode2(template.Node):
         def __init__(self, format_string):
             self.format_string = format_string
+
         def render(self, context):
-            context['current_time'] = datetime.datetime.now().strftime(self.format_string)
-            return ''
+            context["current_time"] = datetime.datetime.now().strftime(self.format_string)
+            return ""
 
 Note that ``render()`` returns the empty string. ``render()`` should always
 return string output. If all the template tag does is set a variable,
@@ -1041,13 +1053,16 @@ class, like so::
 
     import re
 
+
     class CurrentTimeNode3(template.Node):
         def __init__(self, format_string, var_name):
             self.format_string = format_string
             self.var_name = var_name
+
         def render(self, context):
             context[self.var_name] = datetime.datetime.now().strftime(self.format_string)
-            return ''
+            return ""
+
 
     def do_current_time(parser, token):
         # This version uses a regular expression to parse tag contents.
@@ -1058,7 +1073,7 @@ class, like so::
             raise template.TemplateSyntaxError(
                 "%r tag requires arguments" % token.contents.split()[0]
             )
-        m = re.search(r'(.*?) as (\w+)', arg)
+        m = re.search(r"(.*?) as (\w+)", arg)
         if not m:
             raise template.TemplateSyntaxError("%r tag had invalid arguments" % tag_name)
         format_string, var_name = m.groups()
@@ -1087,13 +1102,14 @@ compilation function.
 Here's how a simplified ``{% comment %}`` tag might be implemented::
 
     def do_comment(parser, token):
-        nodelist = parser.parse(('endcomment',))
+        nodelist = parser.parse(("endcomment",))
         parser.delete_first_token()
         return CommentNode()
 
+
     class CommentNode(template.Node):
         def render(self, context):
-            return ''
+            return ""
 
 .. note::
     The actual implementation of :ttag:`{% comment %}<comment>` is slightly
@@ -1140,13 +1156,15 @@ As in the previous example, we'll use ``parser.parse()``. But this time, we
 pass the resulting ``nodelist`` to the ``Node``::
 
     def do_upper(parser, token):
-        nodelist = parser.parse(('endupper',))
+        nodelist = parser.parse(("endupper",))
         parser.delete_first_token()
         return UpperNode(nodelist)
 
+
     class UpperNode(template.Node):
         def __init__(self, nodelist):
             self.nodelist = nodelist
+
         def render(self, context):
             output = self.nodelist.render(context)
             return output.upper()

+ 1 - 0
docs/howto/deployment/asgi/index.txt

@@ -69,4 +69,5 @@ To apply ASGI middleware, or to embed Django in another ASGI application, you
 can wrap Django's ``application`` object in the ``asgi.py`` file. For example::
 
     from some_asgi_library import AmazingMiddleware
+
     application = AmazingMiddleware(application)

+ 6 - 4
docs/howto/deployment/checklist.txt

@@ -52,19 +52,21 @@ Instead of hardcoding the secret key in your settings module, consider loading
 it from an environment variable::
 
     import os
-    SECRET_KEY = os.environ['SECRET_KEY']
+
+    SECRET_KEY = os.environ["SECRET_KEY"]
 
 or from a file::
 
-    with open('/etc/secret_key.txt') as f:
+    with open("/etc/secret_key.txt") as f:
         SECRET_KEY = f.read().strip()
 
 If rotating secret keys, you may use :setting:`SECRET_KEY_FALLBACKS`::
 
     import os
-    SECRET_KEY = os.environ['CURRENT_SECRET_KEY']
+
+    SECRET_KEY = os.environ["CURRENT_SECRET_KEY"]
     SECRET_KEY_FALLBACKS = [
-        os.environ['OLD_SECRET_KEY'],
+        os.environ["OLD_SECRET_KEY"],
     ]
 
 Ensure that old secret keys are removed from ``SECRET_KEY_FALLBACKS`` in a

+ 2 - 1
docs/howto/deployment/wsgi/apache-auth.txt

@@ -84,11 +84,12 @@ function::
 
     import os
 
-    os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
+    os.environ["DJANGO_SETTINGS_MODULE"] = "mysite.settings"
 
     from django.contrib.auth.handlers.modwsgi import check_password
 
     from django.core.handlers.wsgi import WSGIHandler
+
     application = WSGIHandler()
 
 

+ 1 - 0
docs/howto/deployment/wsgi/index.txt

@@ -76,6 +76,7 @@ object. For instance you could add these lines at the bottom of
 :file:`wsgi.py`::
 
     from helloworld.wsgi import HelloWorldApplication
+
     application = HelloWorldApplication(application)
 
 You could also replace the Django WSGI application with a custom WSGI

+ 18 - 14
docs/howto/error-reporting.txt

@@ -81,9 +81,10 @@ You can tell Django to stop reporting particular 404s by tweaking the
 regular expression objects. For example::
 
     import re
+
     IGNORABLE_404_URLS = [
-        re.compile(r'\.(php|cgi)$'),
-        re.compile(r'^/phpmyadmin/'),
+        re.compile(r"\.(php|cgi)$"),
+        re.compile(r"^/phpmyadmin/"),
     ]
 
 In this example, a 404 to any URL ending with ``.php`` or ``.cgi`` will *not* be
@@ -93,10 +94,11 @@ The following example shows how to exclude some conventional URLs that browsers
 crawlers often request::
 
     import re
+
     IGNORABLE_404_URLS = [
-        re.compile(r'^/apple-touch-icon.*\.png$'),
-        re.compile(r'^/favicon\.ico$'),
-        re.compile(r'^/robots\.txt$'),
+        re.compile(r"^/apple-touch-icon.*\.png$"),
+        re.compile(r"^/favicon\.ico$"),
+        re.compile(r"^/robots\.txt$"),
     ]
 
 (Note that these are regular expressions, so we put a backslash in front of
@@ -158,7 +160,8 @@ filtered out of error reports in a production environment (that is, where
 
         from django.views.decorators.debug import sensitive_variables
 
-        @sensitive_variables('user', 'pw', 'cc')
+
+        @sensitive_variables("user", "pw", "cc")
         def process_info(user):
             pw = user.pass_word
             cc = user.credit_card_number
@@ -185,7 +188,7 @@ filtered out of error reports in a production environment (that is, where
         at the top of the decorator chain. This way it will also hide the
         function argument as it gets passed through the other decorators::
 
-            @sensitive_variables('user', 'pw', 'cc')
+            @sensitive_variables("user", "pw", "cc")
             @some_decorator
             @another_decorator
             def process_info(user):
@@ -201,13 +204,14 @@ filtered out of error reports in a production environment (that is, where
 
         from django.views.decorators.debug import sensitive_post_parameters
 
-        @sensitive_post_parameters('pass_word', 'credit_card_number')
+
+        @sensitive_post_parameters("pass_word", "credit_card_number")
         def record_user_profile(request):
             UserProfile.create(
                 user=request.user,
-                password=request.POST['pass_word'],
-                credit_card=request.POST['credit_card_number'],
-                name=request.POST['name'],
+                password=request.POST["pass_word"],
+                credit_card=request.POST["credit_card_number"],
+                name=request.POST["name"],
             )
             ...
 
@@ -248,7 +252,7 @@ override or customize this default behavior for your entire site, you need to
 define your own filter class and tell Django to use it via the
 :setting:`DEFAULT_EXCEPTION_REPORTER_FILTER` setting::
 
-    DEFAULT_EXCEPTION_REPORTER_FILTER = 'path.to.your.CustomExceptionReporterFilter'
+    DEFAULT_EXCEPTION_REPORTER_FILTER = "path.to.your.CustomExceptionReporterFilter"
 
 You may also control in a more granular way which filter to use within any
 given view by setting the ``HttpRequest``’s ``exception_reporter_filter``
@@ -281,7 +285,7 @@ following attributes and methods:
 
             import re
 
-            re.compile(r'API|TOKEN|KEY|SECRET|PASS|SIGNATURE|HTTP_COOKIE', flags=re.IGNORECASE)
+            re.compile(r"API|TOKEN|KEY|SECRET|PASS|SIGNATURE|HTTP_COOKIE", flags=re.IGNORECASE)
 
         .. versionchanged:: 4.2
 
@@ -311,7 +315,7 @@ If you need to customize error reports beyond filtering you may specify a
 custom error reporter class by defining the
 :setting:`DEFAULT_EXCEPTION_REPORTER` setting::
 
-    DEFAULT_EXCEPTION_REPORTER = 'path.to.your.CustomExceptionReporter'
+    DEFAULT_EXCEPTION_REPORTER = "path.to.your.CustomExceptionReporter"
 
 The exception reporter is responsible for compiling the exception report data,
 and formatting it as text or HTML appropriately. (The exception reporter uses

+ 3 - 2
docs/howto/legacy-databases.txt

@@ -58,9 +58,10 @@ each table's creation, modification, and deletion::
     class Person(models.Model):
         id = models.IntegerField(primary_key=True)
         first_name = models.CharField(max_length=70)
+
         class Meta:
-           managed = False
-           db_table = 'CENSUS_PERSONS'
+            managed = False
+            db_table = "CENSUS_PERSONS"
 
 If you do want to allow Django to manage the table's lifecycle, you'll need to
 change the :attr:`~django.db.models.Options.managed` option above to ``True``

+ 39 - 43
docs/howto/logging.txt

@@ -41,7 +41,7 @@ And then in a function, for example in a view, send a record to the logger::
     def some_view(request):
         ...
         if some_risky_state:
-            logger.warning('Platform is running at risk')
+            logger.warning("Platform is running at risk")
 
 When this code is executed, a :py:class:`~logging.LogRecord` containing that
 message will be sent to the logger. If you're using Django's default logging
@@ -51,7 +51,7 @@ The ``WARNING`` level used in the example above is one of several
 :ref:`logging severity levels <topic-logging-parts-loggers>`: ``DEBUG``,
 ``INFO``, ``WARNING``, ``ERROR``, ``CRITICAL``. So, another example might be::
 
-    logger.critical('Payment system is not responding')
+    logger.critical("Payment system is not responding")
 
 .. important::
 
@@ -99,8 +99,8 @@ Create a ``LOGGING`` dictionary
 In your ``settings.py``::
 
     LOGGING = {
-        'version': 1,                       # the dictConfig format version
-        'disable_existing_loggers': False,  # retain the default loggers
+        "version": 1,  # the dictConfig format version
+        "disable_existing_loggers": False,  # retain the default loggers
     }
 
 It nearly always makes sense to retain and extend the default logging
@@ -118,10 +118,10 @@ file ``general.log`` (at the project root):
 
     LOGGING = {
         # ...
-        'handlers': {
-            'file': {
-                'class': 'logging.FileHandler',
-                'filename': 'general.log',
+        "handlers": {
+            "file": {
+                "class": "logging.FileHandler",
+                "filename": "general.log",
             },
         },
     }
@@ -138,9 +138,9 @@ messages of all levels). Using the example above, adding:
     :emphasize-lines: 4
 
     {
-        'class': 'logging.FileHandler',
-        'filename': 'general.log',
-        'level': 'DEBUG',
+        "class": "logging.FileHandler",
+        "filename": "general.log",
+        "level": "DEBUG",
     }
 
 would define a handler configuration that only accepts records of level
@@ -157,10 +157,10 @@ example:
 
     LOGGING = {
         # ...
-        'loggers': {
-            '': {
-                'level': 'DEBUG',
-                'handlers': ['file'],
+        "loggers": {
+            "": {
+                "level": "DEBUG",
+                "handlers": ["file"],
             },
         },
     }
@@ -178,7 +178,7 @@ between loggers and handlers is many-to-many.
 
 If you execute::
 
-    logger.debug('Attempting to connect to API')
+    logger.debug("Attempting to connect to API")
 
 in your code, you will find that message in the file ``general.log`` in the
 root of the project.
@@ -196,14 +196,14 @@ formatters named ``verbose`` and ``simple``:
 
     LOGGING = {
         # ...
-        'formatters': {
-            'verbose': {
-                'format': '{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}',
-                'style': '{',
+        "formatters": {
+            "verbose": {
+                "format": "{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}",
+                "style": "{",
             },
-            'simple': {
-                'format': '{levelname} {message}',
-                'style': '{',
+            "simple": {
+                "format": "{levelname} {message}",
+                "style": "{",
             },
         },
     }
@@ -220,11 +220,11 @@ dictionary referring to the formatter by name, for example:
 .. code-block:: python
     :emphasize-lines: 5
 
-    'handlers': {
-        'file': {
-            'class': 'logging.FileHandler',
-            'filename': 'general.log',
-            'formatter': 'verbose',
+    "handlers": {
+        "file": {
+            "class": "logging.FileHandler",
+            "filename": "general.log",
+            "formatter": "verbose",
         },
     }
 
@@ -254,10 +254,8 @@ A logger mapping named ``my_app.views`` will capture records from this logger:
 
     LOGGING = {
         # ...
-        'loggers': {
-            'my_app.views': {
-                ...
-            },
+        "loggers": {
+            "my_app.views": {...},
         },
     }
 
@@ -270,16 +268,14 @@ from loggers anywhere within the ``my_app`` namespace (including
 
     LOGGING = {
         # ...
-        'loggers': {
-            'my_app': {
-                ...
-            },
+        "loggers": {
+            "my_app": {...},
         },
     }
 
 You can also define logger namespacing explicitly::
 
-    logger = logging.getLogger('project.payment')
+    logger = logging.getLogger("project.payment")
 
 and set up logger mappings accordingly.
 
@@ -298,16 +294,16 @@ To manage this behavior, set the propagation key on the mappings you define::
 
     LOGGING = {
         # ...
-        'loggers': {
-            'my_app': {
+        "loggers": {
+            "my_app": {
                 # ...
             },
-            'my_app.views': {
+            "my_app.views": {
                 # ...
             },
-            'my_app.views.private': {
+            "my_app.views.private": {
                 # ...
-                'propagate': False,
+                "propagate": False,
             },
         },
     }
@@ -333,7 +329,7 @@ For example, you could set an environment variable ``DJANGO_LOG_LEVEL``
 appropriately in your development and staging environments, and make use of it
 in a logger mapping thus::
 
-    'level': os.getenv('DJANGO_LOG_LEVEL', 'WARNING')
+    "level": os.getenv("DJANGO_LOG_LEVEL", "WARNING")
 
 \- so that unless the environment specifies a lower log level, this
 configuration will only forward records of severity ``WARNING`` and above to

+ 16 - 11
docs/howto/outputting-csv.txt

@@ -18,16 +18,17 @@ Here's an example::
     import csv
     from django.http import HttpResponse
 
+
     def some_view(request):
         # Create the HttpResponse object with the appropriate CSV header.
         response = HttpResponse(
-            content_type='text/csv',
-            headers={'Content-Disposition': 'attachment; filename="somefilename.csv"'},
+            content_type="text/csv",
+            headers={"Content-Disposition": 'attachment; filename="somefilename.csv"'},
         )
 
         writer = csv.writer(response)
-        writer.writerow(['First row', 'Foo', 'Bar', 'Baz'])
-        writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"])
+        writer.writerow(["First row", "Foo", "Bar", "Baz"])
+        writer.writerow(["Second row", "A", "B", "C", '"Testing"', "Here's a quote"])
 
         return response
 
@@ -72,14 +73,17 @@ the assembly and transmission of a large CSV file::
 
     from django.http import StreamingHttpResponse
 
+
     class Echo:
         """An object that implements just the write method of the file-like
         interface.
         """
+
         def write(self, value):
             """Write the value by returning it, instead of storing in a buffer."""
             return value
 
+
     def some_streaming_csv_view(request):
         """A view that streams a large CSV file."""
         # Generate a sequence of rows. The range is based on the maximum number of
@@ -91,7 +95,7 @@ the assembly and transmission of a large CSV file::
         return StreamingHttpResponse(
             (writer.writerow(row) for row in rows),
             content_type="text/csv",
-            headers={'Content-Disposition': 'attachment; filename="somefilename.csv"'},
+            headers={"Content-Disposition": 'attachment; filename="somefilename.csv"'},
         )
 
 Using the template system
@@ -109,22 +113,23 @@ Here's an example, which generates the same CSV file as above::
     from django.http import HttpResponse
     from django.template import loader
 
+
     def some_view(request):
         # Create the HttpResponse object with the appropriate CSV header.
         response = HttpResponse(
-            content_type='text/csv',
-            headers={'Content-Disposition': 'attachment; filename="somefilename.csv"'},
+            content_type="text/csv",
+            headers={"Content-Disposition": 'attachment; filename="somefilename.csv"'},
         )
 
         # The data is hard-coded here, but you could load it from a database or
         # some other source.
         csv_data = (
-            ('First row', 'Foo', 'Bar', 'Baz'),
-            ('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"),
+            ("First row", "Foo", "Bar", "Baz"),
+            ("Second row", "A", "B", "C", '"Testing"', "Here's a quote"),
         )
 
-        t = loader.get_template('my_template_name.txt')
-        c = {'data': csv_data}
+        t = loader.get_template("my_template_name.txt")
+        c = {"data": csv_data}
         response.write(t.render(c))
         return response
 

+ 2 - 1
docs/howto/outputting-pdf.txt

@@ -52,6 +52,7 @@ Here's a "Hello World" example::
     from django.http import FileResponse
     from reportlab.pdfgen import canvas
 
+
     def some_view(request):
         # Create a file-like buffer to receive PDF data.
         buffer = io.BytesIO()
@@ -70,7 +71,7 @@ Here's a "Hello World" example::
         # FileResponse sets the Content-Disposition header so that browsers
         # present the option to save the file.
         buffer.seek(0)
-        return FileResponse(buffer, as_attachment=True, filename='hello.pdf')
+        return FileResponse(buffer, as_attachment=True, filename="hello.pdf")
 
 The code and comments should be self-explanatory, but a few things deserve a
 mention:

+ 5 - 5
docs/howto/overriding-templates.txt

@@ -33,15 +33,15 @@ called ``blog``, which provides the templates ``blog/post.html`` and
 
     INSTALLED_APPS = [
         ...,
-        'blog',
+        "blog",
         ...,
     ]
 
     TEMPLATES = [
         {
-            'BACKEND': 'django.template.backends.django.DjangoTemplates',
-            'DIRS': [BASE_DIR / 'templates'],
-            'APP_DIRS': True,
+            "BACKEND": "django.template.backends.django.DjangoTemplates",
+            "DIRS": [BASE_DIR / "templates"],
+            "APP_DIRS": True,
             # ...
         },
     ]
@@ -78,7 +78,7 @@ First, make sure your template settings are checking inside app directories::
     TEMPLATES = [
         {
             # ...
-            'APP_DIRS': True,
+            "APP_DIRS": True,
             # ...
         },
     ]

+ 2 - 2
docs/howto/static-files/index.txt

@@ -16,7 +16,7 @@ Configuring static files
 
 #. In your settings file, define :setting:`STATIC_URL`, for example::
 
-      STATIC_URL = 'static/'
+      STATIC_URL = "static/"
 
 #. In your templates, use the :ttag:`static` template tag to build the URL for
    the given relative path using the configured ``staticfiles``
@@ -54,7 +54,7 @@ settings file where Django will also look for static files. For example::
 
     STATICFILES_DIRS = [
         BASE_DIR / "static",
-        '/var/www/static/',
+        "/var/www/static/",
     ]
 
 See the documentation for the :setting:`STATICFILES_FINDERS` setting for

+ 51 - 45
docs/howto/writing-migrations.txt

@@ -21,13 +21,14 @@ attribute::
 
     from django.db import migrations
 
+
     def forwards(apps, schema_editor):
-        if schema_editor.connection.alias != 'default':
+        if schema_editor.connection.alias != "default":
             return
         # Your migration code goes here
 
-    class Migration(migrations.Migration):
 
+    class Migration(migrations.Migration):
         dependencies = [
             # Dependencies to other migrations
         ]
@@ -43,28 +44,28 @@ method of database routers as ``**hints``:
     :caption: ``myapp/dbrouters.py``
 
     class MyRouter:
-
         def allow_migrate(self, db, app_label, model_name=None, **hints):
-            if 'target_db' in hints:
-                return db == hints['target_db']
+            if "target_db" in hints:
+                return db == hints["target_db"]
             return True
 
 Then, to leverage this in your migrations, do the following::
 
     from django.db import migrations
 
+
     def forwards(apps, schema_editor):
         # Your migration code goes here
         ...
 
-    class Migration(migrations.Migration):
 
+    class Migration(migrations.Migration):
         dependencies = [
             # Dependencies to other migrations
         ]
 
         operations = [
-            migrations.RunPython(forwards, hints={'target_db': 'default'}),
+            migrations.RunPython(forwards, hints={"target_db": "default"}),
         ]
 
 If your ``RunPython`` or ``RunSQL`` operation only affects one model, it's good
@@ -104,16 +105,16 @@ the respective field according to your needs.
     from django.db import migrations, models
     import uuid
 
-    class Migration(migrations.Migration):
 
+    class Migration(migrations.Migration):
         dependencies = [
-            ('myapp', '0005_populate_uuid_values'),
+            ("myapp", "0005_populate_uuid_values"),
         ]
 
         operations = [
             migrations.AlterField(
-                model_name='mymodel',
-                name='uuid',
+                model_name="mymodel",
+                name="uuid",
                 field=models.UUIDField(default=uuid.uuid4, unique=True),
             ),
         ]
@@ -125,15 +126,14 @@ the respective field according to your needs.
     :caption: ``0004_add_uuid_field.py``
 
     class Migration(migrations.Migration):
-
         dependencies = [
-            ('myapp', '0003_auto_20150129_1705'),
+            ("myapp", "0003_auto_20150129_1705"),
         ]
 
         operations = [
             migrations.AddField(
-                model_name='mymodel',
-                name='uuid',
+                model_name="mymodel",
+                name="uuid",
                 field=models.UUIDField(default=uuid.uuid4, unique=True),
             ),
         ]
@@ -155,16 +155,17 @@ the respective field according to your needs.
     from django.db import migrations
     import uuid
 
+
     def gen_uuid(apps, schema_editor):
-        MyModel = apps.get_model('myapp', 'MyModel')
+        MyModel = apps.get_model("myapp", "MyModel")
         for row in MyModel.objects.all():
             row.uuid = uuid.uuid4()
-            row.save(update_fields=['uuid'])
+            row.save(update_fields=["uuid"])
 
-    class Migration(migrations.Migration):
 
+    class Migration(migrations.Migration):
         dependencies = [
-            ('myapp', '0004_add_uuid_field'),
+            ("myapp", "0004_add_uuid_field"),
         ]
 
         operations = [
@@ -190,6 +191,7 @@ a transaction by setting the ``atomic`` attribute to ``False``::
 
     from django.db import migrations
 
+
     class Migration(migrations.Migration):
         atomic = False
 
@@ -205,14 +207,16 @@ smaller batches::
 
     from django.db import migrations, transaction
 
+
     def gen_uuid(apps, schema_editor):
-        MyModel = apps.get_model('myapp', 'MyModel')
+        MyModel = apps.get_model("myapp", "MyModel")
         while MyModel.objects.filter(uuid__isnull=True).exists():
             with transaction.atomic():
                 for row in MyModel.objects.filter(uuid__isnull=True)[:1000]:
                     row.uuid = uuid.uuid4()
                     row.save()
 
+
     class Migration(migrations.Migration):
         atomic = False
 
@@ -241,10 +245,10 @@ The ``dependencies`` property is declared like this::
 
     from django.db import migrations
 
-    class Migration(migrations.Migration):
 
+    class Migration(migrations.Migration):
         dependencies = [
-            ('myapp', '0123_the_previous_migration'),
+            ("myapp", "0123_the_previous_migration"),
         ]
 
 Usually this will be enough, but from time to time you may need to
@@ -259,7 +263,7 @@ the ``run_before`` attribute on your ``Migration`` class::
         ...
 
         run_before = [
-            ('third_party_app', '0001_do_awesome'),
+            ("third_party_app", "0001_do_awesome"),
         ]
 
 Prefer using ``dependencies`` over ``run_before`` when possible. You should
@@ -288,30 +292,32 @@ Here's a sample migration:
     from django.apps import apps as global_apps
     from django.db import migrations
 
+
     def forwards(apps, schema_editor):
         try:
-            OldModel = apps.get_model('old_app', 'OldModel')
+            OldModel = apps.get_model("old_app", "OldModel")
         except LookupError:
             # The old app isn't installed.
             return
 
-        NewModel = apps.get_model('new_app', 'NewModel')
+        NewModel = apps.get_model("new_app", "NewModel")
         NewModel.objects.bulk_create(
             NewModel(new_attribute=old_object.old_attribute)
             for old_object in OldModel.objects.all()
         )
 
+
     class Migration(migrations.Migration):
         operations = [
             migrations.RunPython(forwards, migrations.RunPython.noop),
         ]
         dependencies = [
-            ('myapp', '0123_the_previous_migration'),
-            ('new_app', '0001_initial'),
+            ("myapp", "0123_the_previous_migration"),
+            ("new_app", "0001_initial"),
         ]
 
-        if global_apps.is_installed('old_app'):
-            dependencies.append(('old_app', '0001_initial'))
+        if global_apps.is_installed("old_app"):
+            dependencies.append(("old_app", "0001_initial"))
 
 Also consider what you want to happen when the migration is unapplied. You
 could either do nothing (as in the example above) or remove some or all of the
@@ -345,7 +351,7 @@ For example, if we had a ``Book`` model with a ``ManyToManyField`` linking to
 
     class Migration(migrations.Migration):
         dependencies = [
-            ('core', '0001_initial'),
+            ("core", "0001_initial"),
         ]
 
         operations = [
@@ -354,52 +360,52 @@ For example, if we had a ``Book`` model with a ``ManyToManyField`` linking to
                     # Old table name from checking with sqlmigrate, new table
                     # name from AuthorBook._meta.db_table.
                     migrations.RunSQL(
-                        sql='ALTER TABLE core_book_authors RENAME TO core_authorbook',
-                        reverse_sql='ALTER TABLE core_authorbook RENAME TO core_book_authors',
+                        sql="ALTER TABLE core_book_authors RENAME TO core_authorbook",
+                        reverse_sql="ALTER TABLE core_authorbook RENAME TO core_book_authors",
                     ),
                 ],
                 state_operations=[
                     migrations.CreateModel(
-                        name='AuthorBook',
+                        name="AuthorBook",
                         fields=[
                             (
-                                'id',
+                                "id",
                                 models.AutoField(
                                     auto_created=True,
                                     primary_key=True,
                                     serialize=False,
-                                    verbose_name='ID',
+                                    verbose_name="ID",
                                 ),
                             ),
                             (
-                                'author',
+                                "author",
                                 models.ForeignKey(
                                     on_delete=django.db.models.deletion.DO_NOTHING,
-                                    to='core.Author',
+                                    to="core.Author",
                                 ),
                             ),
                             (
-                                'book',
+                                "book",
                                 models.ForeignKey(
                                     on_delete=django.db.models.deletion.DO_NOTHING,
-                                    to='core.Book',
+                                    to="core.Book",
                                 ),
                             ),
                         ],
                     ),
                     migrations.AlterField(
-                        model_name='book',
-                        name='authors',
+                        model_name="book",
+                        name="authors",
                         field=models.ManyToManyField(
-                            to='core.Author',
-                            through='core.AuthorBook',
+                            to="core.Author",
+                            through="core.AuthorBook",
                         ),
                     ),
                 ],
             ),
             migrations.AddField(
-                model_name='authorbook',
-                name='is_primary',
+                model_name="authorbook",
+                name="is_primary",
                 field=models.BooleanField(default=False),
             ),
         ]

+ 22 - 18
docs/internals/contributing/writing-code/coding-style.txt

@@ -68,20 +68,20 @@ Python style
   guide, f-strings should use only plain variable and property access, with
   prior local variable assignment for more complex cases::
 
-    # Allowed
-    f'hello {user}'
-    f'hello {user.name}'
-    f'hello {self.user.name}'
+    # Allowed
+    f"hello {user}"
+    f"hello {user.name}"
+    f"hello {self.user.name}"
 
     # Disallowed
-    f'hello {get_user()}'
-    f'you are {user.age * 365.25} days old'
+    f"hello {get_user()}"
+    f"you are {user.age * 365.25} days old"
 
     # Allowed with local variable assignment
     user = get_user()
-    f'hello {user}'
+    f"hello {user}"
     user_days_old = user.age * 365.25
-    f'you are {user_days_old} days old'
+    f"you are {user_days_old} days old"
 
   f-strings should not be used for any string that may require translation,
   including error and logging messages. In general ``format()`` is more
@@ -182,7 +182,10 @@ Imports
       # Django
       from django.http import Http404
       from django.http.response import (
-          Http404, HttpResponse, HttpResponseNotAllowed, StreamingHttpResponse,
+          Http404,
+          HttpResponse,
+          HttpResponseNotAllowed,
+          StreamingHttpResponse,
           cookie,
       )
 
@@ -195,7 +198,7 @@ Imports
       except ImportError:
           yaml = None
 
-      CONSTANT = 'foo'
+      CONSTANT = "foo"
 
 
       class Example:
@@ -272,21 +275,22 @@ Model style
           last_name = models.CharField(max_length=40)
 
           class Meta:
-              verbose_name_plural = 'people'
+              verbose_name_plural = "people"
 
   Don't do this::
 
       class Person(models.Model):
           first_name = models.CharField(max_length=20)
           last_name = models.CharField(max_length=40)
+
           class Meta:
-              verbose_name_plural = 'people'
+              verbose_name_plural = "people"
 
   Don't do this, either::
 
       class Person(models.Model):
           class Meta:
-              verbose_name_plural = 'people'
+              verbose_name_plural = "people"
 
           first_name = models.CharField(max_length=20)
           last_name = models.CharField(max_length=40)
@@ -307,11 +311,11 @@ Model style
   Example::
 
     class MyModel(models.Model):
-        DIRECTION_UP = 'U'
-        DIRECTION_DOWN = 'D'
+        DIRECTION_UP = "U"
+        DIRECTION_DOWN = "D"
         DIRECTION_CHOICES = [
-            (DIRECTION_UP, 'Up'),
-            (DIRECTION_DOWN, 'Down'),
+            (DIRECTION_UP, "Up"),
+            (DIRECTION_DOWN, "Down"),
         ]
 
 Use of ``django.conf.settings``
@@ -327,7 +331,7 @@ as follows::
 
     from django.conf import settings
 
-    settings.configure({}, SOME_SETTING='foo')
+    settings.configure({}, SOME_SETTING="foo")
 
 However, if any setting is accessed before the ``settings.configure`` line,
 this will not work. (Internally, ``settings`` is a ``LazyObject`` which

+ 4 - 1
docs/internals/contributing/writing-code/submitting-patches.txt

@@ -186,6 +186,7 @@ level:
     from django.test import ignore_warnings
     from django.utils.deprecation import RemovedInDjangoXXWarning
 
+
     @ignore_warnings(category=RemovedInDjangoXXWarning)
     def test_foo(self):
         ...
@@ -195,6 +196,7 @@ level:
     from django.test import ignore_warnings
     from django.utils.deprecation import RemovedInDjangoXXWarning
 
+
     @ignore_warnings(category=RemovedInDjangoXXWarning)
     class MyDeprecatedTests(unittest.TestCase):
         ...
@@ -203,8 +205,9 @@ You can also add a test for the deprecation warning::
 
     from django.utils.deprecation import RemovedInDjangoXXWarning
 
+
     def test_foo_deprecation_warning(self):
-        msg = 'Expected deprecation message'
+        msg = "Expected deprecation message"
         with self.assertWarnsMessage(RemovedInDjangoXXWarning, msg):
             # invoke deprecated behavior
             ...

+ 7 - 3
docs/internals/contributing/writing-code/unit-tests.txt

@@ -537,11 +537,13 @@ a temporary ``Apps`` instance. To do this, use the
     from django.test import SimpleTestCase
     from django.test.utils import isolate_apps
 
+
     class TestModelDefinition(SimpleTestCase):
-        @isolate_apps('app_label')
+        @isolate_apps("app_label")
         def test_model_definition(self):
             class TestModel(models.Model):
                 pass
+
             ...
 
 .. admonition:: Setting ``app_label``
@@ -561,8 +563,9 @@ a temporary ``Apps`` instance. To do this, use the
         from django.test import SimpleTestCase
         from django.test.utils import isolate_apps
 
+
         class TestModelDefinition(SimpleTestCase):
-            @isolate_apps('app_label', 'other_app_label')
+            @isolate_apps("app_label", "other_app_label")
             def test_model_definition(self):
                 # This model automatically receives app_label='app_label'
                 class TestModel(models.Model):
@@ -570,5 +573,6 @@ a temporary ``Apps`` instance. To do this, use the
 
                 class OtherAppModel(models.Model):
                     class Meta:
-                        app_label = 'other_app_label'
+                        app_label = "other_app_label"
+
                 ...

+ 1 - 1
docs/internals/contributing/writing-documentation.txt

@@ -519,7 +519,7 @@ example:
     with the full exception information. Each member of the list should be a tuple
     of (Full name, email address). Example::
 
-        [('John', 'john@example.com'), ('Mary', 'mary@example.com')]
+        [("John", "john@example.com"), ("Mary", "mary@example.com")]
 
     Note that Django will email *all* of these people whenever an error happens.
     See :doc:`/howto/error-reporting` for more information.

+ 2 - 2
docs/intro/contributing.txt

@@ -326,7 +326,7 @@ Navigate to Django's ``tests/shortcuts/`` folder and create a new file
 
     class MakeToastTests(SimpleTestCase):
         def test_make_toast(self):
-            self.assertEqual(make_toast(), 'toast')
+            self.assertEqual(make_toast(), "toast")
 
 This test checks that the ``make_toast()`` returns ``'toast'``.
 
@@ -375,7 +375,7 @@ Navigate to the ``django/`` folder and open the ``shortcuts.py`` file. At the
 bottom, add::
 
     def make_toast():
-        return 'toast'
+        return "toast"
 
 Now we need to make sure that the test we wrote earlier passes, so we can see
 whether the code we added is working correctly. Again, navigate to the Django

+ 17 - 12
docs/intro/overview.txt

@@ -30,12 +30,14 @@ database-schema problems. Here's a quick example:
 
     from django.db import models
 
+
     class Reporter(models.Model):
         full_name = models.CharField(max_length=70)
 
         def __str__(self):
             return self.full_name
 
+
     class Article(models.Model):
         pub_date = models.DateField()
         headline = models.CharField(max_length=200)
@@ -78,7 +80,7 @@ necessary:
     <QuerySet []>
 
     # Create a new Reporter.
-    >>> r = Reporter(full_name='John Smith')
+    >>> r = Reporter(full_name="John Smith")
 
     # Save the object into the database. You have to call save() explicitly.
     >>> r.save()
@@ -98,9 +100,9 @@ necessary:
     # Django provides a rich database lookup API.
     >>> Reporter.objects.get(id=1)
     <Reporter: John Smith>
-    >>> Reporter.objects.get(full_name__startswith='John')
+    >>> Reporter.objects.get(full_name__startswith="John")
     <Reporter: John Smith>
-    >>> Reporter.objects.get(full_name__contains='mith')
+    >>> Reporter.objects.get(full_name__contains="mith")
     <Reporter: John Smith>
     >>> Reporter.objects.get(id=2)
     Traceback (most recent call last):
@@ -109,8 +111,9 @@ necessary:
 
     # Create an article.
     >>> from datetime import date
-    >>> a = Article(pub_date=date.today(), headline='Django is cool',
-    ...     content='Yeah.', reporter=r)
+    >>> a = Article(
+    ...     pub_date=date.today(), headline="Django is cool", content="Yeah.", reporter=r
+    ... )
     >>> a.save()
 
     # Now the article is in the database.
@@ -129,11 +132,11 @@ necessary:
     # The API follows relationships as far as you need, performing efficient
     # JOINs for you behind the scenes.
     # This finds all articles by a reporter whose name starts with "John".
-    >>> Article.objects.filter(reporter__full_name__startswith='John')
+    >>> Article.objects.filter(reporter__full_name__startswith="John")
     <QuerySet [<Article: Django is cool>]>
 
     # Change an object by altering its attributes and calling save().
-    >>> r.full_name = 'Billy Goat'
+    >>> r.full_name = "Billy Goat"
     >>> r.save()
 
     # Delete an object with delete().
@@ -152,6 +155,7 @@ only step required is to register your model in the admin site:
 
     from django.db import models
 
+
     class Article(models.Model):
         pub_date = models.DateField()
         headline = models.CharField(max_length=200)
@@ -198,9 +202,9 @@ example above:
     from . import views
 
     urlpatterns = [
-        path('articles/<int:year>/', views.year_archive),
-        path('articles/<int:year>/<int:month>/', views.month_archive),
-        path('articles/<int:year>/<int:month>/<int:pk>/', views.article_detail),
+        path("articles/<int:year>/", views.year_archive),
+        path("articles/<int:year>/<int:month>/", views.month_archive),
+        path("articles/<int:year>/<int:month>/<int:pk>/", views.article_detail),
     ]
 
 The code above maps URL paths to Python callback functions ("views"). The path
@@ -237,10 +241,11 @@ and renders the template with the retrieved data. Here's an example view for
 
     from .models import Article
 
+
     def year_archive(request, year):
         a_list = Article.objects.filter(pub_date__year=year)
-        context = {'year': year, 'article_list': a_list}
-        return render(request, 'news/year_archive.html', context)
+        context = {"year": year, "article_list": a_list}
+        return render(request, "news/year_archive.html", context)
 
 This example uses Django's :doc:`template system </topics/templates>`, which has
 several powerful features but strives to stay simple enough for non-programmers

+ 2 - 2
docs/intro/reusable-apps.txt

@@ -164,12 +164,12 @@ this. For a small app like polls, this process isn't too difficult.
 
            INSTALLED_APPS = [
                ...,
-               'polls',
+               "polls",
            ]
 
        2. Include the polls URLconf in your project urls.py like this::
 
-           path('polls/', include('polls.urls')),
+           path("polls/", include("polls.urls")),
 
        3. Run ``python manage.py migrate`` to create the polls models.
 

+ 3 - 3
docs/intro/tutorial01.txt

@@ -286,7 +286,7 @@ In the ``polls/urls.py`` file include the following code:
     from . import views
 
     urlpatterns = [
-        path('', views.index, name='index'),
+        path("", views.index, name="index"),
     ]
 
 The next step is to point the root URLconf at the ``polls.urls`` module. In
@@ -300,8 +300,8 @@ The next step is to point the root URLconf at the ``polls.urls`` module. In
     from django.urls import include, path
 
     urlpatterns = [
-        path('polls/', include('polls.urls')),
-        path('admin/', admin.site.urls),
+        path("polls/", include("polls.urls")),
+        path("admin/", admin.site.urls),
     ]
 
 The :func:`~django.urls.include` function allows referencing other URLconfs.

+ 15 - 13
docs/intro/tutorial02.txt

@@ -148,7 +148,7 @@ These concepts are represented by Python classes. Edit the
 
     class Question(models.Model):
         question_text = models.CharField(max_length=200)
-        pub_date = models.DateTimeField('date published')
+        pub_date = models.DateTimeField("date published")
 
 
     class Choice(models.Model):
@@ -220,13 +220,13 @@ this:
     :caption: ``mysite/settings.py``
 
     INSTALLED_APPS = [
-        'polls.apps.PollsConfig',
-        'django.contrib.admin',
-        'django.contrib.auth',
-        'django.contrib.contenttypes',
-        'django.contrib.sessions',
-        'django.contrib.messages',
-        'django.contrib.staticfiles',
+        "polls.apps.PollsConfig",
+        "django.contrib.admin",
+        "django.contrib.auth",
+        "django.contrib.contenttypes",
+        "django.contrib.sessions",
+        "django.contrib.messages",
+        "django.contrib.staticfiles",
     ]
 
 Now Django knows to include the ``polls`` app. Let's run another command:
@@ -430,11 +430,13 @@ representation of this object. Let's fix that by editing the ``Question`` model
 
     from django.db import models
 
+
     class Question(models.Model):
         # ...
         def __str__(self):
             return self.question_text
 
+
     class Choice(models.Model):
         # ...
         def __str__(self):
@@ -484,7 +486,7 @@ Save these changes and start a new Python interactive shell by running
     # keyword arguments.
     >>> Question.objects.filter(id=1)
     <QuerySet [<Question: What's up?>]>
-    >>> Question.objects.filter(question_text__startswith='What')
+    >>> Question.objects.filter(question_text__startswith="What")
     <QuerySet [<Question: What's up?>]>
 
     # Get the question that was published this year.
@@ -522,11 +524,11 @@ Save these changes and start a new Python interactive shell by running
     <QuerySet []>
 
     # Create three choices.
-    >>> q.choice_set.create(choice_text='Not much', votes=0)
+    >>> q.choice_set.create(choice_text="Not much", votes=0)
     <Choice: Not much>
-    >>> q.choice_set.create(choice_text='The sky', votes=0)
+    >>> q.choice_set.create(choice_text="The sky", votes=0)
     <Choice: The sky>
-    >>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)
+    >>> c = q.choice_set.create(choice_text="Just hacking again", votes=0)
 
     # Choice objects have API access to their related Question objects.
     >>> c.question
@@ -547,7 +549,7 @@ Save these changes and start a new Python interactive shell by running
     <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
 
     # Let's delete one of the choices. Use delete() for that.
-    >>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
+    >>> c = q.choice_set.filter(choice_text__startswith="Just hacking")
     >>> c.delete()
 
 For more information on model relations, see :doc:`Accessing related objects

+ 28 - 21
docs/intro/tutorial03.txt

@@ -75,10 +75,12 @@ slightly different, because they take an argument:
     def detail(request, question_id):
         return HttpResponse("You're looking at question %s." % question_id)
 
+
     def results(request, question_id):
         response = "You're looking at the results of question %s."
         return HttpResponse(response % question_id)
 
+
     def vote(request, question_id):
         return HttpResponse("You're voting on question %s." % question_id)
 
@@ -94,13 +96,13 @@ Wire these new views into the ``polls.urls`` module by adding the following
 
     urlpatterns = [
         # ex: /polls/
-        path('', views.index, name='index'),
+        path("", views.index, name="index"),
         # ex: /polls/5/
-        path('<int:question_id>/', views.detail, name='detail'),
+        path("<int:question_id>/", views.detail, name="detail"),
         # ex: /polls/5/results/
-        path('<int:question_id>/results/', views.results, name='results'),
+        path("<int:question_id>/results/", views.results, name="results"),
         # ex: /polls/5/vote/
-        path('<int:question_id>/vote/', views.vote, name='vote'),
+        path("<int:question_id>/vote/", views.vote, name="vote"),
     ]
 
 Take a look in your browser, at "/polls/34/". It'll run the ``detail()``
@@ -157,10 +159,11 @@ commas, according to publication date:
 
 
     def index(request):
-        latest_question_list = Question.objects.order_by('-pub_date')[:5]
-        output = ', '.join([q.question_text for q in latest_question_list])
+        latest_question_list = Question.objects.order_by("-pub_date")[:5]
+        output = ", ".join([q.question_text for q in latest_question_list])
         return HttpResponse(output)
 
+
     # Leave the rest of the views (detail, results, vote) unchanged
 
 There's a problem here, though: the page's design is hard-coded in the view. If
@@ -229,10 +232,10 @@ Now let's update our ``index`` view in ``polls/views.py`` to use the template:
 
 
     def index(request):
-        latest_question_list = Question.objects.order_by('-pub_date')[:5]
-        template = loader.get_template('polls/index.html')
+        latest_question_list = Question.objects.order_by("-pub_date")[:5]
+        template = loader.get_template("polls/index.html")
         context = {
-            'latest_question_list': latest_question_list,
+            "latest_question_list": latest_question_list,
         }
         return HttpResponse(template.render(context, request))
 
@@ -261,9 +264,9 @@ rewritten:
 
 
     def index(request):
-        latest_question_list = Question.objects.order_by('-pub_date')[:5]
-        context = {'latest_question_list': latest_question_list}
-        return render(request, 'polls/index.html', context)
+        latest_question_list = Question.objects.order_by("-pub_date")[:5]
+        context = {"latest_question_list": latest_question_list}
+        return render(request, "polls/index.html", context)
 
 Note that once we've done this in all these views, we no longer need to import
 :mod:`~django.template.loader` and :class:`~django.http.HttpResponse` (you'll
@@ -288,13 +291,15 @@ for a given poll. Here's the view:
     from django.shortcuts import render
 
     from .models import Question
+
+
     # ...
     def detail(request, question_id):
         try:
             question = Question.objects.get(pk=question_id)
         except Question.DoesNotExist:
             raise Http404("Question does not exist")
-        return render(request, 'polls/detail.html', {'question': question})
+        return render(request, "polls/detail.html", {"question": question})
 
 The new concept here: The view raises the :exc:`~django.http.Http404` exception
 if a question with the requested ID doesn't exist.
@@ -323,10 +328,12 @@ provides a shortcut. Here's the ``detail()`` view, rewritten:
     from django.shortcuts import get_object_or_404, render
 
     from .models import Question
+
+
     # ...
     def detail(request, question_id):
         question = get_object_or_404(Question, pk=question_id)
-        return render(request, 'polls/detail.html', {'question': question})
+        return render(request, "polls/detail.html", {"question": question})
 
 The :func:`~django.shortcuts.get_object_or_404` function takes a Django model
 as its first argument and an arbitrary number of keyword arguments, which it
@@ -408,7 +415,7 @@ defined below::
 
     ...
     # the 'name' value as called by the {% url %} template tag
-    path('<int:question_id>/', views.detail, name='detail'),
+    path("<int:question_id>/", views.detail, name="detail"),
     ...
 
 If you want to change the URL of the polls detail view to something else,
@@ -417,7 +424,7 @@ template (or templates) you would change it in ``polls/urls.py``::
 
     ...
     # added the word 'specifics'
-    path('specifics/<int:question_id>/', views.detail, name='detail'),
+    path("specifics/<int:question_id>/", views.detail, name="detail"),
     ...
 
 Namespacing URL names
@@ -440,12 +447,12 @@ file, go ahead and add an ``app_name`` to set the application namespace:
 
     from . import views
 
-    app_name = 'polls'
+    app_name = "polls"
     urlpatterns = [
-        path('', views.index, name='index'),
-        path('<int:question_id>/', views.detail, name='detail'),
-        path('<int:question_id>/results/', views.results, name='results'),
-        path('<int:question_id>/vote/', views.vote, name='vote'),
+        path("", views.index, name="index"),
+        path("<int:question_id>/", views.detail, name="detail"),
+        path("<int:question_id>/results/", views.results, name="results"),
+        path("<int:question_id>/vote/", views.vote, name="vote"),
     ]
 
 Now change your ``polls/index.html`` template from:

+ 26 - 20
docs/intro/tutorial04.txt

@@ -66,7 +66,7 @@ created a URLconf for the polls application that includes this line:
 .. code-block:: python
     :caption: ``polls/urls.py``
 
-    path('<int:question_id>/vote/', views.vote, name='vote'),
+    path("<int:question_id>/vote/", views.vote, name="vote"),
 
 We also created a dummy implementation of the ``vote()`` function. Let's
 create a real version. Add the following to ``polls/views.py``:
@@ -79,24 +79,30 @@ create a real version. Add the following to ``polls/views.py``:
     from django.urls import reverse
 
     from .models import Choice, Question
+
+
     # ...
     def vote(request, question_id):
         question = get_object_or_404(Question, pk=question_id)
         try:
-            selected_choice = question.choice_set.get(pk=request.POST['choice'])
+            selected_choice = question.choice_set.get(pk=request.POST["choice"])
         except (KeyError, Choice.DoesNotExist):
             # Redisplay the question voting form.
-            return render(request, 'polls/detail.html', {
-                'question': question,
-                'error_message': "You didn't select a choice.",
-            })
+            return render(
+                request,
+                "polls/detail.html",
+                {
+                    "question": question,
+                    "error_message": "You didn't select a choice.",
+                },
+            )
         else:
             selected_choice.votes += 1
             selected_choice.save()
             # Always return an HttpResponseRedirect after successfully dealing
             # with POST data. This prevents data from being posted twice if a
             # user hits the Back button.
-            return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
+            return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))
 
 This code includes a few things we haven't covered yet in this tutorial:
 
@@ -138,7 +144,7 @@ This code includes a few things we haven't covered yet in this tutorial:
   this :func:`~django.urls.reverse` call will return a string like
   ::
 
-    '/polls/3/results/'
+    "/polls/3/results/"
 
   where the ``3`` is the value of ``question.id``. This redirected URL will
   then call the ``'results'`` view to display the final page.
@@ -159,7 +165,7 @@ page for the question. Let's write that view:
 
     def results(request, question_id):
         question = get_object_or_404(Question, pk=question_id)
-        return render(request, 'polls/results.html', {'question': question})
+        return render(request, "polls/results.html", {"question": question})
 
 This is almost exactly the same as the ``detail()`` view from :doc:`Tutorial 3
 </intro/tutorial03>`. The only difference is the template name. We'll fix this
@@ -246,12 +252,12 @@ First, open the ``polls/urls.py`` URLconf and change it like so:
 
     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('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
-        path('<int:question_id>/vote/', views.vote, name='vote'),
+        path("", views.IndexView.as_view(), name="index"),
+        path("<int:pk>/", views.DetailView.as_view(), name="detail"),
+        path("<int:pk>/results/", views.ResultsView.as_view(), name="results"),
+        path("<int:question_id>/vote/", views.vote, name="vote"),
     ]
 
 Note that the name of the matched pattern in the path strings of the second and
@@ -276,26 +282,26 @@ views and use Django's generic views instead. To do so, open the
 
 
     class IndexView(generic.ListView):
-        template_name = 'polls/index.html'
-        context_object_name = 'latest_question_list'
+        template_name = "polls/index.html"
+        context_object_name = "latest_question_list"
 
         def get_queryset(self):
             """Return the last five published questions."""
-            return Question.objects.order_by('-pub_date')[:5]
+            return Question.objects.order_by("-pub_date")[:5]
 
 
     class DetailView(generic.DetailView):
         model = Question
-        template_name = 'polls/detail.html'
+        template_name = "polls/detail.html"
 
 
     class ResultsView(generic.DetailView):
         model = Question
-        template_name = 'polls/results.html'
+        template_name = "polls/results.html"
 
 
     def vote(request, question_id):
-        ... # same as above, no changes needed.
+        ...  # same as above, no changes needed.
 
 We're using two generic views here:
 :class:`~django.views.generic.list.ListView` and

+ 25 - 24
docs/intro/tutorial05.txt

@@ -183,7 +183,6 @@ Put the following in the ``tests.py`` file in the ``polls`` application:
 
 
     class QuestionModelTests(TestCase):
-
         def test_was_published_recently_with_future_question(self):
             """
             was_published_recently() returns False for questions whose pub_date
@@ -312,6 +311,7 @@ more comprehensively:
         old_question = Question(pub_date=time)
         self.assertIs(old_question.was_published_recently(), False)
 
+
     def test_was_published_recently_with_recent_question(self):
         """
         was_published_recently() returns True for questions whose pub_date
@@ -393,7 +393,7 @@ With that ready, we can ask the client to do some work for us:
 .. code-block:: pycon
 
     >>> # get a response from '/'
-    >>> response = client.get('/')
+    >>> response = client.get("/")
     Not Found: /
     >>> # we should expect a 404 from that address; if you instead see an
     >>> # "Invalid HTTP_HOST header" error and a 400 response, you probably
@@ -403,12 +403,12 @@ With that ready, we can ask the client to do some work for us:
     >>> # on the other hand we should expect to find something at '/polls/'
     >>> # we'll use 'reverse()' rather than a hardcoded URL
     >>> from django.urls import reverse
-    >>> response = client.get(reverse('polls:index'))
+    >>> response = client.get(reverse("polls:index"))
     >>> response.status_code
     200
     >>> response.content
     b'\n    <ul>\n    \n        <li><a href="/polls/1/">What&#x27;s up?</a></li>\n    \n    </ul>\n\n'
-    >>> response.context['latest_question_list']
+    >>> response.context["latest_question_list"]
     <QuerySet [<Question: What's up?>]>
 
 Improving our view
@@ -424,12 +424,12 @@ based on :class:`~django.views.generic.list.ListView`:
     :caption: ``polls/views.py``
 
     class IndexView(generic.ListView):
-        template_name = 'polls/index.html'
-        context_object_name = 'latest_question_list'
+        template_name = "polls/index.html"
+        context_object_name = "latest_question_list"
 
         def get_queryset(self):
             """Return the last five published questions."""
-            return Question.objects.order_by('-pub_date')[:5]
+            return Question.objects.order_by("-pub_date")[:5]
 
 We need to amend the ``get_queryset()`` method and change it so that it also
 checks the date by comparing it with ``timezone.now()``. First we need to add
@@ -450,9 +450,9 @@ and then we must amend the ``get_queryset`` method like so:
         Return the last five published questions (not including those set to be
         published in the future).
         """
-        return Question.objects.filter(
-            pub_date__lte=timezone.now()
-        ).order_by('-pub_date')[:5]
+        return Question.objects.filter(pub_date__lte=timezone.now()).order_by("-pub_date")[
+            :5
+        ]
 
 ``Question.objects.filter(pub_date__lte=timezone.now())`` returns a queryset
 containing ``Question``\s whose ``pub_date`` is less than or equal to - that
@@ -496,10 +496,10 @@ class:
             """
             If no questions exist, an appropriate message is displayed.
             """
-            response = self.client.get(reverse('polls:index'))
+            response = self.client.get(reverse("polls:index"))
             self.assertEqual(response.status_code, 200)
             self.assertContains(response, "No polls are available.")
-            self.assertQuerySetEqual(response.context['latest_question_list'], [])
+            self.assertQuerySetEqual(response.context["latest_question_list"], [])
 
         def test_past_question(self):
             """
@@ -507,9 +507,9 @@ class:
             index page.
             """
             question = create_question(question_text="Past question.", days=-30)
-            response = self.client.get(reverse('polls:index'))
+            response = self.client.get(reverse("polls:index"))
             self.assertQuerySetEqual(
-                response.context['latest_question_list'],
+                response.context["latest_question_list"],
                 [question],
             )
 
@@ -519,9 +519,9 @@ class:
             the index page.
             """
             create_question(question_text="Future question.", days=30)
-            response = self.client.get(reverse('polls:index'))
+            response = self.client.get(reverse("polls:index"))
             self.assertContains(response, "No polls are available.")
-            self.assertQuerySetEqual(response.context['latest_question_list'], [])
+            self.assertQuerySetEqual(response.context["latest_question_list"], [])
 
         def test_future_question_and_past_question(self):
             """
@@ -530,9 +530,9 @@ class:
             """
             question = create_question(question_text="Past question.", days=-30)
             create_question(question_text="Future question.", days=30)
-            response = self.client.get(reverse('polls:index'))
+            response = self.client.get(reverse("polls:index"))
             self.assertQuerySetEqual(
-                response.context['latest_question_list'],
+                response.context["latest_question_list"],
                 [question],
             )
 
@@ -542,9 +542,9 @@ class:
             """
             question1 = create_question(question_text="Past question 1.", days=-30)
             question2 = create_question(question_text="Past question 2.", days=-5)
-            response = self.client.get(reverse('polls:index'))
+            response = self.client.get(reverse("polls:index"))
             self.assertQuerySetEqual(
-                response.context['latest_question_list'],
+                response.context["latest_question_list"],
                 [question2, question1],
             )
 
@@ -584,6 +584,7 @@ we need to add a similar  constraint to ``DetailView``:
 
     class DetailView(generic.DetailView):
         ...
+
         def get_queryset(self):
             """
             Excludes any questions that aren't published yet.
@@ -603,8 +604,8 @@ is not:
             The detail view of a question with a pub_date in the future
             returns a 404 not found.
             """
-            future_question = create_question(question_text='Future question.', days=5)
-            url = reverse('polls:detail', args=(future_question.id,))
+            future_question = create_question(question_text="Future question.", days=5)
+            url = reverse("polls:detail", args=(future_question.id,))
             response = self.client.get(url)
             self.assertEqual(response.status_code, 404)
 
@@ -613,8 +614,8 @@ is not:
             The detail view of a question with a pub_date in the past
             displays the question's text.
             """
-            past_question = create_question(question_text='Past Question.', days=-5)
-            url = reverse('polls:detail', args=(past_question.id,))
+            past_question = create_question(question_text="Past Question.", days=-5)
+            url = reverse("polls:detail", args=(past_question.id,))
             response = self.client.get(url)
             self.assertContains(response, past_question.question_text)
 

+ 25 - 20
docs/intro/tutorial07.txt

@@ -32,7 +32,8 @@ the ``admin.site.register(Question)`` line with:
 
 
     class QuestionAdmin(admin.ModelAdmin):
-        fields = ['pub_date', 'question_text']
+        fields = ["pub_date", "question_text"]
+
 
     admin.site.register(Question, QuestionAdmin)
 
@@ -62,10 +63,11 @@ up into fieldsets:
 
     class QuestionAdmin(admin.ModelAdmin):
         fieldsets = [
-            (None,               {'fields': ['question_text']}),
-            ('Date information', {'fields': ['pub_date']}),
+            (None, {"fields": ["question_text"]}),
+            ("Date information", {"fields": ["pub_date"]}),
         ]
 
+
     admin.site.register(Question, QuestionAdmin)
 
 The first element of each tuple in
@@ -92,6 +94,7 @@ with the admin just as we did with ``Question``:
     from django.contrib import admin
 
     from .models import Choice, Question
+
     # ...
     admin.site.register(Choice)
 
@@ -135,11 +138,12 @@ registration code to read:
 
     class QuestionAdmin(admin.ModelAdmin):
         fieldsets = [
-            (None,               {'fields': ['question_text']}),
-            ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
+            (None, {"fields": ["question_text"]}),
+            ("Date information", {"fields": ["pub_date"], "classes": ["collapse"]}),
         ]
         inlines = [ChoiceInline]
 
+
     admin.site.register(Question, QuestionAdmin)
 
 This tells Django: "``Choice`` objects are edited on the ``Question`` admin page. By
@@ -204,7 +208,7 @@ object:
 
     class QuestionAdmin(admin.ModelAdmin):
         # ...
-        list_display = ['question_text', 'pub_date']
+        list_display = ["question_text", "pub_date"]
 
 For good measure, let's also include the ``was_published_recently()`` method
 from :doc:`Tutorial 2 </intro/tutorial02>`:
@@ -214,7 +218,7 @@ from :doc:`Tutorial 2 </intro/tutorial02>`:
 
     class QuestionAdmin(admin.ModelAdmin):
         # ...
-        list_display = ['question_text', 'pub_date', 'was_published_recently']
+        list_display = ["question_text", "pub_date", "was_published_recently"]
 
 Now the question change list page looks like this:
 
@@ -236,12 +240,13 @@ decorator on that method (in :file:`polls/models.py`), as follows:
 
     from django.contrib import admin
 
+
     class Question(models.Model):
         # ...
         @admin.display(
             boolean=True,
-            ordering='pub_date',
-            description='Published recently?',
+            ordering="pub_date",
+            description="Published recently?",
         )
         def was_published_recently(self):
             now = timezone.now()
@@ -255,7 +260,7 @@ Edit your :file:`polls/admin.py` file again and add an improvement to the
 :attr:`~django.contrib.admin.ModelAdmin.list_filter`. Add the following line to
 ``QuestionAdmin``::
 
-    list_filter = ['pub_date']
+    list_filter = ["pub_date"]
 
 That adds a "Filter" sidebar that lets people filter the change list by the
 ``pub_date`` field:
@@ -270,7 +275,7 @@ knows to give appropriate filter options: "Any date", "Today", "Past 7 days",
 
 This is shaping up well. Let's add some search capability::
 
-    search_fields = ['question_text']
+    search_fields = ["question_text"]
 
 That adds a search box at the top of the change list. When somebody enters
 search terms, Django will search the ``question_text`` field. You can use as many
@@ -314,15 +319,15 @@ Open your settings file (:file:`mysite/settings.py`, remember) and add a
 
     TEMPLATES = [
         {
-            'BACKEND': 'django.template.backends.django.DjangoTemplates',
-            'DIRS': [BASE_DIR / 'templates'],
-            'APP_DIRS': True,
-            'OPTIONS': {
-                'context_processors': [
-                    'django.template.context_processors.debug',
-                    'django.template.context_processors.request',
-                    'django.contrib.auth.context_processors.auth',
-                    'django.contrib.messages.context_processors.messages',
+            "BACKEND": "django.template.backends.django.DjangoTemplates",
+            "DIRS": [BASE_DIR / "templates"],
+            "APP_DIRS": True,
+            "OPTIONS": {
+                "context_processors": [
+                    "django.template.context_processors.debug",
+                    "django.template.context_processors.request",
+                    "django.contrib.auth.context_processors.auth",
+                    "django.contrib.messages.context_processors.messages",
                 ],
             },
         },

+ 10 - 6
docs/ref/applications.txt

@@ -14,7 +14,7 @@ This registry is called :attr:`~django.apps.apps` and it's available in
 .. code-block:: pycon
 
     >>> from django.apps import apps
-    >>> apps.get_app_config('admin').verbose_name
+    >>> apps.get_app_config("admin").verbose_name
     'Administration'
 
 Projects and applications
@@ -77,7 +77,7 @@ configuration class to specify it explicitly::
 
     INSTALLED_APPS = [
         ...,
-        'polls.apps.PollsAppConfig',
+        "polls.apps.PollsAppConfig",
         ...,
     ]
 
@@ -91,8 +91,9 @@ would provide a proper name for the admin::
 
     from django.apps import AppConfig
 
+
     class RockNRollConfig(AppConfig):
-        name = 'rock_n_roll'
+        name = "rock_n_roll"
         verbose_name = "Rock ’n’ roll"
 
 ``RockNRollConfig`` will be loaded automatically when :setting:`INSTALLED_APPS`
@@ -134,13 +135,15 @@ configuration::
 
     from rock_n_roll.apps import RockNRollConfig
 
+
     class JazzManoucheConfig(RockNRollConfig):
         verbose_name = "Jazz Manouche"
 
+
     # anthology/settings.py
 
     INSTALLED_APPS = [
-        'anthology.apps.JazzManoucheConfig',
+        "anthology.apps.JazzManoucheConfig",
         # ...
     ]
 
@@ -289,10 +292,11 @@ Methods
             def ready(self):
                 # importing model classes
                 from .models import MyModel  # or...
-                MyModel = self.get_model('MyModel')
+
+                MyModel = self.get_model("MyModel")
 
                 # registering signals with the model's string label
-                pre_save.connect(receiver, sender='app_label.MyModel')
+                pre_save.connect(receiver, sender="app_label.MyModel")
 
     .. warning::
 

+ 21 - 13
docs/ref/class-based-views/base.txt

@@ -34,10 +34,10 @@ MRO is an acronym for Method Resolution Order.
         from django.http import HttpResponse
         from django.views import View
 
-        class MyView(View):
 
+        class MyView(View):
             def get(self, request, *args, **kwargs):
-                return HttpResponse('Hello, World!')
+                return HttpResponse("Hello, World!")
 
     **Example urls.py**::
 
@@ -46,7 +46,7 @@ MRO is an acronym for Method Resolution Order.
         from myapp.views import MyView
 
         urlpatterns = [
-            path('mine/', MyView.as_view(), name='my-view'),
+            path("mine/", MyView.as_view(), name="my-view"),
         ]
 
     **Attributes**
@@ -57,7 +57,7 @@ MRO is an acronym for Method Resolution Order.
 
         Default::
 
-            ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
+            ["get", "post", "put", "patch", "delete", "head", "options", "trace"]
 
     **Methods**
 
@@ -150,13 +150,13 @@ MRO is an acronym for Method Resolution Order.
 
         from articles.models import Article
 
-        class HomePageView(TemplateView):
 
+        class HomePageView(TemplateView):
             template_name = "home.html"
 
             def get_context_data(self, **kwargs):
                 context = super().get_context_data(**kwargs)
-                context['latest_articles'] = Article.objects.all()[:5]
+                context["latest_articles"] = Article.objects.all()[:5]
                 return context
 
     **Example urls.py**::
@@ -166,7 +166,7 @@ MRO is an acronym for Method Resolution Order.
         from myapp.views import HomePageView
 
         urlpatterns = [
-            path('', HomePageView.as_view(), name='home'),
+            path("", HomePageView.as_view(), name="home"),
         ]
 
     **Context**
@@ -213,14 +213,14 @@ MRO is an acronym for Method Resolution Order.
 
         from articles.models import Article
 
-        class ArticleCounterRedirectView(RedirectView):
 
+        class ArticleCounterRedirectView(RedirectView):
             permanent = False
             query_string = True
-            pattern_name = 'article-detail'
+            pattern_name = "article-detail"
 
             def get_redirect_url(self, *args, **kwargs):
-                article = get_object_or_404(Article, pk=kwargs['pk'])
+                article = get_object_or_404(Article, pk=kwargs["pk"])
                 article.update_counter()
                 return super().get_redirect_url(*args, **kwargs)
 
@@ -232,9 +232,17 @@ MRO is an acronym for Method Resolution Order.
         from article.views import ArticleCounterRedirectView, ArticleDetailView
 
         urlpatterns = [
-            path('counter/<int:pk>/', ArticleCounterRedirectView.as_view(), name='article-counter'),
-            path('details/<int:pk>/', ArticleDetailView.as_view(), name='article-detail'),
-            path('go-to-django/', RedirectView.as_view(url='https://www.djangoproject.com/'), name='go-to-django'),
+            path(
+                "counter/<int:pk>/",
+                ArticleCounterRedirectView.as_view(),
+                name="article-counter",
+            ),
+            path("details/<int:pk>/", ArticleDetailView.as_view(), name="article-detail"),
+            path(
+                "go-to-django/",
+                RedirectView.as_view(url="https://www.djangoproject.com/"),
+                name="go-to-django",
+            ),
         ]
 
     **Attributes**

+ 39 - 25
docs/ref/class-based-views/generic-date-based.txt

@@ -15,12 +15,13 @@ views for displaying drilldown pages for date-based data.
         from django.db import models
         from django.urls import reverse
 
+
         class Article(models.Model):
             title = models.CharField(max_length=200)
             pub_date = models.DateField()
 
             def get_absolute_url(self):
-                return reverse('article-detail', kwargs={'pk': self.pk})
+                return reverse("article-detail", kwargs={"pk": self.pk})
 
 ``ArchiveIndexView``
 ====================
@@ -69,9 +70,11 @@ views for displaying drilldown pages for date-based data.
         from myapp.models import Article
 
         urlpatterns = [
-            path('archive/',
-                 ArchiveIndexView.as_view(model=Article, date_field="pub_date"),
-                 name="article_archive"),
+            path(
+                "archive/",
+                ArchiveIndexView.as_view(model=Article, date_field="pub_date"),
+                name="article_archive",
+            ),
         ]
 
     **Example myapp/article_archive.html**:
@@ -154,6 +157,7 @@ views for displaying drilldown pages for date-based data.
 
         from myapp.models import Article
 
+
         class ArticleYearArchiveView(YearArchiveView):
             queryset = Article.objects.all()
             date_field = "pub_date"
@@ -167,9 +171,7 @@ views for displaying drilldown pages for date-based data.
         from myapp.views import ArticleYearArchiveView
 
         urlpatterns = [
-            path('<int:year>/',
-                 ArticleYearArchiveView.as_view(),
-                 name="article_year_archive"),
+            path("<int:year>/", ArticleYearArchiveView.as_view(), name="article_year_archive"),
         ]
 
     **Example myapp/article_archive_year.html**:
@@ -247,6 +249,7 @@ views for displaying drilldown pages for date-based data.
 
         from myapp.models import Article
 
+
         class ArticleMonthArchiveView(MonthArchiveView):
             queryset = Article.objects.all()
             date_field = "pub_date"
@@ -260,13 +263,17 @@ views for displaying drilldown pages for date-based data.
 
         urlpatterns = [
             # Example: /2012/08/
-            path('<int:year>/<int:month>/',
-                 ArticleMonthArchiveView.as_view(month_format='%m'),
-                 name="archive_month_numeric"),
+            path(
+                "<int:year>/<int:month>/",
+                ArticleMonthArchiveView.as_view(month_format="%m"),
+                name="archive_month_numeric",
+            ),
             # Example: /2012/aug/
-            path('<int:year>/<str:month>/',
-                 ArticleMonthArchiveView.as_view(),
-                 name="archive_month"),
+            path(
+                "<int:year>/<str:month>/",
+                ArticleMonthArchiveView.as_view(),
+                name="archive_month",
+            ),
         ]
 
     **Example myapp/article_archive_month.html**:
@@ -350,6 +357,7 @@ views for displaying drilldown pages for date-based data.
 
         from myapp.models import Article
 
+
         class ArticleWeekArchiveView(WeekArchiveView):
             queryset = Article.objects.all()
             date_field = "pub_date"
@@ -364,9 +372,11 @@ views for displaying drilldown pages for date-based data.
 
         urlpatterns = [
             # Example: /2012/week/23/
-            path('<int:year>/week/<int:week>/',
-                 ArticleWeekArchiveView.as_view(),
-                 name="archive_week"),
+            path(
+                "<int:year>/week/<int:week>/",
+                ArticleWeekArchiveView.as_view(),
+                name="archive_week",
+            ),
         ]
 
     **Example myapp/article_archive_week.html**:
@@ -463,6 +473,7 @@ views for displaying drilldown pages for date-based data.
 
         from myapp.models import Article
 
+
         class ArticleDayArchiveView(DayArchiveView):
             queryset = Article.objects.all()
             date_field = "pub_date"
@@ -476,9 +487,11 @@ views for displaying drilldown pages for date-based data.
 
         urlpatterns = [
             # Example: /2012/nov/10/
-            path('<int:year>/<str:month>/<int:day>/',
-                 ArticleDayArchiveView.as_view(),
-                 name="archive_day"),
+            path(
+                "<int:year>/<str:month>/<int:day>/",
+                ArticleDayArchiveView.as_view(),
+                name="archive_day",
+            ),
         ]
 
     **Example myapp/article_archive_day.html**:
@@ -536,6 +549,7 @@ views for displaying drilldown pages for date-based data.
 
         from myapp.models import Article
 
+
         class ArticleTodayArchiveView(TodayArchiveView):
             queryset = Article.objects.all()
             date_field = "pub_date"
@@ -548,9 +562,7 @@ views for displaying drilldown pages for date-based data.
         from myapp.views import ArticleTodayArchiveView
 
         urlpatterns = [
-            path('today/',
-                 ArticleTodayArchiveView.as_view(),
-                 name="archive_today"),
+            path("today/", ArticleTodayArchiveView.as_view(), name="archive_today"),
         ]
 
     .. admonition:: Where is the example template for ``TodayArchiveView``?
@@ -597,9 +609,11 @@ views for displaying drilldown pages for date-based data.
         from django.views.generic.dates import DateDetailView
 
         urlpatterns = [
-            path('<int:year>/<str:month>/<int:day>/<int:pk>/',
-                 DateDetailView.as_view(model=Article, date_field="pub_date"),
-                 name="archive_date_detail"),
+            path(
+                "<int:year>/<str:month>/<int:day>/<int:pk>/",
+                DateDetailView.as_view(model=Article, date_field="pub_date"),
+                name="archive_date_detail",
+            ),
         ]
 
     **Example myapp/article_detail.html**:

+ 6 - 6
docs/ref/class-based-views/generic-display.txt

@@ -44,13 +44,13 @@ many projects they are typically the most commonly used views.
 
         from articles.models import Article
 
-        class ArticleDetailView(DetailView):
 
+        class ArticleDetailView(DetailView):
             model = Article
 
             def get_context_data(self, **kwargs):
                 context = super().get_context_data(**kwargs)
-                context['now'] = timezone.now()
+                context["now"] = timezone.now()
                 return context
 
     **Example myapp/urls.py**::
@@ -60,7 +60,7 @@ many projects they are typically the most commonly used views.
         from article.views import ArticleDetailView
 
         urlpatterns = [
-            path('<slug:slug>/', ArticleDetailView.as_view(), name='article-detail'),
+            path("<slug:slug>/", ArticleDetailView.as_view(), name="article-detail"),
         ]
 
     **Example myapp/article_detail.html**:
@@ -133,14 +133,14 @@ many projects they are typically the most commonly used views.
 
         from articles.models import Article
 
-        class ArticleListView(ListView):
 
+        class ArticleListView(ListView):
             model = Article
             paginate_by = 100  # if pagination is desired
 
             def get_context_data(self, **kwargs):
                 context = super().get_context_data(**kwargs)
-                context['now'] = timezone.now()
+                context["now"] = timezone.now()
                 return context
 
     **Example myapp/urls.py**::
@@ -150,7 +150,7 @@ many projects they are typically the most commonly used views.
         from article.views import ArticleListView
 
         urlpatterns = [
-            path('', ArticleListView.as_view(), name='article-list'),
+            path("", ArticleListView.as_view(), name="article-list"),
         ]
 
     **Example myapp/article_list.html**:

+ 13 - 7
docs/ref/class-based-views/generic-editing.txt

@@ -24,11 +24,12 @@ editing content:
         from django.db import models
         from django.urls import reverse
 
+
         class Author(models.Model):
             name = models.CharField(max_length=200)
 
             def get_absolute_url(self):
-                return reverse('author-detail', kwargs={'pk': self.pk})
+                return reverse("author-detail", kwargs={"pk": self.pk})
 
 ``FormView``
 ============
@@ -52,6 +53,7 @@ editing content:
 
         from django import forms
 
+
         class ContactForm(forms.Form):
             name = forms.CharField()
             message = forms.CharField(widget=forms.Textarea)
@@ -65,10 +67,11 @@ editing content:
         from myapp.forms import ContactForm
         from django.views.generic.edit import FormView
 
+
         class ContactFormView(FormView):
-            template_name = 'contact.html'
+            template_name = "contact.html"
             form_class = ContactForm
-            success_url = '/thanks/'
+            success_url = "/thanks/"
 
             def form_valid(self, form):
                 # This method is called when valid form data has been POSTed.
@@ -141,9 +144,10 @@ editing content:
         from django.views.generic.edit import CreateView
         from myapp.models import Author
 
+
         class AuthorCreateView(CreateView):
             model = Author
-            fields = ['name']
+            fields = ["name"]
 
     **Example myapp/author_form.html**:
 
@@ -220,10 +224,11 @@ editing content:
         from django.views.generic.edit import UpdateView
         from myapp.models import Author
 
+
         class AuthorUpdateView(UpdateView):
             model = Author
-            fields = ['name']
-            template_name_suffix = '_update_form'
+            fields = ["name"]
+            template_name_suffix = "_update_form"
 
     **Example myapp/author_update_form.html**:
 
@@ -307,9 +312,10 @@ editing content:
         from django.views.generic.edit import DeleteView
         from myapp.models import Author
 
+
         class AuthorDeleteView(DeleteView):
             model = Author
-            success_url = reverse_lazy('author-list')
+            success_url = reverse_lazy("author-list")
 
     **Example myapp/author_confirm_delete.html**:
 

+ 1 - 1
docs/ref/class-based-views/index.txt

@@ -26,7 +26,7 @@ A class-based view is deployed into a URL pattern using the
 :meth:`~django.views.generic.base.View.as_view()` classmethod::
 
     urlpatterns = [
-        path('view/', MyView.as_view(size=42)),
+        path("view/", MyView.as_view(size=42)),
     ]
 
 .. admonition:: Thread safety with view arguments

+ 1 - 1
docs/ref/class-based-views/mixins-multiple-object.txt

@@ -15,7 +15,7 @@ Multiple object mixins
     * Use the ``page`` parameter in the URLconf. For example, this is what
       your URLconf might look like::
 
-        path('objects/page<int:page>/', PaginatedView.as_view()),
+        path("objects/page<int:page>/", PaginatedView.as_view()),
 
     * Pass the page number via the ``page`` query-string parameter. For
       example, a URL would look like this:

+ 3 - 2
docs/ref/class-based-views/mixins-simple.txt

@@ -16,7 +16,8 @@ Simple mixins
         :meth:`~django.views.generic.base.View.as_view`. Example usage::
 
             from django.views.generic import TemplateView
-            TemplateView.as_view(extra_context={'title': 'Custom Title'})
+
+            TemplateView.as_view(extra_context={"title": "Custom Title"})
 
     **Methods**
 
@@ -27,7 +28,7 @@ Simple mixins
 
             def get_context_data(self, **kwargs):
                 context = super().get_context_data(**kwargs)
-                context['number'] = random.randrange(1, 100)
+                context["number"] = random.randrange(1, 100)
                 return context
 
         The template context of all class-based generic views include a

+ 5 - 2
docs/ref/clickjacking.txt

@@ -59,7 +59,7 @@ To set the same ``X-Frame-Options`` value for all responses in your site, put
 
     MIDDLEWARE = [
         ...,
-        'django.middleware.clickjacking.XFrameOptionsMiddleware',
+        "django.middleware.clickjacking.XFrameOptionsMiddleware",
         ...,
     ]
 
@@ -70,7 +70,7 @@ By default, the middleware will set the ``X-Frame-Options`` header to
 ``DENY`` for every outgoing ``HttpResponse``. If you want any other value for
 this header instead, set the :setting:`X_FRAME_OPTIONS` setting::
 
-    X_FRAME_OPTIONS = 'SAMEORIGIN'
+    X_FRAME_OPTIONS = "SAMEORIGIN"
 
 When using the middleware there may be some views where you do **not** want the
 ``X-Frame-Options`` header set. For those cases, you can use a view decorator
@@ -79,6 +79,7 @@ that tells the middleware not to set the header::
     from django.http import HttpResponse
     from django.views.decorators.clickjacking import xframe_options_exempt
 
+
     @xframe_options_exempt
     def ok_to_load_in_a_frame(request):
         return HttpResponse("This page is safe to load in a frame on any site.")
@@ -99,10 +100,12 @@ decorators::
     from django.views.decorators.clickjacking import xframe_options_deny
     from django.views.decorators.clickjacking import xframe_options_sameorigin
 
+
     @xframe_options_deny
     def view_one(request):
         return HttpResponse("I won't display in any frame!")
 
+
     @xframe_options_sameorigin
     def view_two(request):
         return HttpResponse("Display in a frame if it's from the same origin as me.")

+ 66 - 45
docs/ref/contrib/admin/actions.txt

@@ -48,11 +48,12 @@ news application with an ``Article`` model::
     from django.db import models
 
     STATUS_CHOICES = [
-        ('d', 'Draft'),
-        ('p', 'Published'),
-        ('w', 'Withdrawn'),
+        ("d", "Draft"),
+        ("p", "Published"),
+        ("w", "Withdrawn"),
     ]
 
+
     class Article(models.Model):
         title = models.CharField(max_length=100)
         body = models.TextField()
@@ -83,7 +84,7 @@ Our publish-these-articles function won't need the :class:`ModelAdmin` or the
 request object, but we will use the queryset::
 
     def make_published(modeladmin, request, queryset):
-        queryset.update(status='p')
+        queryset.update(status="p")
 
 .. note::
 
@@ -107,9 +108,10 @@ function::
 
     ...
 
-    @admin.action(description='Mark selected stories as published')
+
+    @admin.action(description="Mark selected stories as published")
     def make_published(modeladmin, request, queryset):
-        queryset.update(status='p')
+        queryset.update(status="p")
 
 .. note::
 
@@ -129,15 +131,18 @@ the action and its registration would look like::
     from django.contrib import admin
     from myapp.models import Article
 
-    @admin.action(description='Mark selected stories as published')
+
+    @admin.action(description="Mark selected stories as published")
     def make_published(modeladmin, request, queryset):
-        queryset.update(status='p')
+        queryset.update(status="p")
+
 
     class ArticleAdmin(admin.ModelAdmin):
-        list_display = ['title', 'status']
-        ordering = ['title']
+        list_display = ["title", "status"]
+        ordering = ["title"]
         actions = [make_published]
 
+
     admin.site.register(Article, ArticleAdmin)
 
 That code will give us an admin change list that looks something like this:
@@ -176,11 +181,11 @@ You can do it like this::
     class ArticleAdmin(admin.ModelAdmin):
         ...
 
-        actions = ['make_published']
+        actions = ["make_published"]
 
-        @admin.action(description='Mark selected stories as published')
+        @admin.action(description="Mark selected stories as published")
         def make_published(self, request, queryset):
-            queryset.update(status='p')
+            queryset.update(status="p")
 
 Notice first that we've moved ``make_published`` into a method and renamed the
 ``modeladmin`` parameter to ``self``, and second that we've now put the string
@@ -199,16 +204,22 @@ that the action was successful::
     from django.contrib import messages
     from django.utils.translation import ngettext
 
+
     class ArticleAdmin(admin.ModelAdmin):
         ...
 
         def make_published(self, request, queryset):
-            updated = queryset.update(status='p')
-            self.message_user(request, ngettext(
-                '%d story was successfully marked as published.',
-                '%d stories were successfully marked as published.',
-                updated,
-            ) % updated, messages.SUCCESS)
+            updated = queryset.update(status="p")
+            self.message_user(
+                request,
+                ngettext(
+                    "%d story was successfully marked as published.",
+                    "%d stories were successfully marked as published.",
+                    updated,
+                )
+                % updated,
+                messages.SUCCESS,
+            )
 
 This make the action match what the admin itself does after successfully
 performing an action:
@@ -231,6 +242,7 @@ dump some selected objects as JSON::
     from django.core import serializers
     from django.http import HttpResponse
 
+
     def export_as_json(modeladmin, request, queryset):
         response = HttpResponse(content_type="application/json")
         serializers.serialize("json", queryset, stream=response)
@@ -249,13 +261,17 @@ that redirects to your custom export view::
     from django.contrib.contenttypes.models import ContentType
     from django.http import HttpResponseRedirect
 
+
     def export_selected_objects(modeladmin, request, queryset):
-        selected = queryset.values_list('pk', flat=True)
+        selected = queryset.values_list("pk", flat=True)
         ct = ContentType.objects.get_for_model(queryset.model)
-        return HttpResponseRedirect('/export/?ct=%s&ids=%s' % (
-            ct.pk,
-            ','.join(str(pk) for pk in selected),
-        ))
+        return HttpResponseRedirect(
+            "/export/?ct=%s&ids=%s"
+            % (
+                ct.pk,
+                ",".join(str(pk) for pk in selected),
+            )
+        )
 
 As you can see, the action is rather short; all the complex logic would belong
 in your export view. This would need to deal with objects of any type, hence
@@ -285,7 +301,7 @@ Making actions available site-wide
     <disabling-admin-actions>` -- by passing a second argument to
     :meth:`AdminSite.add_action()`::
 
-        admin.site.add_action(export_selected_objects, 'export_selected')
+        admin.site.add_action(export_selected_objects, "export_selected")
 
 .. _disabling-admin-actions:
 
@@ -307,7 +323,7 @@ Disabling a site-wide action
     For example, you can use this method to remove the built-in "delete selected
     objects" action::
 
-        admin.site.disable_action('delete_selected')
+        admin.site.disable_action("delete_selected")
 
     Once you've done the above, that action will no longer be available
     site-wide.
@@ -316,16 +332,18 @@ Disabling a site-wide action
     particular model, list it explicitly in your ``ModelAdmin.actions`` list::
 
         # Globally disable delete selected
-        admin.site.disable_action('delete_selected')
+        admin.site.disable_action("delete_selected")
+
 
         # This ModelAdmin will not have delete_selected available
         class SomeModelAdmin(admin.ModelAdmin):
-            actions = ['some_other_action']
+            actions = ["some_other_action"]
             ...
 
+
         # This one will
         class AnotherModelAdmin(admin.ModelAdmin):
-            actions = ['delete_selected', 'a_third_action']
+            actions = ["delete_selected", "a_third_action"]
             ...
 
 
@@ -360,9 +378,9 @@ Conditionally enabling or disabling actions
 
             def get_actions(self, request):
                 actions = super().get_actions(request)
-                if request.user.username[0].upper() != 'J':
-                    if 'delete_selected' in actions:
-                        del actions['delete_selected']
+                if request.user.username[0].upper() != "J":
+                    if "delete_selected" in actions:
+                        del actions["delete_selected"]
                 return actions
 
 .. _admin-action-permissions:
@@ -374,9 +392,9 @@ Actions may limit their availability to users with specific permissions by
 wrapping the action function with the :func:`~django.contrib.admin.action`
 decorator and passing the ``permissions`` argument::
 
-    @admin.action(permissions=['change'])
+    @admin.action(permissions=["change"])
     def make_published(modeladmin, request, queryset):
-        queryset.update(status='p')
+        queryset.update(status="p")
 
 The ``make_published()`` action will only be available to users that pass the
 :meth:`.ModelAdmin.has_change_permission` check.
@@ -399,18 +417,19 @@ For example::
     from django.contrib import admin
     from django.contrib.auth import get_permission_codename
 
+
     class ArticleAdmin(admin.ModelAdmin):
-        actions = ['make_published']
+        actions = ["make_published"]
 
-        @admin.action(permissions=['publish'])
+        @admin.action(permissions=["publish"])
         def make_published(self, request, queryset):
-            queryset.update(status='p')
+            queryset.update(status="p")
 
         def has_publish_permission(self, request):
             """Does the user have the publish permission?"""
             opts = self.opts
-            codename = get_permission_codename('publish', opts)
-            return request.user.has_perm('%s.%s' % (opts.app_label, codename))
+            codename = get_permission_codename("publish", opts)
+            return request.user.has_perm("%s.%s" % (opts.app_label, codename))
 
 The ``action`` decorator
 ========================
@@ -422,19 +441,21 @@ The ``action`` decorator
     :attr:`~django.contrib.admin.ModelAdmin.actions`::
 
         @admin.action(
-            permissions=['publish'],
-            description='Mark selected stories as published',
+            permissions=["publish"],
+            description="Mark selected stories as published",
         )
         def make_published(self, request, queryset):
-            queryset.update(status='p')
+            queryset.update(status="p")
 
     This is equivalent to setting some attributes (with the original, longer
     names) on the function directly::
 
         def make_published(self, request, queryset):
-            queryset.update(status='p')
-        make_published.allowed_permissions = ['publish']
-        make_published.short_description = 'Mark selected stories as published'
+            queryset.update(status="p")
+
+
+        make_published.allowed_permissions = ["publish"]
+        make_published.short_description = "Mark selected stories as published"
 
     Use of this decorator is not compulsory to make an action function, but it
     can be useful to use it without arguments as a marker in your source to

+ 6 - 3
docs/ref/contrib/admin/admindocs.txt

@@ -62,11 +62,13 @@ A model with useful documentation might look like this::
         Stores a single blog entry, related to :model:`blog.Blog` and
         :model:`auth.User`.
         """
+
         slug = models.SlugField(help_text="A short label, generally used in URLs.")
         author = models.ForeignKey(
             User,
             models.SET_NULL,
-            blank=True, null=True,
+            blank=True,
+            null=True,
         )
         blog = models.ForeignKey(Blog, models.CASCADE)
         ...
@@ -92,6 +94,7 @@ For example::
 
     from myapp.models import MyModel
 
+
     def my_view(request, slug):
         """
         Display an individual :model:`myapp.MyModel`.
@@ -105,8 +108,8 @@ For example::
 
         :template:`myapp/my_template.html`
         """
-        context = {'mymodel': MyModel.objects.get(slug=slug)}
-        return render(request, 'myapp/my_template.html', context)
+        context = {"mymodel": MyModel.objects.get(slug=slug)}
+        return render(request, "myapp/my_template.html", context)
 
 Template tags and filters reference
 ===================================

+ 17 - 17
docs/ref/contrib/admin/filters.txt

@@ -33,13 +33,13 @@ Each specified field should be either a ``BooleanField``, ``CharField``,
 ``ManyToManyField``, for example::
 
     class PersonAdmin(admin.ModelAdmin):
-        list_filter = ['is_staff', 'company']
+        list_filter = ["is_staff", "company"]
 
 Field names in ``list_filter`` can also span relations
 using the ``__`` lookup, for example::
 
     class PersonAdmin(admin.UserAdmin):
-        list_filter = ['company__name']
+        list_filter = ["company__name"]
 
 Using a ``SimpleListFilter``
 ============================
@@ -54,13 +54,14 @@ and ``parameter_name`` attributes, and override the ``lookups`` and
     from django.contrib import admin
     from django.utils.translation import gettext_lazy as _
 
+
     class DecadeBornListFilter(admin.SimpleListFilter):
         # Human-readable title which will be displayed in the
         # right admin sidebar just above the filter options.
-        title = _('decade born')
+        title = _("decade born")
 
         # Parameter for the filter that will be used in the URL query.
-        parameter_name = 'decade'
+        parameter_name = "decade"
 
         def lookups(self, request, model_admin):
             """
@@ -71,8 +72,8 @@ and ``parameter_name`` attributes, and override the ``lookups`` and
             in the right sidebar.
             """
             return [
-                ('80s', _('in the eighties')),
-                ('90s', _('in the nineties')),
+                ("80s", _("in the eighties")),
+                ("90s", _("in the nineties")),
             ]
 
         def queryset(self, request, queryset):
@@ -83,17 +84,18 @@ and ``parameter_name`` attributes, and override the ``lookups`` and
             """
             # Compare the requested value (either '80s' or '90s')
             # to decide how to filter the queryset.
-            if self.value() == '80s':
+            if self.value() == "80s":
                 return queryset.filter(
                     birthday__gte=date(1980, 1, 1),
                     birthday__lte=date(1989, 12, 31),
                 )
-            if self.value() == '90s':
+            if self.value() == "90s":
                 return queryset.filter(
                     birthday__gte=date(1990, 1, 1),
                     birthday__lte=date(1999, 12, 31),
                 )
 
+
     class PersonAdmin(admin.ModelAdmin):
         list_filter = [DecadeBornListFilter]
 
@@ -103,7 +105,6 @@ and ``parameter_name`` attributes, and override the ``lookups`` and
     and ``queryset`` methods, for example::
 
         class AuthDecadeBornListFilter(DecadeBornListFilter):
-
             def lookups(self, request, model_admin):
                 if request.user.is_superuser:
                     return super().lookups(request, model_admin)
@@ -117,7 +118,6 @@ and ``parameter_name`` attributes, and override the ``lookups`` and
     available data::
 
         class AdvancedDecadeBornListFilter(DecadeBornListFilter):
-
             def lookups(self, request, model_admin):
                 """
                 Only show the lookups if there actually is
@@ -128,12 +128,12 @@ and ``parameter_name`` attributes, and override the ``lookups`` and
                     birthday__gte=date(1980, 1, 1),
                     birthday__lte=date(1989, 12, 31),
                 ).exists():
-                    yield ('80s', _('in the eighties'))
+                    yield ("80s", _("in the eighties"))
                 if qs.filter(
                     birthday__gte=date(1990, 1, 1),
                     birthday__lte=date(1999, 12, 31),
                 ).exists():
-                    yield ('90s', _('in the nineties'))
+                    yield ("90s", _("in the nineties"))
 
 Using a field name and an explicit ``FieldListFilter``
 ======================================================
@@ -145,7 +145,7 @@ field name and the second element is a class inheriting from
 
     class PersonAdmin(admin.ModelAdmin):
         list_filter = [
-            ('is_staff', admin.BooleanFieldListFilter),
+            ("is_staff", admin.BooleanFieldListFilter),
         ]
 
 Here the ``is_staff`` field will use the ``BooleanFieldListFilter``. Specifying
@@ -160,7 +160,7 @@ that relation using ``RelatedOnlyFieldListFilter``::
 
     class BookAdmin(admin.ModelAdmin):
         list_filter = [
-            ('author', admin.RelatedOnlyFieldListFilter),
+            ("author", admin.RelatedOnlyFieldListFilter),
         ]
 
 Assuming ``author`` is a ``ForeignKey`` to a ``User`` model, this will
@@ -173,7 +173,7 @@ allows to store::
 
     class BookAdmin(admin.ModelAdmin):
         list_filter = [
-            ('title', admin.EmptyFieldListFilter),
+            ("title", admin.EmptyFieldListFilter),
         ]
 
 By defining a filter using the ``__in`` lookup, it is possible to filter for
@@ -186,10 +186,10 @@ the separator::
 
     class FilterWithCustomSeparator(admin.FieldListFilter):
         # custom list separator that should be used to separate values.
-        list_separator = '|'
+        list_separator = "|"
 
         def __init__(self, field, request, params, model, model_admin, field_path):
-            self.lookup_kwarg = '%s__in' % field_path
+            self.lookup_kwarg = "%s__in" % field_path
             super().__init__(field, request, params, model, model_admin, field_path)
 
         def expected_parameters(self):

File diff suppressed because it is too large
+ 196 - 122
docs/ref/contrib/admin/index.txt


+ 18 - 16
docs/ref/contrib/contenttypes.txt

@@ -126,7 +126,7 @@ For example, we could look up the
 .. code-block:: pycon
 
     >>> from django.contrib.contenttypes.models import ContentType
-    >>> user_type = ContentType.objects.get(app_label='auth', model='user')
+    >>> user_type = ContentType.objects.get(app_label="auth", model="user")
     >>> user_type
     <ContentType: user>
 
@@ -138,7 +138,7 @@ to the ``User`` model class:
 
     >>> user_type.model_class()
     <class 'django.contrib.auth.models.User'>
-    >>> user_type.get_object_for_this_type(username='Guido')
+    >>> user_type.get_object_for_this_type(username="Guido")
     <User: Guido>
 
 Together,
@@ -252,11 +252,12 @@ For example, it could be used for a tagging system like so::
     from django.contrib.contenttypes.models import ContentType
     from django.db import models
 
+
     class TaggedItem(models.Model):
         tag = models.SlugField()
         content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
         object_id = models.PositiveIntegerField()
-        content_object = GenericForeignKey('content_type', 'object_id')
+        content_object = GenericForeignKey("content_type", "object_id")
 
         def __str__(self):
             return self.tag
@@ -351,8 +352,8 @@ creating a ``TaggedItem``:
 .. code-block:: pycon
 
     >>> from django.contrib.auth.models import User
-    >>> guido = User.objects.get(username='Guido')
-    >>> t = TaggedItem(content_object=guido, tag='bdfl')
+    >>> guido = User.objects.get(username="Guido")
+    >>> t = TaggedItem(content_object=guido, tag="bdfl")
     >>> t.save()
     >>> t.content_object
     <User: Guido>
@@ -400,6 +401,7 @@ a "reverse" generic relationship to enable an additional API. For example::
     from django.contrib.contenttypes.fields import GenericRelation
     from django.db import models
 
+
     class Bookmark(models.Model):
         url = models.URLField()
         tags = GenericRelation(TaggedItem)
@@ -409,11 +411,11 @@ be used to retrieve their associated ``TaggedItems``:
 
 .. code-block:: pycon
 
-    >>> b = Bookmark(url='https://www.djangoproject.com/')
+    >>> b = Bookmark(url="https://www.djangoproject.com/")
     >>> b.save()
-    >>> t1 = TaggedItem(content_object=b, tag='django')
+    >>> t1 = TaggedItem(content_object=b, tag="django")
     >>> t1.save()
-    >>> t2 = TaggedItem(content_object=b, tag='python')
+    >>> t2 = TaggedItem(content_object=b, tag="python")
     >>> t2.save()
     >>> b.tags.all()
     <QuerySet [<TaggedItem: django>, <TaggedItem: python>]>
@@ -423,9 +425,9 @@ relationships:
 
 .. code-block:: pycon
 
-    >>> t3 = TaggedItem(tag='Web development')
+    >>> t3 = TaggedItem(tag="Web development")
     >>> b.tags.add(t3, bulk=False)
-    >>> b.tags.create(tag='Web framework')
+    >>> b.tags.create(tag="Web framework")
     <TaggedItem: Web framework>
     >>> b.tags.all()
     <QuerySet [<TaggedItem: django>, <TaggedItem: python>, <TaggedItem: Web development>, <TaggedItem: Web framework>]>
@@ -457,7 +459,7 @@ instance:
 Defining :class:`~django.contrib.contenttypes.fields.GenericRelation` with
 ``related_query_name`` set allows querying from the related object::
 
-    tags = GenericRelation(TaggedItem, related_query_name='bookmark')
+    tags = GenericRelation(TaggedItem, related_query_name="bookmark")
 
 This enables filtering, ordering, and other query operations on ``Bookmark``
 from ``TaggedItem``:
@@ -465,7 +467,7 @@ from ``TaggedItem``:
 .. code-block:: pycon
 
     >>> # Get all tags belonging to bookmarks containing `django` in the url
-    >>> TaggedItem.objects.filter(bookmark__url__contains='django')
+    >>> TaggedItem.objects.filter(bookmark__url__contains="django")
     <QuerySet [<TaggedItem: django>, <TaggedItem: python>]>
 
 If you don't add the ``related_query_name``, you can do the same types of
@@ -473,7 +475,7 @@ lookups manually:
 
 .. code-block:: pycon
 
-    >>> bookmarks = Bookmark.objects.filter(url__contains='django')
+    >>> bookmarks = Bookmark.objects.filter(url__contains="django")
     >>> bookmark_type = ContentType.objects.get_for_model(Bookmark)
     >>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id, object_id__in=bookmarks)
     <QuerySet [<TaggedItem: django>, <TaggedItem: python>]>
@@ -491,8 +493,8 @@ referred to above used fields named ``content_type_fk`` and
 
     tags = GenericRelation(
         TaggedItem,
-        content_type_field='content_type_fk',
-        object_id_field='object_primary_key',
+        content_type_field="content_type_fk",
+        object_id_field="object_primary_key",
     )
 
 Note also, that if you delete an object that has a
@@ -519,7 +521,7 @@ can find out how many tags all the bookmarks have:
 
 .. code-block:: pycon
 
-    >>> Bookmark.objects.aggregate(Count('tags'))
+    >>> Bookmark.objects.aggregate(Count("tags"))
     {'tags__count': 3}
 
 .. module:: django.contrib.contenttypes.forms

+ 25 - 18
docs/ref/contrib/flatpages.txt

@@ -42,7 +42,7 @@ Then either:
 3. Add an entry in your URLconf. For example::
 
     urlpatterns = [
-        path('pages/', include('django.contrib.flatpages.urls')),
+        path("pages/", include("django.contrib.flatpages.urls")),
     ]
 
 or:
@@ -69,7 +69,7 @@ There are several ways to include the flat pages in your URLconf. You can
 dedicate a particular path to flat pages::
 
     urlpatterns = [
-        path('pages/', include('django.contrib.flatpages.urls')),
+        path("pages/", include("django.contrib.flatpages.urls")),
     ]
 
 You can also set it up as a "catchall" pattern. In this case, it is important
@@ -79,7 +79,7 @@ to place the pattern at the end of the other urlpatterns::
 
     # Your other patterns here
     urlpatterns += [
-        re_path(r'^(?P<url>.*/)$', views.flatpage),
+        re_path(r"^(?P<url>.*/)$", views.flatpage),
     ]
 
 .. warning::
@@ -95,8 +95,8 @@ tag::
     from django.contrib.flatpages import views
 
     urlpatterns += [
-        path('about-us/', views.flatpage, {'url': '/about-us/'}, name='about'),
-        path('license/', views.flatpage, {'url': '/license/'}, name='license'),
+        path("about-us/", views.flatpage, {"url": "/about-us/"}, name="about"),
+        path("license/", views.flatpage, {"url": "/license/"}, name="license"),
     ]
 
 Using the middleware
@@ -183,20 +183,25 @@ registering a custom ``ModelAdmin`` for ``FlatPage``::
     from django.contrib.flatpages.models import FlatPage
     from django.utils.translation import gettext_lazy as _
 
+
     # Define a new FlatPageAdmin
     class FlatPageAdmin(FlatPageAdmin):
         fieldsets = [
-            (None, {'fields': ['url', 'title', 'content', 'sites']}),
-            (_('Advanced options'), {
-                'classes': ['collapse'],
-                'fields': [
-                    'enable_comments',
-                    'registration_required',
-                    'template_name',
-                ],
-            }),
+            (None, {"fields": ["url", "title", "content", "sites"]}),
+            (
+                _("Advanced options"),
+                {
+                    "classes": ["collapse"],
+                    "fields": [
+                        "enable_comments",
+                        "registration_required",
+                        "template_name",
+                    ],
+                },
+            ),
         ]
 
+
     # Re-register FlatPageAdmin
     admin.site.unregister(FlatPage)
     admin.site.register(FlatPage, FlatPageAdmin)
@@ -344,9 +349,11 @@ Here's an example of a URLconf using :class:`FlatPageSitemap`::
 
     urlpatterns = [
         # ...
-
         # the sitemap
-        path('sitemap.xml', sitemap,
-            {'sitemaps': {'flatpages': FlatPageSitemap}},
-            name='django.contrib.sitemaps.views.sitemap'),
+        path(
+            "sitemap.xml",
+            sitemap,
+            {"sitemaps": {"flatpages": FlatPageSitemap}},
+            name="django.contrib.sitemaps.views.sitemap",
+        ),
     ]

+ 32 - 13
docs/ref/contrib/gis/db-api.txt

@@ -42,7 +42,7 @@ model):
 .. code-block:: pycon
 
     >>> from zipcode.models import Zipcode
-    >>> z = Zipcode(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
+    >>> z = Zipcode(code=77096, poly="POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))")
     >>> z.save()
 
 :class:`~django.contrib.gis.geos.GEOSGeometry` objects may also be used to save geometric models:
@@ -50,7 +50,7 @@ model):
 .. code-block:: pycon
 
     >>> from django.contrib.gis.geos import GEOSGeometry
-    >>> poly = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
+    >>> poly = GEOSGeometry("POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))")
     >>> z = Zipcode(code=77096, poly=poly)
     >>> z.save()
 
@@ -61,11 +61,15 @@ transform procedure:
 
 .. code-block:: pycon
 
-    >>> poly_3084 = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))', srid=3084)  # SRID 3084 is 'NAD83(HARN) / Texas Centric Lambert Conformal'
+    >>> poly_3084 = GEOSGeometry(
+    ...     "POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))", srid=3084
+    ... )  # SRID 3084 is 'NAD83(HARN) / Texas Centric Lambert Conformal'
     >>> z = Zipcode(code=78212, poly=poly_3084)
     >>> z.save()
     >>> from django.db import connection
-    >>> print(connection.queries[-1]['sql']) # printing the last SQL statement executed (requires DEBUG=True)
+    >>> print(
+    ...     connection.queries[-1]["sql"]
+    ... )  # printing the last SQL statement executed (requires DEBUG=True)
     INSERT INTO "geoapp_zipcode" ("code", "poly") VALUES (78212, ST_Transform(ST_GeomFromWKB('\\001 ... ', 3084), 4326))
 
 Thus, geometry parameters may be passed in using the ``GEOSGeometry`` object, WKT
@@ -93,7 +97,7 @@ Here is an example of how to create a raster object from a raster file
 .. code-block:: pycon
 
     >>> from elevation.models import Elevation
-    >>> dem = Elevation(name='Volcano', rast='/path/to/raster/volcano.tif')
+    >>> dem = Elevation(name="Volcano", rast="/path/to/raster/volcano.tif")
     >>> dem.save()
 
 :class:`~django.contrib.gis.gdal.GDALRaster` objects may also be used to save
@@ -102,9 +106,17 @@ raster models:
 .. code-block:: pycon
 
     >>> from django.contrib.gis.gdal import GDALRaster
-    >>> rast = GDALRaster({'width': 10, 'height': 10, 'name': 'Canyon', 'srid': 4326,
-    ...                    'scale': [0.1, -0.1], 'bands': [{"data": range(100)}]})
-    >>> dem = Elevation(name='Canyon', rast=rast)
+    >>> rast = GDALRaster(
+    ...     {
+    ...         "width": 10,
+    ...         "height": 10,
+    ...         "name": "Canyon",
+    ...         "srid": 4326,
+    ...         "scale": [0.1, -0.1],
+    ...         "bands": [{"data": range(100)}],
+    ...     }
+    ... )
+    >>> dem = Elevation(name="Canyon", rast=rast)
     >>> dem.save()
 
 Note that this equivalent to:
@@ -112,9 +124,15 @@ Note that this equivalent to:
 .. code-block:: pycon
 
     >>> dem = Elevation.objects.create(
-    ...     name='Canyon',
-    ...     rast={'width': 10, 'height': 10, 'name': 'Canyon', 'srid': 4326,
-    ...           'scale': [0.1, -0.1], 'bands': [{"data": range(100)}]},
+    ...     name="Canyon",
+    ...     rast={
+    ...         "width": 10,
+    ...         "height": 10,
+    ...         "name": "Canyon",
+    ...         "srid": 4326,
+    ...         "scale": [0.1, -0.1],
+    ...         "bands": [{"data": range(100)}],
+    ...     },
     ... )
 
 .. _spatial-lookups-intro:
@@ -270,6 +288,7 @@ For example, let's say we have a ``SouthTexasCity`` model (from the
 
     from django.contrib.gis.db import models
 
+
     class SouthTexasCity(models.Model):
         name = models.CharField(max_length=30)
         # A projected coordinate system (only valid for South Texas!)
@@ -281,10 +300,10 @@ Then distance queries may be performed as follows:
 .. code-block:: pycon
 
     >>> from django.contrib.gis.geos import GEOSGeometry
-    >>> from django.contrib.gis.measure import D # ``D`` is a shortcut for ``Distance``
+    >>> from django.contrib.gis.measure import D  # ``D`` is a shortcut for ``Distance``
     >>> from geoapp.models import SouthTexasCity
     # Distances will be calculated from this point, which does not have to be projected.
-    >>> pnt = GEOSGeometry('POINT(-96.876369 29.905320)', srid=4326)
+    >>> pnt = GEOSGeometry("POINT(-96.876369 29.905320)", srid=4326)
     # If numeric parameter, units of field (meters in this case) are assumed.
     >>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, 7000))
     # Find all Cities within 7 km, > 20 miles away, and > 100 chains away (an obscure unit)

+ 2 - 4
docs/ref/contrib/gis/feeds.txt

@@ -33,8 +33,8 @@ API Reference
 
         from django.contrib.gis.feeds import Feed
 
-        class MyFeed(Feed):
 
+        class MyFeed(Feed):
             # First, as a class attribute.
             geometry = ...
             item_geometry = ...
@@ -60,10 +60,9 @@ API Reference
     to represent a point or a box. For example::
 
         class ZipcodeFeed(Feed):
-
             def geometry(self, obj):
                 # Can also return: `obj.poly`, and `obj.poly.centroid`.
-                return obj.poly.extent # tuple like: (X0, Y0, X1, Y1).
+                return obj.poly.extent  # tuple like: (X0, Y0, X1, Y1).
 
     .. method:: item_geometry(item)
 
@@ -72,7 +71,6 @@ API Reference
     bounding box. For example::
 
         class ZipcodeFeed(Feed):
-
             def item_geometry(self, obj):
                 # Returns the polygon.
                 return obj.poly

+ 2 - 2
docs/ref/contrib/gis/forms-api.txt

@@ -134,9 +134,9 @@ widget. For example::
 
     from django.contrib.gis import forms
 
+
     class MyGeoForm(forms.Form):
-        point = forms.PointField(widget=
-            forms.OSMWidget(attrs={'display_raw': True}))
+        point = forms.PointField(widget=forms.OSMWidget(attrs={"display_raw": True}))
 
 Widget classes
 --------------

+ 9 - 8
docs/ref/contrib/gis/functions.txt

@@ -13,7 +13,7 @@ Example:
 .. code-block:: pycon
 
     >>> from django.contrib.gis.db.models.functions import Length
-    >>> Track.objects.annotate(length=Length('line')).filter(length__gt=100)
+    >>> Track.objects.annotate(length=Length("line")).filter(length__gt=100)
 
 Not all backends support all functions, so refer to the documentation of each
 function to see if your database backend supports the function you want to use.
@@ -67,7 +67,7 @@ Example:
 
 .. code-block:: pycon
 
-    >>> City.objects.annotate(json=AsGeoJSON('point')).get(name='Chicago').json
+    >>> City.objects.annotate(json=AsGeoJSON("point")).get(name="Chicago").json
     {"type":"Point","coordinates":[-87.65018,41.85039]}
 
 =====================  =====================================================
@@ -102,7 +102,7 @@ Example:
 
 .. code-block:: pycon
 
-    >>> qs = Zipcode.objects.annotate(gml=AsGML('poly'))
+    >>> qs = Zipcode.objects.annotate(gml=AsGML("poly"))
     >>> print(qs[0].gml)
     <gml:Polygon srsName="EPSG:4326"><gml:OuterBoundaryIs>-147.78711,70.245363 ...
     -147.78711,70.245363</gml:OuterBoundaryIs></gml:Polygon>
@@ -133,7 +133,7 @@ Example:
 
 .. code-block:: pycon
 
-    >>> qs = Zipcode.objects.annotate(kml=AsKML('poly'))
+    >>> qs = Zipcode.objects.annotate(kml=AsKML("poly"))
     >>> print(qs[0].kml)
     <Polygon><outerBoundaryIs><LinearRing><coordinates>-103.04135,36.217596,0 ...
     -103.04135,36.217596,0</coordinates></LinearRing></outerBoundaryIs></Polygon>
@@ -188,7 +188,7 @@ Example:
 
 .. code-block:: pycon
 
-    >>> bytes(City.objects.annotate(wkb=AsWKB('point')).get(name='Chelyabinsk').wkb)
+    >>> bytes(City.objects.annotate(wkb=AsWKB("point")).get(name="Chelyabinsk").wkb)
     b'\x01\x01\x00\x00\x00]3\xf9f\x9b\x91K@\x00X\x1d9\xd2\xb9N@'
 
 ``AsWKT``
@@ -207,7 +207,7 @@ Example:
 
 .. code-block:: pycon
 
-    >>> City.objects.annotate(wkt=AsWKT('point')).get(name='Chelyabinsk').wkt
+    >>> City.objects.annotate(wkt=AsWKT("point")).get(name="Chelyabinsk").wkt
     'POINT (55.137555 61.451728)'
 
 ``Azimuth``
@@ -306,9 +306,10 @@ queryset is calculated:
 .. code-block:: pycon
 
     >>> from django.contrib.gis.db.models.functions import Distance
-    >>> pnt = AustraliaCity.objects.get(name='Hobart').point
-    >>> for city in AustraliaCity.objects.annotate(distance=Distance('point', pnt)):
+    >>> pnt = AustraliaCity.objects.get(name="Hobart").point
+    >>> for city in AustraliaCity.objects.annotate(distance=Distance("point", pnt)):
     ...     print(city.name, city.distance)
+    ...
     Wollongong 990071.220408 m
     Shellharbour 972804.613941 m
     Thirroul 1002334.36351 m

+ 94 - 85
docs/ref/contrib/gis/gdal.txt

@@ -82,10 +82,10 @@ each feature in that layer.
     .. code-block:: pycon
 
         >>> from django.contrib.gis.gdal import DataSource
-        >>> ds = DataSource('/path/to/your/cities.shp')
+        >>> ds = DataSource("/path/to/your/cities.shp")
         >>> ds.name
         '/path/to/your/cities.shp'
-        >>> ds.layer_count                  # This file only contains one layer
+        >>> ds.layer_count  # This file only contains one layer
         1
 
     .. attribute:: layer_count
@@ -248,13 +248,13 @@ __ https://gdal.org/drivers/vector/
         None
         >>> print(len(layer))
         3
-        >>> [feat.get('Name') for feat in layer]
+        >>> [feat.get("Name") for feat in layer]
         ['Pueblo', 'Lawrence', 'Houston']
-        >>> ks_extent = (-102.051, 36.99, -94.59, 40.00) # Extent for state of Kansas
+        >>> ks_extent = (-102.051, 36.99, -94.59, 40.00)  # Extent for state of Kansas
         >>> layer.spatial_filter = ks_extent
         >>> len(layer)
         1
-        >>> [feat.get('Name') for feat in layer]
+        >>> [feat.get("Name") for feat in layer]
         ['Lawrence']
         >>> layer.spatial_filter = None
         >>> len(layer)
@@ -267,7 +267,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> layer.get_fields('Name')
+        >>> layer.get_fields("Name")
         ['Pueblo', 'Lawrence', 'Houston']
 
     .. method:: get_geoms(geos=False)
@@ -321,7 +321,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> city.get('Population')
+        >>> city.get("Population")
         102121
 
     .. attribute:: geom_type
@@ -371,7 +371,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> city.index('Population')
+        >>> city.index("Population")
         1
 
 ``Field``
@@ -385,7 +385,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> city['Name'].name
+        >>> city["Name"].name
         'Name'
 
     .. attribute:: type
@@ -395,7 +395,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> city['Density'].type
+        >>> city["Density"].type
         2
 
     .. attribute:: type_name
@@ -404,7 +404,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> city['Name'].type_name
+        >>> city["Name"].type_name
         'String'
 
     .. attribute:: value
@@ -415,7 +415,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> city['Population'].value
+        >>> city["Population"].value
         102121
 
     .. attribute:: width
@@ -424,7 +424,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> city['Name'].width
+        >>> city["Name"].width
         80
 
     .. attribute:: precision
@@ -434,7 +434,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> city['Density'].precision
+        >>> city["Density"].precision
         15
 
     .. method:: as_double()
@@ -443,7 +443,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> city['Density'].as_double()
+        >>> city["Density"].as_double()
         874.7
 
     .. method:: as_int()
@@ -452,7 +452,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> city['Population'].as_int()
+        >>> city["Population"].as_int()
         102121
 
     .. method:: as_string()
@@ -461,7 +461,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> city['Name'].as_string()
+        >>> city["Name"].as_string()
         'Pueblo'
 
     .. method:: as_datetime()
@@ -470,7 +470,7 @@ __ https://gdal.org/drivers/vector/
 
     .. code-block:: pycon
 
-        >>> city['Created'].as_datetime()
+        >>> city["Created"].as_datetime()
         (c_long(1999), c_long(5), c_long(23), c_long(0), c_long(0), c_long(0), c_long(0))
 
 ``Driver``
@@ -501,7 +501,7 @@ coordinate transformation:
 .. code-block:: pycon
 
     >>> from django.contrib.gis.gdal import OGRGeometry
-    >>> polygon = OGRGeometry('POLYGON((0 0, 5 0, 5 5, 0 5))')
+    >>> polygon = OGRGeometry("POLYGON((0 0, 5 0, 5 5, 0 5))")
 
 .. class:: OGRGeometry(geom_input, srs=None)
 
@@ -650,7 +650,7 @@ coordinate transformation:
 
     .. code-block:: pycon
 
-        >>> OGRGeometry('POINT(1 2)').gml
+        >>> OGRGeometry("POINT(1 2)").gml
         '<gml:Point><gml:coordinates>1,2</gml:coordinates></gml:Point>'
 
     .. attribute:: hex
@@ -659,7 +659,7 @@ coordinate transformation:
 
     .. code-block:: pycon
 
-        >>> OGRGeometry('POINT(1 2)').hex
+        >>> OGRGeometry("POINT(1 2)").hex
         '0101000000000000000000F03F0000000000000040'
 
     .. attribute:: json
@@ -668,7 +668,7 @@ coordinate transformation:
 
     .. code-block:: pycon
 
-        >>> OGRGeometry('POINT(1 2)').json
+        >>> OGRGeometry("POINT(1 2)").json
         '{ "type": "Point", "coordinates": [ 1.000000, 2.000000 ] }'
 
     .. attribute:: kml
@@ -682,7 +682,7 @@ coordinate transformation:
 
     .. code-block:: pycon
 
-        >>> OGRGeometry('POINT(1 2)').wkb_size
+        >>> OGRGeometry("POINT(1 2)").wkb_size
         21
 
     .. attribute:: wkb
@@ -708,7 +708,7 @@ coordinate transformation:
 
     .. code-block:: pycon
 
-        >>> triangle = OGRGeometry('LINEARRING (0 0,0 1,1 0)')
+        >>> triangle = OGRGeometry("LINEARRING (0 0,0 1,1 0)")
         >>> triangle.close_rings()
         >>> triangle.wkt
         'LINEARRING (0 0,0 1,1 0,0 0)'
@@ -800,9 +800,9 @@ coordinate transformation:
 
     .. code-block:: pycon
 
-        >>> OGRGeometry('POINT (1 2)').tuple
+        >>> OGRGeometry("POINT (1 2)").tuple
         (1.0, 2.0)
-        >>> OGRGeometry('LINESTRING (1 2,3 4)').tuple
+        >>> OGRGeometry("LINESTRING (1 2,3 4)").tuple
         ((1.0, 2.0), (3.0, 4.0))
 
     .. attribute:: coords
@@ -817,7 +817,7 @@ coordinate transformation:
 
     .. code-block:: pycon
 
-        >>> OGRGeometry('POINT (1 2)').x
+        >>> OGRGeometry("POINT (1 2)").x
         1.0
 
     .. attribute:: y
@@ -826,7 +826,7 @@ coordinate transformation:
 
     .. code-block:: pycon
 
-        >>> OGRGeometry('POINT (1 2)').y
+        >>> OGRGeometry("POINT (1 2)").y
         2.0
 
     .. attribute:: z
@@ -836,7 +836,7 @@ coordinate transformation:
 
     .. code-block:: pycon
 
-        >>> OGRGeometry('POINT (1 2 3)').z
+        >>> OGRGeometry("POINT (1 2 3)").z
         3.0
 
 .. class:: LineString
@@ -847,7 +847,7 @@ coordinate transformation:
 
     .. code-block:: pycon
 
-        >>> OGRGeometry('LINESTRING (1 2,3 4)').x
+        >>> OGRGeometry("LINESTRING (1 2,3 4)").x
         [1.0, 3.0]
 
     .. attribute:: y
@@ -856,7 +856,7 @@ coordinate transformation:
 
     .. code-block:: pycon
 
-        >>> OGRGeometry('LINESTRING (1 2,3 4)').y
+        >>> OGRGeometry("LINESTRING (1 2,3 4)").y
         [2.0, 4.0]
 
     .. attribute:: z
@@ -866,7 +866,7 @@ coordinate transformation:
 
     .. code-block:: pycon
 
-        >>> OGRGeometry('LINESTRING (1 2 3,4 5 6)').z
+        >>> OGRGeometry("LINESTRING (1 2 3,4 5 6)").z
         [3.0, 6.0]
 
 
@@ -903,10 +903,10 @@ coordinate transformation:
     .. code-block:: pycon
 
         >>> from django.contrib.gis.gdal import OGRGeomType
-        >>> gt1 = OGRGeomType(3)             # Using an integer for the type
-        >>> gt2 = OGRGeomType('Polygon')     # Using a string
-        >>> gt3 = OGRGeomType('POLYGON')     # It's case-insensitive
-        >>> print(gt1 == 3, gt1 == 'Polygon') # Equivalence works w/non-OGRGeomType objects
+        >>> gt1 = OGRGeomType(3)  # Using an integer for the type
+        >>> gt2 = OGRGeomType("Polygon")  # Using a string
+        >>> gt3 = OGRGeomType("POLYGON")  # It's case-insensitive
+        >>> print(gt1 == 3, gt1 == "Polygon")  # Equivalence works w/non-OGRGeomType objects
         True True
 
     .. attribute:: name
@@ -1001,12 +1001,13 @@ Coordinate System Objects
 
     .. code-block:: pycon
 
-        >>> wgs84 = SpatialReference('WGS84') # shorthand string
-        >>> wgs84 = SpatialReference(4326) # EPSG code
-        >>> wgs84 = SpatialReference('EPSG:4326') # EPSG string
-        >>> proj = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs '
-        >>> wgs84 = SpatialReference(proj) # PROJ string
-        >>> wgs84 = SpatialReference("""GEOGCS["WGS 84",
+        >>> wgs84 = SpatialReference("WGS84")  # shorthand string
+        >>> wgs84 = SpatialReference(4326)  # EPSG code
+        >>> wgs84 = SpatialReference("EPSG:4326")  # EPSG string
+        >>> proj = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs "
+        >>> wgs84 = SpatialReference(proj)  # PROJ string
+        >>> wgs84 = SpatialReference(
+        ...     """GEOGCS["WGS 84",
         ... DATUM["WGS_1984",
         ...      SPHEROID["WGS 84",6378137,298.257223563,
         ...          AUTHORITY["EPSG","7030"]],
@@ -1015,7 +1016,8 @@ Coordinate System Objects
         ...      AUTHORITY["EPSG","8901"]],
         ... UNIT["degree",0.01745329251994328,
         ...      AUTHORITY["EPSG","9122"]],
-        ... AUTHORITY["EPSG","4326"]]""") # OGC WKT
+        ... AUTHORITY["EPSG","4326"]]"""
+        ... )  # OGC WKT
 
     .. method:: __getitem__(target)
 
@@ -1026,20 +1028,20 @@ Coordinate System Objects
     .. code-block:: pycon
 
         >>> wkt = 'GEOGCS["WGS 84", DATUM["WGS_1984, ... AUTHORITY["EPSG","4326"]]'
-        >>> srs = SpatialReference(wkt) # could also use 'WGS84', or 4326
-        >>> print(srs['GEOGCS'])
+        >>> srs = SpatialReference(wkt)  # could also use 'WGS84', or 4326
+        >>> print(srs["GEOGCS"])
         WGS 84
-        >>> print(srs['DATUM'])
+        >>> print(srs["DATUM"])
         WGS_1984
-        >>> print(srs['AUTHORITY'])
+        >>> print(srs["AUTHORITY"])
         EPSG
-        >>> print(srs['AUTHORITY', 1]) # The authority value
+        >>> print(srs["AUTHORITY", 1])  # The authority value
         4326
-        >>> print(srs['TOWGS84', 4]) # the fourth value in this wkt
+        >>> print(srs["TOWGS84", 4])  # the fourth value in this wkt
         0
-        >>> print(srs['UNIT|AUTHORITY']) # For the units authority, have to use the pipe symbol.
+        >>> print(srs["UNIT|AUTHORITY"])  # For the units authority, have to use the pipe symbol.
         EPSG
-        >>> print(srs['UNIT|AUTHORITY', 1]) # The authority value for the units
+        >>> print(srs["UNIT|AUTHORITY", 1])  # The authority value for the units
         9122
 
     .. method:: attr_value(target, index=0)
@@ -1188,10 +1190,11 @@ coordinate transformation repeatedly on different geometries:
 
 .. code-block:: pycon
 
-    >>> ct = CoordTransform(SpatialReference('WGS84'), SpatialReference('NAD83'))
+    >>> ct = CoordTransform(SpatialReference("WGS84"), SpatialReference("NAD83"))
     >>> for feat in layer:
-    ...     geom = feat.geom # getting clone of feature geometry
-    ...     geom.transform(ct) # transforming
+    ...     geom = feat.geom  # getting clone of feature geometry
+    ...     geom.transform(ct)  # transforming
+    ...
 
 .. _raster-data-source-objects:
 
@@ -1366,8 +1369,8 @@ blue.
         tuple of six coefficients which map pixel/line coordinates into
         georeferenced space using the following relationship::
 
-            Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
-            Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
+            Xgeo = GT(0) + Xpixel * GT(1) + Yline * GT(2)
+            Ygeo = GT(3) + Xpixel * GT(4) + Yline * GT(5)
 
         The same values can be retrieved by accessing the :attr:`origin`
         (indices 0 and 3), :attr:`scale` (indices 1 and 5) and :attr:`skew`
@@ -1843,21 +1846,23 @@ Key               Default  Usage
 
     .. code-block:: pycon
 
-        >>> GDALRaster({
-        ...    'driver': 'GTiff',
-        ...    'name': '/path/to/new/file.tif',
-        ...    'srid': 4326,
-        ...    'width': 255,
-        ...    'height': 255,
-        ...    'nr_of_bands': 1,
-        ...    'papsz_options': {
-        ...        'compress': 'packbits',
-        ...        'pixeltype': 'signedbyte',
-        ...        'tiled': 'yes',
-        ...        'blockxsize': 23,
-        ...        'blockysize': 23,
-        ...    }
-        ... })
+        >>> GDALRaster(
+        ...     {
+        ...         "driver": "GTiff",
+        ...         "name": "/path/to/new/file.tif",
+        ...         "srid": 4326,
+        ...         "width": 255,
+        ...         "height": 255,
+        ...         "nr_of_bands": 1,
+        ...         "papsz_options": {
+        ...             "compress": "packbits",
+        ...             "pixeltype": "signedbyte",
+        ...             "tiled": "yes",
+        ...             "blockxsize": 23,
+        ...             "blockysize": 23,
+        ...         },
+        ...     }
+        ... )
 
 __ https://gdal.org/drivers/raster/gtiff.html
 
@@ -1913,7 +1918,7 @@ For instance:
 
     # Read a raster as a file object from a remote source.
     >>> from urllib.request import urlopen
-    >>> dat = urlopen('http://example.com/raster.tif').read()
+    >>> dat = urlopen("http://example.com/raster.tif").read()
     # Instantiate a raster from the bytes object.
     >>> rst = GDALRaster(dat)
     # The name starts with /vsimem/, indicating that the raster lives in the
@@ -1934,15 +1939,19 @@ Here's how to create a raster and return it as a file in an
 .. code-block:: pycon
 
     >>> from django.http import HttpResponse
-    >>> rst = GDALRaster({
-    ...     'name': '/vsimem/temporarymemfile',
-    ...     'driver': 'tif',
-    ...     'width': 6, 'height': 6, 'srid': 3086,
-    ...     'origin': [500000, 400000],
-    ...     'scale': [100, -100],
-    ...     'bands': [{'data': range(36), 'nodata_value': 99}]
-    ... })
-    >>> HttpResponse(rast.vsi_buffer, 'image/tiff')
+    >>> rst = GDALRaster(
+    ...     {
+    ...         "name": "/vsimem/temporarymemfile",
+    ...         "driver": "tif",
+    ...         "width": 6,
+    ...         "height": 6,
+    ...         "srid": 3086,
+    ...         "origin": [500000, 400000],
+    ...         "scale": [100, -100],
+    ...         "bands": [{"data": range(36), "nodata_value": 99}],
+    ...     }
+    ... )
+    >>> HttpResponse(rast.vsi_buffer, "image/tiff")
 
 Using other Virtual Filesystems
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1967,9 +1976,9 @@ directly access compressed files using the ``/vsizip/``, ``/vsigzip/``, or
 .. code-block:: pycon
 
    >>> from django.contrib.gis.gdal import GDALRaster
-   >>> rst = GDALRaster('/vsizip/path/to/your/file.zip/path/to/raster.tif')
-   >>> rst = GDALRaster('/vsigzip/path/to/your/file.gz')
-   >>> rst = GDALRaster('/vsitar/path/to/your/file.tar/path/to/raster.tif')
+   >>> rst = GDALRaster("/vsizip/path/to/your/file.zip/path/to/raster.tif")
+   >>> rst = GDALRaster("/vsigzip/path/to/your/file.gz")
+   >>> rst = GDALRaster("/vsitar/path/to/your/file.tar/path/to/raster.tif")
 
 Network rasters
 ^^^^^^^^^^^^^^^
@@ -1983,7 +1992,7 @@ To access a public raster file with no authentication, you can use
 .. code-block:: pycon
 
    >>> from django.contrib.gis.gdal import GDALRaster
-   >>> rst = GDALRaster('/vsicurl/https://example.com/raster.tif')
+   >>> rst = GDALRaster("/vsicurl/https://example.com/raster.tif")
    >>> rst.name
    '/vsicurl/https://example.com/raster.tif'
 

+ 5 - 5
docs/ref/contrib/gis/geoip2.txt

@@ -37,9 +37,9 @@ Here is an example of its usage:
 
     >>> from django.contrib.gis.geoip2 import GeoIP2
     >>> g = GeoIP2()
-    >>> g.country('google.com')
+    >>> g.country("google.com")
     {'country_code': 'US', 'country_name': 'United States'}
-    >>> g.city('72.14.207.99')
+    >>> g.city("72.14.207.99")
     {'city': 'Mountain View',
     'continent_code': 'NA',
     'continent_name': 'North America',
@@ -52,11 +52,11 @@ Here is an example of its usage:
     'postal_code': '94043',
     'region': 'CA',
     'time_zone': 'America/Los_Angeles'}
-    >>> g.lat_lon('salon.com')
+    >>> g.lat_lon("salon.com")
     (39.0437, -77.4875)
-    >>> g.lon_lat('uh.edu')
+    >>> g.lon_lat("uh.edu")
     (-95.4342, 29.834)
-    >>> g.geos('24.124.1.80').wkt
+    >>> g.geos("24.124.1.80").wkt
     'POINT (-97 38)'
 
 API Reference

+ 14 - 12
docs/ref/contrib/gis/geoquerysets.txt

@@ -428,7 +428,7 @@ Geometry example::
 
     # A tuple lookup parameter is used to specify the geometry and
     # the intersection pattern (the pattern here is for 'contains').
-    Zipcode.objects.filter(poly__relate=(geom, 'T*T***FF*'))
+    Zipcode.objects.filter(poly__relate=(geom, "T*T***FF*"))
 
 PostGIS and MariaDB SQL equivalent:
 
@@ -444,8 +444,8 @@ SpatiaLite SQL equivalent:
 
 Raster example::
 
-    Zipcode.objects.filter(poly__relate=(rast, 1, 'T*T***FF*'))
-    Zipcode.objects.filter(rast__2__relate=(rast, 1, 'T*T***FF*'))
+    Zipcode.objects.filter(poly__relate=(rast, 1, "T*T***FF*"))
+    Zipcode.objects.filter(rast__2__relate=(rast, 1, "T*T***FF*"))
 
 PostGIS SQL equivalent:
 
@@ -466,7 +466,7 @@ strings are case-insensitive.
 
 Example::
 
-    Zipcode.objects.filter(poly__relate=(geom, 'anyinteract'))
+    Zipcode.objects.filter(poly__relate=(geom, "anyinteract"))
 
 Oracle SQL equivalent:
 
@@ -863,7 +863,7 @@ Example:
 .. code-block:: pycon
 
     >>> from django.contrib.gis.db.models import Extent, Union
-    >>> WorldBorder.objects.aggregate(Extent('mpoly'), Union('mpoly'))
+    >>> WorldBorder.objects.aggregate(Extent("mpoly"), Union("mpoly"))
 
 ``Collect``
 ~~~~~~~~~~~
@@ -894,8 +894,8 @@ Example:
 
 .. code-block:: pycon
 
-    >>> qs = City.objects.filter(name__in=('Houston', 'Dallas')).aggregate(Extent('poly'))
-    >>> print(qs['poly__extent'])
+    >>> qs = City.objects.filter(name__in=("Houston", "Dallas")).aggregate(Extent("poly"))
+    >>> print(qs["poly__extent"])
     (-96.8016128540039, 29.7633724212646, -95.3631439208984, 32.782058715820)
 
 ``Extent3D``
@@ -913,8 +913,8 @@ Example:
 
 .. code-block:: pycon
 
-    >>> qs = City.objects.filter(name__in=('Houston', 'Dallas')).aggregate(Extent3D('poly'))
-    >>> print(qs['poly__extent3d'])
+    >>> qs = City.objects.filter(name__in=("Houston", "Dallas")).aggregate(Extent3D("poly"))
+    >>> print(qs["poly__extent3d"])
     (-96.8016128540039, 29.7633724212646, 0, -95.3631439208984, 32.782058715820, 0)
 
 ``MakeLine``
@@ -932,8 +932,8 @@ Example:
 
 .. code-block:: pycon
 
-    >>> qs = City.objects.filter(name__in=('Houston', 'Dallas')).aggregate(MakeLine('poly'))
-    >>> print(qs['poly__makeline'])
+    >>> qs = City.objects.filter(name__in=("Houston", "Dallas")).aggregate(MakeLine("poly"))
+    >>> print(qs["poly__makeline"])
     LINESTRING (-95.3631510000000020 29.7633739999999989, -96.8016109999999941 32.7820570000000018)
 
 ``Union``
@@ -959,7 +959,9 @@ Example:
 .. code-block:: pycon
 
     >>> u = Zipcode.objects.aggregate(Union(poly))  # This may take a long time.
-    >>> u = Zipcode.objects.filter(poly__within=bbox).aggregate(Union(poly))  # A more sensible approach.
+    >>> u = Zipcode.objects.filter(poly__within=bbox).aggregate(
+    ...     Union(poly)
+    ... )  # A more sensible approach.
 
 .. rubric:: Footnotes
 .. [#fnde9im] *See* `OpenGIS Simple Feature Specification For SQL <https://portal.ogc.org/files/?artifact_id=829>`_, at Ch. 2.1.13.2, p. 2-13 (The Dimensionally Extended Nine-Intersection Model).

+ 34 - 27
docs/ref/contrib/gis/geos.txt

@@ -55,10 +55,16 @@ are examples of creating the same geometry from WKT, HEX, WKB, and GeoJSON:
 .. code-block:: pycon
 
     >>> from django.contrib.gis.geos import GEOSGeometry
-    >>> pnt = GEOSGeometry('POINT(5 23)') # WKT
-    >>> pnt = GEOSGeometry('010100000000000000000014400000000000003740') # HEX
-    >>> pnt = GEOSGeometry(memoryview(b'\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x007@')) # WKB
-    >>> pnt = GEOSGeometry('{ "type": "Point", "coordinates": [ 5.000000, 23.000000 ] }') # GeoJSON
+    >>> pnt = GEOSGeometry("POINT(5 23)")  # WKT
+    >>> pnt = GEOSGeometry("010100000000000000000014400000000000003740")  # HEX
+    >>> pnt = GEOSGeometry(
+    ...     memoryview(
+    ...         b"\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x007@"
+    ...     )
+    ... )  # WKB
+    >>> pnt = GEOSGeometry(
+    ...     '{ "type": "Point", "coordinates": [ 5.000000, 23.000000 ] }'
+    ... )  # GeoJSON
 
 Another option is to use the constructor for the specific geometry type
 that you wish to create.  For example, a :class:`Point` object may be
@@ -74,7 +80,7 @@ All these constructors take the keyword argument ``srid``. For example:
 .. code-block:: pycon
 
     >>> from django.contrib.gis.geos import GEOSGeometry, LineString, Point
-    >>> print(GEOSGeometry('POINT (0 0)', srid=4326))
+    >>> print(GEOSGeometry("POINT (0 0)", srid=4326))
     SRID=4326;POINT (0 0)
     >>> print(LineString((0, 0), (1, 1), srid=4326))
     SRID=4326;LINESTRING (0 0, 1 1)
@@ -87,8 +93,8 @@ Finally, there is the :func:`fromfile` factory method which returns a
 .. code-block:: pycon
 
     >>> from django.contrib.gis.geos import fromfile
-    >>> pnt = fromfile('/path/to/pnt.wkt')
-    >>> pnt = fromfile(open('/path/to/pnt.wkt'))
+    >>> pnt = fromfile("/path/to/pnt.wkt")
+    >>> pnt = fromfile(open("/path/to/pnt.wkt"))
 
 .. _geos-exceptions-in-logfile:
 
@@ -141,10 +147,10 @@ Whereas indexing on a :class:`Polygon` will return the ring
 .. code-block:: pycon
 
     >>> from django.contrib.gis.geos import Polygon
-    >>> poly = Polygon( ((0.0, 0.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (0.0, 0.0)) )
+    >>> poly = Polygon(((0.0, 0.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (0.0, 0.0)))
     >>> poly[0]
     <LinearRing object at 0x1044395b0>
-    >>> poly[0][-2] # second-to-last coordinate of external ring
+    >>> poly[0][-2]  # second-to-last coordinate of external ring
     (50.0, 0.0)
 
 In addition, coordinates/components of the geometry may added or modified,
@@ -218,11 +224,11 @@ The ``srid`` parameter, if given, is set as the SRID of the created geometry if
 .. code-block:: pycon
 
     >>> from django.contrib.gis.geos import GEOSGeometry
-    >>> GEOSGeometry('POINT EMPTY', srid=4326).ewkt
+    >>> GEOSGeometry("POINT EMPTY", srid=4326).ewkt
     'SRID=4326;POINT EMPTY'
-    >>> GEOSGeometry('SRID=4326;POINT EMPTY', srid=4326).ewkt
+    >>> GEOSGeometry("SRID=4326;POINT EMPTY", srid=4326).ewkt
     'SRID=4326;POINT EMPTY'
-    >>> GEOSGeometry('SRID=1;POINT EMPTY', srid=4326)
+    >>> GEOSGeometry("SRID=1;POINT EMPTY", srid=4326)
     Traceback (most recent call last):
     ...
     ValueError: Input geometry already has SRID: 1.
@@ -274,7 +280,7 @@ Properties
 
     .. code-block:: pycon
 
-        >>> pnt = GEOSGeometry('POINT(5 23)')
+        >>> pnt = GEOSGeometry("POINT(5 23)")
         >>> pnt.geom_type
         'Point'
 
@@ -749,8 +755,8 @@ Other Properties & Methods
 
     .. code-block:: pycon
 
-        >>> ls = LineString( ((0, 0), (1, 1)) )
-        >>> ls = LineString( [Point(0, 0), Point(1, 1)] )
+        >>> ls = LineString(((0, 0), (1, 1)))
+        >>> ls = LineString([Point(0, 0), Point(1, 1)])
 
     Empty ``LineString`` objects may be instantiated by passing no arguments
     or an empty sequence. The following are equivalent:
@@ -823,6 +829,7 @@ Other Properties & Methods
 
         >>> if poly_1.area > poly_2.area:
         ...     pass
+        ...
 
 .. _geos-geometry-collections:
 
@@ -840,7 +847,7 @@ Geometry Collections
     .. code-block:: pycon
 
         >>> mp = MultiPoint(Point(0, 0), Point(1, 1))
-        >>> mp = MultiPoint( (Point(0, 0), Point(1, 1)) )
+        >>> mp = MultiPoint((Point(0, 0), Point(1, 1)))
 
 ``MultiLineString``
 -------------------
@@ -877,8 +884,8 @@ Geometry Collections
 
     .. code-block:: pycon
 
-        >>> p1 = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) )
-        >>> p2 = Polygon( ((1, 1), (1, 2), (2, 2), (1, 1)) )
+        >>> p1 = Polygon(((0, 0), (0, 1), (1, 1), (0, 0)))
+        >>> p2 = Polygon(((1, 1), (1, 2), (2, 2), (1, 1)))
         >>> mp = MultiPolygon(p1, p2)
         >>> mp = MultiPolygon([p1, p2])
 
@@ -893,7 +900,7 @@ Geometry Collections
 
     .. code-block:: pycon
 
-        >>> poly = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) )
+        >>> poly = Polygon(((0, 0), (0, 1), (1, 1), (0, 0)))
         >>> gc = GeometryCollection(Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly)
         >>> gc = GeometryCollection((Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly))
 
@@ -960,7 +967,7 @@ Geometry Factories
     .. code-block:: pycon
 
         >>> from django.contrib.gis.geos import fromfile
-        >>> g = fromfile('/home/bob/geom.wkt')
+        >>> g = fromfile("/home/bob/geom.wkt")
 
 .. function:: fromstr(string, srid=None)
 
@@ -978,7 +985,7 @@ Geometry Factories
     .. code-block:: pycon
 
         >>> from django.contrib.gis.geos import fromstr
-        >>> pnt = fromstr('POINT(-90.5 29.5)', srid=4326)
+        >>> pnt = fromstr("POINT(-90.5 29.5)", srid=4326)
 
 I/O Objects
 ===========
@@ -997,7 +1004,7 @@ and/or WKT input given to their ``read(geom)`` method.
 
         >>> from django.contrib.gis.geos import WKBReader
         >>> wkb_r = WKBReader()
-        >>> wkb_r.read('0101000000000000000000F03F000000000000F03F')
+        >>> wkb_r.read("0101000000000000000000F03F000000000000F03F")
         <Point object at 0x103a88910>
 
 .. class:: WKTReader
@@ -1008,7 +1015,7 @@ and/or WKT input given to their ``read(geom)`` method.
 
         >>> from django.contrib.gis.geos import WKTReader
         >>> wkt_r = WKTReader()
-        >>> wkt_r.read('POINT(1 1)')
+        >>> wkt_r.read("POINT(1 1)")
         <Point object at 0x103a88b50>
 
 Writer Objects
@@ -1099,9 +1106,9 @@ include the SRID value (in other words, EWKB).
         >>> wkb_w.outdim
         2
         >>> pnt = Point(1, 1, 1)
-        >>> wkb_w.write_hex(pnt) # By default, no Z value included:
+        >>> wkb_w.write_hex(pnt)  # By default, no Z value included:
         '0101000000000000000000F03F000000000000F03F'
-        >>> wkb_w.outdim = 3 # Tell writer to include Z values
+        >>> wkb_w.outdim = 3  # Tell writer to include Z values
         >>> wkb_w.write_hex(pnt)
         '0101000080000000000000F03F000000000000F03F000000000000F03F'
 
@@ -1115,9 +1122,9 @@ include the SRID value (in other words, EWKB).
         >>> from django.contrib.gis.geos import Point, WKBWriter
         >>> wkb_w = WKBWriter()
         >>> pnt = Point(1, 1, srid=4326)
-        >>> wkb_w.write_hex(pnt) # By default, no SRID included:
+        >>> wkb_w.write_hex(pnt)  # By default, no SRID included:
         '0101000000000000000000F03F000000000000F03F'
-        >>> wkb_w.srid = True # Tell writer to include SRID
+        >>> wkb_w.srid = True  # Tell writer to include SRID
         >>> wkb_w.write_hex(pnt)
         '0101000020E6100000000000000000F03F000000000000F03F'
 

+ 2 - 5
docs/ref/contrib/gis/install/postgis.txt

@@ -50,12 +50,9 @@ process. An alternative is to use a migration operation in your project::
     from django.contrib.postgres.operations import CreateExtension
     from django.db import migrations
 
-    class Migration(migrations.Migration):
 
-        operations = [
-            CreateExtension('postgis'),
-            ...
-        ]
+    class Migration(migrations.Migration):
+        operations = [CreateExtension("postgis"), ...]
 
 If you plan to use PostGIS raster functionality on PostGIS 3+, you should also
 activate the ``postgis_raster`` extension. You can install the extension using

+ 1 - 1
docs/ref/contrib/gis/install/spatialite.txt

@@ -114,6 +114,6 @@ including SQLite, SpatiaLite, PROJ, and GEOS. Install them like this:
 Finally, for GeoDjango to be able to find the SpatiaLite library, add the
 following to your ``settings.py``::
 
-    SPATIALITE_LIBRARY_PATH='/usr/local/lib/mod_spatialite.dylib'
+    SPATIALITE_LIBRARY_PATH = "/usr/local/lib/mod_spatialite.dylib"
 
 .. _Homebrew: https://brew.sh/

+ 14 - 13
docs/ref/contrib/gis/layermapping.txt

@@ -37,15 +37,15 @@ Example
 .. code-block:: pycon
 
     >>> from django.contrib.gis.gdal import DataSource
-    >>> ds = DataSource('test_poly.shp')
+    >>> ds = DataSource("test_poly.shp")
     >>> layer = ds[0]
-    >>> print(layer.fields) # Exploring the fields in the layer, we only want the 'str' field.
+    >>> print(layer.fields)  # Exploring the fields in the layer, we only want the 'str' field.
     ['float', 'int', 'str']
-    >>> print(len(layer)) # getting the number of features in the layer (should be 3)
+    >>> print(len(layer))  # getting the number of features in the layer (should be 3)
     3
-    >>> print(layer.geom_type) # Should be 'Polygon'
+    >>> print(layer.geom_type)  # Should be 'Polygon'
     Polygon
-    >>> print(layer.srs) # WGS84 in WKT
+    >>> print(layer.srs)  # WGS84 in WKT
     GEOGCS["GCS_WGS_1984",
         DATUM["WGS_1984",
             SPHEROID["WGS_1984",6378137,298.257223563]],
@@ -56,12 +56,13 @@ Example
 
     from django.contrib.gis.db import models
 
+
     class TestGeo(models.Model):
-        name = models.CharField(max_length=25) # corresponds to the 'str' field
-        poly = models.PolygonField(srid=4269) # we want our model in a different SRID
+        name = models.CharField(max_length=25)  # corresponds to the 'str' field
+        poly = models.PolygonField(srid=4269)  # we want our model in a different SRID
 
         def __str__(self):
-            return 'Name: %s' % self.name
+            return "Name: %s" % self.name
 
 #. Use :class:`LayerMapping` to extract all the features and place them in the
    database:
@@ -71,11 +72,11 @@ Example
     >>> from django.contrib.gis.utils import LayerMapping
     >>> from geoapp.models import TestGeo
     >>> mapping = {
-    ...     'name': 'str', # The 'name' model field maps to the 'str' layer field.
-    ...     'poly': 'POLYGON', # For geometry fields use OGC name.
-    ... } # The mapping is a dictionary
-    >>> lm = LayerMapping(TestGeo, 'test_poly.shp', mapping)
-    >>> lm.save(verbose=True) # Save the layermap, imports the data.
+    ...     "name": "str",  # The 'name' model field maps to the 'str' layer field.
+    ...     "poly": "POLYGON",  # For geometry fields use OGC name.
+    ... }  # The mapping is a dictionary
+    >>> lm = LayerMapping(TestGeo, "test_poly.shp", mapping)
+    >>> lm.save(verbose=True)  # Save the layermap, imports the data.
     Saved: Name: 1
     Saved: Name: 2
     Saved: Name: 3

+ 10 - 10
docs/ref/contrib/gis/measure.txt

@@ -24,7 +24,7 @@ instantiated in units of kilometers (``km``) and miles (``mi``):
     >>> d1 = Distance(km=5)
     >>> print(d1)
     5.0 km
-    >>> d2 = D(mi=5) # `D` is an alias for `Distance`
+    >>> d2 = D(mi=5)  # `D` is an alias for `Distance`
     >>> print(d2)
     5.0 mi
 
@@ -33,9 +33,9 @@ distance quantity:
 
 .. code-block:: pycon
 
-    >>> print(d1.mi) # Converting 5 kilometers to miles
+    >>> print(d1.mi)  # Converting 5 kilometers to miles
     3.10685596119
-    >>> print(d2.km) # Converting 5 miles to kilometers
+    >>> print(d2.km)  # Converting 5 miles to kilometers
     8.04672
 
 Moreover, arithmetic operations may be performed between the distance
@@ -43,9 +43,9 @@ objects:
 
 .. code-block:: pycon
 
-    >>> print(d1 + d2) # Adding 5 miles to 5 kilometers
+    >>> print(d1 + d2)  # Adding 5 miles to 5 kilometers
     13.04672 km
-    >>> print(d2 - d1) # Subtracting 5 kilometers from 5 miles
+    >>> print(d2 - d1)  # Subtracting 5 kilometers from 5 miles
     1.89314403881 mi
 
 Two :class:`Distance` objects multiplied together will yield an :class:`Area`
@@ -53,7 +53,7 @@ object, which uses squared units of measure:
 
 .. code-block:: pycon
 
-    >>> a = d1 * d2 # Returns an Area object.
+    >>> a = d1 * d2  # Returns an Area object.
     >>> print(a)
     40.2336 sq_km
 
@@ -62,9 +62,9 @@ class method may be used:
 
 .. code-block:: pycon
 
-    >>> print(Distance.unit_attname('US Survey Foot'))
+    >>> print(Distance.unit_attname("US Survey Foot"))
     survey_ft
-    >>> print(Distance.unit_attname('centimeter'))
+    >>> print(Distance.unit_attname("centimeter"))
     cm
 
 .. _supported_units:
@@ -150,7 +150,7 @@ Measurement API
 
     .. code-block:: pycon
 
-        >>> Distance.unit_attname('Mile')
+        >>> Distance.unit_attname("Mile")
         'mi'
 
 .. class:: D
@@ -188,7 +188,7 @@ Measurement API
 
     .. code-block:: pycon
 
-        >>> Area.unit_attname('Kilometer')
+        >>> Area.unit_attname("Kilometer")
         'sq_km'
 
 .. class:: A

+ 5 - 3
docs/ref/contrib/gis/model-api.txt

@@ -11,10 +11,12 @@ of a `Digital Elevation Model`__ as our examples::
 
     from django.contrib.gis.db import models
 
+
     class Zipcode(models.Model):
         code = models.CharField(max_length=5)
         poly = models.PolygonField()
 
+
     class Elevation(models.Model):
         name = models.CharField(max_length=100)
         rast = models.RasterField()
@@ -254,9 +256,9 @@ geography column to a geometry type in the query::
     from django.contrib.gis.db.models import PointField
     from django.db.models.functions import Cast
 
-    Zipcode.objects.annotate(
-        geom=Cast('geography_field', PointField())
-    ).filter(geom__within=poly)
+    Zipcode.objects.annotate(geom=Cast("geography_field", PointField())).filter(
+        geom__within=poly
+    )
 
 For more information, the PostGIS documentation contains a helpful section on
 determining `when to use geography data type over geometry data type

+ 11 - 21
docs/ref/contrib/gis/serializers.txt

@@ -40,31 +40,21 @@ Example::
     from django.core.serializers import serialize
     from my_app.models import City
 
-    serialize('geojson', City.objects.all(),
-              geometry_field='point',
-              fields=['name'])
+    serialize("geojson", City.objects.all(), geometry_field="point", fields=["name"])
 
 Would output::
 
     {
-      'type': 'FeatureCollection',
-      'crs': {
-        'type': 'name',
-        'properties': {'name': 'EPSG:4326'}
-      },
-      'features': [
-        {
-          'type': 'Feature',
-          'id': 1,
-          'geometry': {
-            'type': 'Point',
-            'coordinates': [-87.650175, 41.850385]
-          },
-          'properties': {
-            'name': 'Chicago'
-          }
-        }
-      ]
+        "type": "FeatureCollection",
+        "crs": {"type": "name", "properties": {"name": "EPSG:4326"}},
+        "features": [
+            {
+                "type": "Feature",
+                "id": 1,
+                "geometry": {"type": "Point", "coordinates": [-87.650175, 41.850385]},
+                "properties": {"name": "Chicago"},
+            }
+        ],
     }
 
 When the ``fields`` parameter is not specified, the ``geojson`` serializer adds

+ 9 - 9
docs/ref/contrib/gis/testing.txt

@@ -106,19 +106,19 @@ that can be used to run the entire Django test suite, including those
 in :mod:`django.contrib.gis`::
 
     DATABASES = {
-        'default': {
-            'ENGINE': 'django.contrib.gis.db.backends.postgis',
-            'NAME': 'geodjango',
-            'USER': 'geodjango',
+        "default": {
+            "ENGINE": "django.contrib.gis.db.backends.postgis",
+            "NAME": "geodjango",
+            "USER": "geodjango",
         },
-        'other': {
-            'ENGINE': 'django.contrib.gis.db.backends.postgis',
-            'NAME': 'other',
-            'USER': 'geodjango',
+        "other": {
+            "ENGINE": "django.contrib.gis.db.backends.postgis",
+            "NAME": "other",
+            "USER": "geodjango",
         },
     }
 
-    SECRET_KEY = 'django_tests_secret_key'
+    SECRET_KEY = "django_tests_secret_key"
 
 Assuming the settings above were in a ``postgis.py`` file in the same
 directory as ``runtests.py``, then all Django and GeoDjango tests would

+ 61 - 57
docs/ref/contrib/gis/tutorial.txt

@@ -77,10 +77,10 @@ The ``geodjango`` project settings are stored in the ``geodjango/settings.py``
 file. Edit the database connection settings to match your setup::
 
     DATABASES = {
-        'default': {
-            'ENGINE': 'django.contrib.gis.db.backends.postgis',
-            'NAME': 'geodjango',
-            'USER': 'geo',
+        "default": {
+            "ENGINE": "django.contrib.gis.db.backends.postgis",
+            "NAME": "geodjango",
+            "USER": "geo",
         },
     }
 
@@ -89,14 +89,14 @@ In addition, modify the :setting:`INSTALLED_APPS` setting to include
 and ``world`` (your newly created application)::
 
     INSTALLED_APPS = [
-        'django.contrib.admin',
-        'django.contrib.auth',
-        'django.contrib.contenttypes',
-        'django.contrib.sessions',
-        'django.contrib.messages',
-        'django.contrib.staticfiles',
-        'django.contrib.gis',
-        'world',
+        "django.contrib.admin",
+        "django.contrib.auth",
+        "django.contrib.contenttypes",
+        "django.contrib.sessions",
+        "django.contrib.messages",
+        "django.contrib.staticfiles",
+        "django.contrib.gis",
+        "world",
     ]
 
 Geographic Data
@@ -197,18 +197,19 @@ model to represent this data::
 
     from django.contrib.gis.db import models
 
+
     class WorldBorder(models.Model):
         # Regular Django fields corresponding to the attributes in the
         # world borders shapefile.
         name = models.CharField(max_length=50)
         area = models.IntegerField()
-        pop2005 = models.IntegerField('Population 2005')
-        fips = models.CharField('FIPS Code', max_length=2, null=True)
-        iso2 = models.CharField('2 Digit ISO', max_length=2)
-        iso3 = models.CharField('3 Digit ISO', max_length=3)
-        un = models.IntegerField('United Nations Code')
-        region = models.IntegerField('Region Code')
-        subregion = models.IntegerField('Sub-Region Code')
+        pop2005 = models.IntegerField("Population 2005")
+        fips = models.CharField("FIPS Code", max_length=2, null=True)
+        iso2 = models.CharField("2 Digit ISO", max_length=2)
+        iso3 = models.CharField("3 Digit ISO", max_length=3)
+        un = models.IntegerField("United Nations Code")
+        region = models.IntegerField("Region Code")
+        subregion = models.IntegerField("Sub-Region Code")
         lon = models.FloatField()
         lat = models.FloatField()
 
@@ -327,7 +328,7 @@ you can determine its path using Python's :class:`pathlib.Path`:
 
     >>> from pathlib import Path
     >>> import world
-    >>> world_shp = Path(world.__file__).resolve().parent / 'data' / 'TM_WORLD_BORDERS-0.3.shp'
+    >>> world_shp = Path(world.__file__).resolve().parent / "data" / "TM_WORLD_BORDERS-0.3.shp"
 
 Now, open the world borders shapefile using GeoDjango's
 :class:`~django.contrib.gis.gdal.DataSource` interface:
@@ -389,7 +390,7 @@ system associated with it.  If it does, the ``srs`` attribute will return a
     AXIS["Latitude",NORTH],
     AXIS["Longitude",EAST],
     AUTHORITY["EPSG","4326"]]
-    >>> srs.proj # PROJ representation
+    >>> srs.proj  # PROJ representation
     '+proj=longlat +datum=WGS84 +no_defs'
 
 This shapefile is in the popular WGS84 spatial reference
@@ -416,7 +417,7 @@ method):
 .. code-block:: pycon
 
     >>> for feat in lyr:
-    ...    print(feat.get('NAME'), feat.geom.num_points)
+    ...     print(feat.get("NAME"), feat.geom.num_points)
     ...
     Guernsey 18
     Jersey 26
@@ -435,7 +436,7 @@ And individual features may be retrieved by their feature ID:
 .. code-block:: pycon
 
     >>> feat = lyr[234]
-    >>> print(feat.get('NAME'))
+    >>> print(feat.get("NAME"))
     San Marino
 
 Boundary geometries may be exported as WKT and GeoJSON:
@@ -460,21 +461,22 @@ with the following code::
     from .models import WorldBorder
 
     world_mapping = {
-        'fips' : 'FIPS',
-        'iso2' : 'ISO2',
-        'iso3' : 'ISO3',
-        'un' : 'UN',
-        'name' : 'NAME',
-        'area' : 'AREA',
-        'pop2005' : 'POP2005',
-        'region' : 'REGION',
-        'subregion' : 'SUBREGION',
-        'lon' : 'LON',
-        'lat' : 'LAT',
-        'mpoly' : 'MULTIPOLYGON',
+        "fips": "FIPS",
+        "iso2": "ISO2",
+        "iso3": "ISO3",
+        "un": "UN",
+        "name": "NAME",
+        "area": "AREA",
+        "pop2005": "POP2005",
+        "region": "REGION",
+        "subregion": "SUBREGION",
+        "lon": "LON",
+        "lat": "LAT",
+        "mpoly": "MULTIPOLYGON",
     }
 
-    world_shp = Path(__file__).resolve().parent / 'data' / 'TM_WORLD_BORDERS-0.3.shp'
+    world_shp = Path(__file__).resolve().parent / "data" / "TM_WORLD_BORDERS-0.3.shp"
+
 
     def run(verbose=True):
         lm = LayerMapping(WorldBorder, world_shp, world_mapping, transform=False)
@@ -553,6 +555,7 @@ directly into the ``models.py`` of a GeoDjango application::
     # This is an auto-generated Django model module created by ogrinspect.
     from django.contrib.gis.db import models
 
+
     class WorldBorder(models.Model):
         fips = models.CharField(max_length=2)
         iso2 = models.CharField(max_length=2)
@@ -567,20 +570,21 @@ directly into the ``models.py`` of a GeoDjango application::
         lat = models.FloatField()
         geom = models.MultiPolygonField(srid=4326)
 
+
     # Auto-generated `LayerMapping` dictionary for WorldBorder model
     worldborders_mapping = {
-        'fips' : 'FIPS',
-        'iso2' : 'ISO2',
-        'iso3' : 'ISO3',
-        'un' : 'UN',
-        'name' : 'NAME',
-        'area' : 'AREA',
-        'pop2005' : 'POP2005',
-        'region' : 'REGION',
-        'subregion' : 'SUBREGION',
-        'lon' : 'LON',
-        'lat' : 'LAT',
-        'geom' : 'MULTIPOLYGON',
+        "fips": "FIPS",
+        "iso2": "ISO2",
+        "iso3": "ISO3",
+        "un": "UN",
+        "name": "NAME",
+        "area": "AREA",
+        "pop2005": "POP2005",
+        "region": "REGION",
+        "subregion": "SUBREGION",
+        "lon": "LON",
+        "lat": "LAT",
+        "geom": "MULTIPOLYGON",
     }
 
 Spatial Queries
@@ -600,7 +604,7 @@ Now, define a point of interest [#]_:
 
 .. code-block:: pycon
 
-    >>> pnt_wkt = 'POINT(-95.3385 29.7245)'
+    >>> pnt_wkt = "POINT(-95.3385 29.7245)"
 
 The ``pnt_wkt`` string represents the point at -95.3385 degrees longitude,
 29.7245 degrees latitude.  The geometry is in a format known as
@@ -652,7 +656,7 @@ WKT that includes the SRID:
 
 .. code-block:: pycon
 
-    >>> pnt = GEOSGeometry('SRID=32140;POINT(954158.1 4215137.1)')
+    >>> pnt = GEOSGeometry("SRID=32140;POINT(954158.1 4215137.1)")
 
 GeoDjango's ORM will automatically wrap geometry values
 in transformation SQL, allowing the developer to work at a higher level
@@ -661,14 +665,14 @@ of abstraction:
 .. code-block:: pycon
 
     >>> qs = WorldBorder.objects.filter(mpoly__intersects=pnt)
-    >>> print(qs.query) # Generating the SQL
+    >>> print(qs.query)  # Generating the SQL
     SELECT "world_worldborder"."id", "world_worldborder"."name", "world_worldborder"."area",
     "world_worldborder"."pop2005", "world_worldborder"."fips", "world_worldborder"."iso2",
     "world_worldborder"."iso3", "world_worldborder"."un", "world_worldborder"."region",
     "world_worldborder"."subregion", "world_worldborder"."lon", "world_worldborder"."lat",
     "world_worldborder"."mpoly" FROM "world_worldborder"
     WHERE ST_Intersects("world_worldborder"."mpoly", ST_Transform(%s, 4326))
-    >>> qs # printing evaluates the queryset
+    >>> qs  # printing evaluates the queryset
     <QuerySet [<WorldBorder: United States>]>
 
 __ https://spatialreference.org/ref/epsg/32140/
@@ -701,14 +705,14 @@ formats:
 
 .. code-block:: pycon
 
-    >>> sm = WorldBorder.objects.get(name='San Marino')
+    >>> sm = WorldBorder.objects.get(name="San Marino")
     >>> sm.mpoly
     <MultiPolygon object at 0x24c6798>
-    >>> sm.mpoly.wkt # WKT
+    >>> sm.mpoly.wkt  # WKT
     MULTIPOLYGON (((12.4157980000000006 43.9579540000000009, 12.4505540000000003 43.9797209999999978, ...
-    >>> sm.mpoly.wkb # WKB (as Python binary buffer)
+    >>> sm.mpoly.wkb  # WKB (as Python binary buffer)
     <read-only buffer for 0x1fe2c70, size -1, offset 0 at 0x2564c40>
-    >>> sm.mpoly.geojson # GeoJSON
+    >>> sm.mpoly.geojson  # GeoJSON
     '{ "type": "MultiPolygon", "coordinates": [ [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...
 
 This includes access to all of the advanced geometric operations provided by
@@ -758,7 +762,7 @@ Next, edit your ``urls.py`` in the ``geodjango`` application folder as follows::
     from django.urls import include, path
 
     urlpatterns = [
-        path('admin/', admin.site.urls),
+        path("admin/", admin.site.urls),
     ]
 
 Create an admin user:

+ 27 - 19
docs/ref/contrib/messages.txt

@@ -83,7 +83,7 @@ default storage class. If it isn't suitable to your needs, you can select
 another storage class by setting :setting:`MESSAGE_STORAGE` to its full import
 path, for example::
 
-    MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
+    MESSAGE_STORAGE = "django.contrib.messages.storage.cookie.CookieStorage"
 
 .. class:: storage.base.BaseStorage
 
@@ -147,9 +147,10 @@ you wish to change. As this extends the default tags, you only need to provide
 tags for the levels you wish to override::
 
     from django.contrib.messages import constants as messages
+
     MESSAGE_TAGS = {
-        messages.INFO: '',
-        50: 'critical',
+        messages.INFO: "",
+        50: "critical",
     }
 
 Using messages in views and templates
@@ -163,16 +164,17 @@ Adding a message
 To add a message, call::
 
     from django.contrib import messages
-    messages.add_message(request, messages.INFO, 'Hello world.')
+
+    messages.add_message(request, messages.INFO, "Hello world.")
 
 Some shortcut methods provide a standard way to add messages with commonly
 used tags (which are usually represented as HTML classes for the message)::
 
-    messages.debug(request, '%s SQL statements were executed.' % count)
-    messages.info(request, 'Three credits remain in your account.')
-    messages.success(request, 'Profile details updated.')
-    messages.warning(request, 'Your account expires in three days.')
-    messages.error(request, 'Document deleted.')
+    messages.debug(request, "%s SQL statements were executed." % count)
+    messages.info(request, "Three credits remain in your account.")
+    messages.success(request, "Profile details updated.")
+    messages.warning(request, "Your account expires in three days.")
+    messages.error(request, "Document deleted.")
 
 .. _message-displaying:
 
@@ -264,8 +266,9 @@ level constants and use them to create more customized user feedback, e.g.::
 
     CRITICAL = 50
 
+
     def my_view(request):
-        messages.add_message(request, CRITICAL, 'A serious error occurred.')
+        messages.add_message(request, CRITICAL, "A serious error occurred.")
 
 When creating custom message levels you should be careful to avoid overloading
 existing levels. The values for the built-in levels are:
@@ -299,12 +302,12 @@ method::
 
     # Change the messages level to ensure the debug message is added.
     messages.set_level(request, messages.DEBUG)
-    messages.debug(request, 'Test message...')
+    messages.debug(request, "Test message...")
 
     # In another request, record only messages with a level of WARNING and higher
     messages.set_level(request, messages.WARNING)
-    messages.success(request, 'Your profile was updated.') # ignored
-    messages.warning(request, 'Your account is about to expire.') # recorded
+    messages.success(request, "Your profile was updated.")  # ignored
+    messages.warning(request, "Your account is about to expire.")  # recorded
 
     # Set the messages level back to default.
     messages.set_level(request, None)
@@ -312,6 +315,7 @@ method::
 Similarly, the current effective level can be retrieved with ``get_level``::
 
     from django.contrib import messages
+
     current_level = messages.get_level(request)
 
 For more information on how the minimum recorded level functions, see
@@ -323,8 +327,8 @@ Adding extra message tags
 For more direct control over message tags, you can optionally provide a string
 containing extra tags to any of the add methods::
 
-    messages.add_message(request, messages.INFO, 'Over 9000!', extra_tags='dragonball')
-    messages.error(request, 'Email box full', extra_tags='email')
+    messages.add_message(request, messages.INFO, "Over 9000!", extra_tags="dragonball")
+    messages.error(request, "Email box full", extra_tags="email")
 
 Extra tags are added before the default tag for that level and are space
 separated.
@@ -339,10 +343,12 @@ if they don't want to, you may pass an additional keyword argument
 example::
 
     messages.add_message(
-        request, messages.SUCCESS, 'Profile details updated.',
+        request,
+        messages.SUCCESS,
+        "Profile details updated.",
         fail_silently=True,
     )
-    messages.info(request, 'Hello world.', fail_silently=True)
+    messages.info(request, "Hello world.", fail_silently=True)
 
 .. note::
    Setting ``fail_silently=True`` only hides the ``MessageFailure`` that would
@@ -369,9 +375,10 @@ Adding messages in class-based views
     from django.views.generic.edit import CreateView
     from myapp.models import Author
 
+
     class AuthorCreateView(SuccessMessageMixin, CreateView):
         model = Author
-        success_url = '/success/'
+        success_url = "/success/"
         success_message = "%(name)s was created successfully"
 
 The cleaned data from the ``form`` is available for string interpolation using
@@ -386,9 +393,10 @@ method.
     from django.views.generic.edit import CreateView
     from myapp.models import ComplicatedModel
 
+
     class ComplicatedCreateView(SuccessMessageMixin, CreateView):
         model = ComplicatedModel
-        success_url = '/success/'
+        success_url = "/success/"
         success_message = "%(calculated_field)s was created successfully"
 
         def get_success_message(self, cleaned_data):

+ 20 - 16
docs/ref/contrib/postgres/aggregates.txt

@@ -16,7 +16,7 @@ module. They are described in more detail in the `PostgreSQL docs
 
     .. code-block:: pycon
 
-        >>> SomeModel.objects.aggregate(arr=ArrayAgg('somefield'))
+        >>> SomeModel.objects.aggregate(arr=ArrayAgg("somefield"))
         {'arr': [0, 1, 2]}
 
 .. admonition:: Common aggregate options
@@ -49,10 +49,11 @@ General-purpose aggregation functions
 
         Examples::
 
-            'some_field'
-            '-some_field'
+            "some_field"
+            "-some_field"
             from django.db.models import F
-            F('some_field').desc()
+
+            F("some_field").desc()
 
     .. versionchanged:: 5.0
 
@@ -103,7 +104,7 @@ General-purpose aggregation functions
 
         >>> from django.db.models import Q
         >>> from django.contrib.postgres.aggregates import BoolAnd
-        >>> Comment.objects.aggregate(booland=BoolAnd('published'))
+        >>> Comment.objects.aggregate(booland=BoolAnd("published"))
         {'booland': False}
         >>> Comment.objects.aggregate(booland=BoolAnd(Q(rank__lt=100)))
         {'booland': True}
@@ -127,7 +128,7 @@ General-purpose aggregation functions
 
         >>> from django.db.models import Q
         >>> from django.contrib.postgres.aggregates import BoolOr
-        >>> Comment.objects.aggregate(boolor=BoolOr('published'))
+        >>> Comment.objects.aggregate(boolor=BoolOr("published"))
         {'boolor': True}
         >>> Comment.objects.aggregate(boolor=BoolOr(Q(rank__gt=2)))
         {'boolor': False}
@@ -160,8 +161,9 @@ General-purpose aggregation functions
         class Room(models.Model):
             number = models.IntegerField(unique=True)
 
+
         class HotelReservation(models.Model):
-            room = models.ForeignKey('Room', on_delete=models.CASCADE)
+            room = models.ForeignKey("Room", on_delete=models.CASCADE)
             start = models.DateTimeField()
             end = models.DateTimeField()
             requirements = models.JSONField(blank=True, null=True)
@@ -171,10 +173,10 @@ General-purpose aggregation functions
         >>> from django.contrib.postgres.aggregates import JSONBAgg
         >>> Room.objects.annotate(
         ...     requirements=JSONBAgg(
-        ...         'hotelreservation__requirements',
-        ...         ordering='-hotelreservation__start',
+        ...         "hotelreservation__requirements",
+        ...         ordering="-hotelreservation__start",
         ...     )
-        ... ).filter(requirements__0__sea_view=True).values('number', 'requirements')
+        ... ).filter(requirements__0__sea_view=True).values("number", "requirements")
         <QuerySet [{'number': 102, 'requirements': [
             {'parking': False, 'sea_view': True, 'double_bed': False},
             {'parking': True, 'double_bed': True}
@@ -217,6 +219,7 @@ General-purpose aggregation functions
         class Publication(models.Model):
             title = models.CharField(max_length=30)
 
+
         class Article(models.Model):
             headline = models.CharField(max_length=100)
             publications = models.ManyToManyField(Publication)
@@ -373,11 +376,11 @@ Here's some examples of some of the general-purpose aggregation functions:
 
 .. code-block:: pycon
 
-    >>> TestModel.objects.aggregate(result=StringAgg('field1', delimiter=';'))
+    >>> TestModel.objects.aggregate(result=StringAgg("field1", delimiter=";"))
     {'result': 'foo;bar;test'}
-    >>> TestModel.objects.aggregate(result=ArrayAgg('field2'))
+    >>> TestModel.objects.aggregate(result=ArrayAgg("field2"))
     {'result': [1, 2, 3]}
-    >>> TestModel.objects.aggregate(result=ArrayAgg('field1'))
+    >>> TestModel.objects.aggregate(result=ArrayAgg("field1"))
     {'result': ['foo', 'bar', 'test']}
 
 The next example shows the usage of statistical aggregate functions. The
@@ -386,8 +389,9 @@ underlying math will be not described (you can read about this, for example, at
 
 .. code-block:: pycon
 
-    >>> TestModel.objects.aggregate(count=RegrCount(y='field3', x='field2'))
+    >>> TestModel.objects.aggregate(count=RegrCount(y="field3", x="field2"))
     {'count': 2}
-    >>> TestModel.objects.aggregate(avgx=RegrAvgX(y='field3', x='field2'),
-    ...                             avgy=RegrAvgY(y='field3', x='field2'))
+    >>> TestModel.objects.aggregate(
+    ...     avgx=RegrAvgX(y="field3", x="field2"), avgy=RegrAvgY(y="field3", x="field2")
+    ... )
     {'avgx': 2, 'avgy': 13}

+ 20 - 16
docs/ref/contrib/postgres/constraints.txt

@@ -47,9 +47,9 @@ second element is an SQL operator represented as a string. To avoid typos, you
 may use :class:`~django.contrib.postgres.fields.RangeOperators` which maps the
 operators with strings. For example::
 
-    expressions=[
-        ('timespan', RangeOperators.ADJACENT_TO),
-        (F('room'), RangeOperators.EQUAL),
+    expressions = [
+        ("timespan", RangeOperators.ADJACENT_TO),
+        (F("room"), RangeOperators.EQUAL),
     ]
 
 .. admonition:: Restrictions on operators.
@@ -60,8 +60,8 @@ The :class:`OpClass() <django.contrib.postgres.indexes.OpClass>` expression can
 be used to specify a custom `operator class`_ for the constraint expressions.
 For example::
 
-    expressions=[
-        (OpClass('circle', name='circle_ops'), RangeOperators.OVERLAPS),
+    expressions = [
+        (OpClass("circle", name="circle_ops"), RangeOperators.OVERLAPS),
     ]
 
 creates an exclusion constraint on ``circle`` using ``circle_ops``.
@@ -103,9 +103,9 @@ are ``Deferrable.DEFERRED`` or ``Deferrable.IMMEDIATE``. For example::
 
 
     ExclusionConstraint(
-        name='exclude_overlapping_deferred',
+        name="exclude_overlapping_deferred",
         expressions=[
-            ('timespan', RangeOperators.OVERLAPS),
+            ("timespan", RangeOperators.OVERLAPS),
         ],
         deferrable=Deferrable.DEFERRED,
     )
@@ -161,22 +161,23 @@ taking canceled reservations into account::
     from django.db import models
     from django.db.models import Q
 
+
     class Room(models.Model):
         number = models.IntegerField()
 
 
     class Reservation(models.Model):
-        room = models.ForeignKey('Room', on_delete=models.CASCADE)
+        room = models.ForeignKey("Room", on_delete=models.CASCADE)
         timespan = DateTimeRangeField()
         cancelled = models.BooleanField(default=False)
 
         class Meta:
             constraints = [
                 ExclusionConstraint(
-                    name='exclude_overlapping_reservations',
+                    name="exclude_overlapping_reservations",
                     expressions=[
-                        ('timespan', RangeOperators.OVERLAPS),
-                        ('room', RangeOperators.EQUAL),
+                        ("timespan", RangeOperators.OVERLAPS),
+                        ("room", RangeOperators.EQUAL),
                     ],
                     condition=Q(cancelled=False),
                 ),
@@ -202,12 +203,12 @@ current/rangetypes.html#RANGETYPES-INCLUSIVITY>`_. For example::
 
 
     class TsTzRange(Func):
-        function = 'TSTZRANGE'
+        function = "TSTZRANGE"
         output_field = DateTimeRangeField()
 
 
     class Reservation(models.Model):
-        room = models.ForeignKey('Room', on_delete=models.CASCADE)
+        room = models.ForeignKey("Room", on_delete=models.CASCADE)
         start = models.DateTimeField()
         end = models.DateTimeField()
         cancelled = models.BooleanField(default=False)
@@ -215,10 +216,13 @@ current/rangetypes.html#RANGETYPES-INCLUSIVITY>`_. For example::
         class Meta:
             constraints = [
                 ExclusionConstraint(
-                    name='exclude_overlapping_reservations',
+                    name="exclude_overlapping_reservations",
                     expressions=[
-                        (TsTzRange('start', 'end', RangeBoundary()), RangeOperators.OVERLAPS),
-                        ('room', RangeOperators.EQUAL),
+                        (
+                            TsTzRange("start", "end", RangeBoundary()),
+                            RangeOperators.OVERLAPS,
+                        ),
+                        ("room", RangeOperators.EQUAL),
                     ],
                     condition=Q(cancelled=False),
                 ),

+ 2 - 2
docs/ref/contrib/postgres/expressions.txt

@@ -29,8 +29,8 @@ objects:
     >>> from django.db.models import OuterRef
     >>> from django.db.models.functions import JSONObject
     >>> from django.contrib.postgres.expressions import ArraySubquery
-    >>> books = Book.objects.filter(author=OuterRef('pk')).values(
-    ...     json=JSONObject(title='title', pages='pages')
+    >>> books = Book.objects.filter(author=OuterRef("pk")).values(
+    ...     json=JSONObject(title="title", pages="pages")
     ... )
     >>> author = Author.objects.annotate(books=ArraySubquery(books)).first()
     >>> author.books

+ 91 - 79
docs/ref/contrib/postgres/fields.txt

@@ -57,6 +57,7 @@ may be a good choice for the :ref:`range fields <range-fields>` and
             from django.contrib.postgres.fields import ArrayField
             from django.db import models
 
+
             class ChessBoard(models.Model):
                 board = ArrayField(
                     ArrayField(
@@ -86,20 +87,26 @@ may be a good choice for the :ref:`range fields <range-fields>` and
         from django.contrib.postgres.fields import ArrayField
         from django.db import models
 
+
         class Board(models.Model):
             pieces = ArrayField(ArrayField(models.IntegerField()))
 
+
         # Valid
-        Board(pieces=[
-            [2, 3],
-            [2, 1],
-        ])
+        Board(
+            pieces=[
+                [2, 3],
+                [2, 1],
+            ]
+        )
 
         # Not valid
-        Board(pieces=[
-            [2, 3],
-            [2],
-        ])
+        Board(
+            pieces=[
+                [2, 3],
+                [2],
+            ]
+        )
 
     If irregular shapes are required, then the underlying field should be made
     nullable and the values padded with ``None``.
@@ -113,6 +120,7 @@ We will use the following example model::
     from django.contrib.postgres.fields import ArrayField
     from django.db import models
 
+
     class Post(models.Model):
         name = models.CharField(max_length=200)
         tags = ArrayField(models.CharField(max_length=200), blank=True)
@@ -131,17 +139,17 @@ data. It uses the SQL operator ``@>``. For example:
 
 .. code-block:: pycon
 
-    >>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
-    >>> Post.objects.create(name='Second post', tags=['thoughts'])
-    >>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])
+    >>> Post.objects.create(name="First post", tags=["thoughts", "django"])
+    >>> Post.objects.create(name="Second post", tags=["thoughts"])
+    >>> Post.objects.create(name="Third post", tags=["tutorial", "django"])
 
-    >>> Post.objects.filter(tags__contains=['thoughts'])
+    >>> Post.objects.filter(tags__contains=["thoughts"])
     <QuerySet [<Post: First post>, <Post: Second post>]>
 
-    >>> Post.objects.filter(tags__contains=['django'])
+    >>> Post.objects.filter(tags__contains=["django"])
     <QuerySet [<Post: First post>, <Post: Third post>]>
 
-    >>> Post.objects.filter(tags__contains=['django', 'thoughts'])
+    >>> Post.objects.filter(tags__contains=["django", "thoughts"])
     <QuerySet [<Post: First post>]>
 
 .. fieldlookup:: arrayfield.contained_by
@@ -155,14 +163,14 @@ passed. It uses the SQL operator ``<@``. For example:
 
 .. code-block:: pycon
 
-    >>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
-    >>> Post.objects.create(name='Second post', tags=['thoughts'])
-    >>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])
+    >>> Post.objects.create(name="First post", tags=["thoughts", "django"])
+    >>> Post.objects.create(name="Second post", tags=["thoughts"])
+    >>> Post.objects.create(name="Third post", tags=["tutorial", "django"])
 
-    >>> Post.objects.filter(tags__contained_by=['thoughts', 'django'])
+    >>> Post.objects.filter(tags__contained_by=["thoughts", "django"])
     <QuerySet [<Post: First post>, <Post: Second post>]>
 
-    >>> Post.objects.filter(tags__contained_by=['thoughts', 'django', 'tutorial'])
+    >>> Post.objects.filter(tags__contained_by=["thoughts", "django", "tutorial"])
     <QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
 
 .. fieldlookup:: arrayfield.overlap
@@ -175,17 +183,17 @@ the SQL operator ``&&``. For example:
 
 .. code-block:: pycon
 
-    >>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
-    >>> Post.objects.create(name='Second post', tags=['thoughts', 'tutorial'])
-    >>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])
+    >>> Post.objects.create(name="First post", tags=["thoughts", "django"])
+    >>> Post.objects.create(name="Second post", tags=["thoughts", "tutorial"])
+    >>> Post.objects.create(name="Third post", tags=["tutorial", "django"])
 
-    >>> Post.objects.filter(tags__overlap=['thoughts'])
+    >>> Post.objects.filter(tags__overlap=["thoughts"])
     <QuerySet [<Post: First post>, <Post: Second post>]>
 
-    >>> Post.objects.filter(tags__overlap=['thoughts', 'tutorial'])
+    >>> Post.objects.filter(tags__overlap=["thoughts", "tutorial"])
     <QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
 
-    >>> Post.objects.filter(tags__overlap=Post.objects.values_list('tags'))
+    >>> Post.objects.filter(tags__overlap=Post.objects.values_list("tags"))
     <QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
 
 .. versionchanged:: 4.2
@@ -203,8 +211,8 @@ available for :class:`~django.db.models.IntegerField`. For example:
 
 .. code-block:: pycon
 
-    >>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
-    >>> Post.objects.create(name='Second post', tags=['thoughts'])
+    >>> Post.objects.create(name="First post", tags=["thoughts", "django"])
+    >>> Post.objects.create(name="Second post", tags=["thoughts"])
 
     >>> Post.objects.filter(tags__len=1)
     <QuerySet [<Post: Second post>]>
@@ -221,16 +229,16 @@ array. The lookups available after the transform are those from the
 
 .. code-block:: pycon
 
-    >>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
-    >>> Post.objects.create(name='Second post', tags=['thoughts'])
+    >>> Post.objects.create(name="First post", tags=["thoughts", "django"])
+    >>> Post.objects.create(name="Second post", tags=["thoughts"])
 
-    >>> Post.objects.filter(tags__0='thoughts')
+    >>> Post.objects.filter(tags__0="thoughts")
     <QuerySet [<Post: First post>, <Post: Second post>]>
 
-    >>> Post.objects.filter(tags__1__iexact='Django')
+    >>> Post.objects.filter(tags__1__iexact="Django")
     <QuerySet [<Post: First post>]>
 
-    >>> Post.objects.filter(tags__276='javascript')
+    >>> Post.objects.filter(tags__276="javascript")
     <QuerySet []>
 
 .. note::
@@ -250,14 +258,14 @@ transform do not change. For example:
 
 .. code-block:: pycon
 
-    >>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
-    >>> Post.objects.create(name='Second post', tags=['thoughts'])
-    >>> Post.objects.create(name='Third post', tags=['django', 'python', 'thoughts'])
+    >>> Post.objects.create(name="First post", tags=["thoughts", "django"])
+    >>> Post.objects.create(name="Second post", tags=["thoughts"])
+    >>> Post.objects.create(name="Third post", tags=["django", "python", "thoughts"])
 
-    >>> Post.objects.filter(tags__0_1=['thoughts'])
+    >>> Post.objects.filter(tags__0_1=["thoughts"])
     <QuerySet [<Post: First post>, <Post: Second post>]>
 
-    >>> Post.objects.filter(tags__0_2__contains=['thoughts'])
+    >>> Post.objects.filter(tags__0_2__contains=["thoughts"])
     <QuerySet [<Post: First post>, <Post: Second post>]>
 
 .. note::
@@ -374,6 +382,7 @@ We will use the following example model::
     from django.contrib.postgres.fields import HStoreField
     from django.db import models
 
+
     class Dog(models.Model):
         name = models.CharField(max_length=200)
         data = HStoreField()
@@ -390,17 +399,17 @@ To query based on a given key, you can use that key as the lookup name:
 
 .. code-block:: pycon
 
-    >>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
-    >>> Dog.objects.create(name='Meg', data={'breed': 'collie'})
+    >>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
+    >>> Dog.objects.create(name="Meg", data={"breed": "collie"})
 
-    >>> Dog.objects.filter(data__breed='collie')
+    >>> Dog.objects.filter(data__breed="collie")
     <QuerySet [<Dog: Meg>]>
 
 You can chain other lookups after key lookups:
 
 .. code-block:: pycon
 
-    >>> Dog.objects.filter(data__breed__contains='l')
+    >>> Dog.objects.filter(data__breed__contains="l")
     <QuerySet [<Dog: Rufus>, <Dog: Meg>]>
 
 or use ``F()`` expressions to annotate a key value. For example:
@@ -441,14 +450,14 @@ field. It uses the SQL operator ``@>``. For example:
 
 .. code-block:: pycon
 
-    >>> Dog.objects.create(name='Rufus', data={'breed': 'labrador', 'owner': 'Bob'})
-    >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
-    >>> Dog.objects.create(name='Fred', data={})
+    >>> Dog.objects.create(name="Rufus", data={"breed": "labrador", "owner": "Bob"})
+    >>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
+    >>> Dog.objects.create(name="Fred", data={})
 
-    >>> Dog.objects.filter(data__contains={'owner': 'Bob'})
+    >>> Dog.objects.filter(data__contains={"owner": "Bob"})
     <QuerySet [<Dog: Rufus>, <Dog: Meg>]>
 
-    >>> Dog.objects.filter(data__contains={'breed': 'collie'})
+    >>> Dog.objects.filter(data__contains={"breed": "collie"})
     <QuerySet [<Dog: Meg>]>
 
 .. fieldlookup:: hstorefield.contained_by
@@ -463,14 +472,14 @@ example:
 
 .. code-block:: pycon
 
-    >>> Dog.objects.create(name='Rufus', data={'breed': 'labrador', 'owner': 'Bob'})
-    >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
-    >>> Dog.objects.create(name='Fred', data={})
+    >>> Dog.objects.create(name="Rufus", data={"breed": "labrador", "owner": "Bob"})
+    >>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
+    >>> Dog.objects.create(name="Fred", data={})
 
-    >>> Dog.objects.filter(data__contained_by={'breed': 'collie', 'owner': 'Bob'})
+    >>> Dog.objects.filter(data__contained_by={"breed": "collie", "owner": "Bob"})
     <QuerySet [<Dog: Meg>, <Dog: Fred>]>
 
-    >>> Dog.objects.filter(data__contained_by={'breed': 'collie'})
+    >>> Dog.objects.filter(data__contained_by={"breed": "collie"})
     <QuerySet [<Dog: Fred>]>
 
 .. fieldlookup:: hstorefield.has_key
@@ -483,10 +492,10 @@ Returns objects where the given key is in the data. Uses the SQL operator
 
 .. code-block:: pycon
 
-    >>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
-    >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
+    >>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
+    >>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
 
-    >>> Dog.objects.filter(data__has_key='owner')
+    >>> Dog.objects.filter(data__has_key="owner")
     <QuerySet [<Dog: Meg>]>
 
 .. fieldlookup:: hstorefield.has_any_keys
@@ -499,11 +508,11 @@ operator ``?|``. For example:
 
 .. code-block:: pycon
 
-    >>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
-    >>> Dog.objects.create(name='Meg', data={'owner': 'Bob'})
-    >>> Dog.objects.create(name='Fred', data={})
+    >>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
+    >>> Dog.objects.create(name="Meg", data={"owner": "Bob"})
+    >>> Dog.objects.create(name="Fred", data={})
 
-    >>> Dog.objects.filter(data__has_any_keys=['owner', 'breed'])
+    >>> Dog.objects.filter(data__has_any_keys=["owner", "breed"])
     <QuerySet [<Dog: Rufus>, <Dog: Meg>]>
 
 .. fieldlookup:: hstorefield.has_keys
@@ -516,10 +525,10 @@ Returns objects where all of the given keys are in the data. Uses the SQL operat
 
 .. code-block:: pycon
 
-    >>> Dog.objects.create(name='Rufus', data={})
-    >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
+    >>> Dog.objects.create(name="Rufus", data={})
+    >>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
 
-    >>> Dog.objects.filter(data__has_keys=['breed', 'owner'])
+    >>> Dog.objects.filter(data__has_keys=["breed", "owner"])
     <QuerySet [<Dog: Meg>]>
 
 .. fieldlookup:: hstorefield.keys
@@ -535,10 +544,10 @@ in conjunction with lookups on
 
 .. code-block:: pycon
 
-    >>> Dog.objects.create(name='Rufus', data={'toy': 'bone'})
-    >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
+    >>> Dog.objects.create(name="Rufus", data={"toy": "bone"})
+    >>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
 
-    >>> Dog.objects.filter(data__keys__overlap=['breed', 'toy'])
+    >>> Dog.objects.filter(data__keys__overlap=["breed", "toy"])
     <QuerySet [<Dog: Rufus>, <Dog: Meg>]>
 
 .. fieldlookup:: hstorefield.values
@@ -554,10 +563,10 @@ using in conjunction with lookups on
 
 .. code-block:: pycon
 
-    >>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
-    >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
+    >>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
+    >>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
 
-    >>> Dog.objects.filter(data__values__contains=['collie'])
+    >>> Dog.objects.filter(data__values__contains=["collie"])
     <QuerySet [<Dog: Meg>]>
 
 .. _range-fields:
@@ -666,6 +675,7 @@ model::
     from django.contrib.postgres.fields import IntegerRangeField
     from django.db import models
 
+
     class Event(models.Model):
         name = models.CharField(max_length=200)
         ages = IntegerRangeField()
@@ -681,8 +691,10 @@ We will also use the following example objects:
     >>> import datetime
     >>> from django.utils import timezone
     >>> now = timezone.now()
-    >>> Event.objects.create(name='Soft play', ages=(0, 10), start=now)
-    >>> Event.objects.create(name='Pub trip', ages=(21, None), start=now - datetime.timedelta(days=1))
+    >>> Event.objects.create(name="Soft play", ages=(0, 10), start=now)
+    >>> Event.objects.create(
+    ...     name="Pub trip", ages=(21, None), start=now - datetime.timedelta(days=1)
+    ... )
 
 and ``NumericRange``:
 
@@ -945,16 +957,16 @@ corresponding lookups.
 .. code-block:: python
 
     class RangeOperators:
-        EQUAL = '='
-        NOT_EQUAL = '<>'
-        CONTAINS = '@>'
-        CONTAINED_BY = '<@'
-        OVERLAPS = '&&'
-        FULLY_LT = '<<'
-        FULLY_GT = '>>'
-        NOT_LT = '&>'
-        NOT_GT = '&<'
-        ADJACENT_TO = '-|-'
+        EQUAL = "="
+        NOT_EQUAL = "<>"
+        CONTAINS = "@>"
+        CONTAINED_BY = "<@"
+        OVERLAPS = "&&"
+        FULLY_LT = "<<"
+        FULLY_GT = ">>"
+        NOT_LT = "&>"
+        NOT_GT = "&<"
+        ADJACENT_TO = "-|-"
 
 RangeBoundary() expressions
 ---------------------------

+ 22 - 20
docs/ref/contrib/postgres/forms.txt

@@ -32,14 +32,15 @@ Fields
 
             >>> class NumberListForm(forms.Form):
             ...     numbers = SimpleArrayField(forms.IntegerField())
+            ...
 
-            >>> form = NumberListForm({'numbers': '1,2,3'})
+            >>> form = NumberListForm({"numbers": "1,2,3"})
             >>> form.is_valid()
             True
             >>> form.cleaned_data
             {'numbers': [1, 2, 3]}
 
-            >>> form = NumberListForm({'numbers': '1,2,a'})
+            >>> form = NumberListForm({"numbers": "1,2,a"})
             >>> form.is_valid()
             False
 
@@ -55,9 +56,10 @@ Fields
             >>> from django.contrib.postgres.forms import SimpleArrayField
 
             >>> class GridForm(forms.Form):
-            ...     places = SimpleArrayField(SimpleArrayField(IntegerField()), delimiter='|')
+            ...     places = SimpleArrayField(SimpleArrayField(IntegerField()), delimiter="|")
+            ...
 
-            >>> form = GridForm({'places': '1,2|2,1|4,3'})
+            >>> form = GridForm({"places": "1,2|2,1|4,3"})
             >>> form.is_valid()
             True
             >>> form.cleaned_data
@@ -115,31 +117,31 @@ Fields
 
             SplitArrayField(IntegerField(required=True), size=3, remove_trailing_nulls=False)
 
-            ['1', '2', '3']  # -> [1, 2, 3]
-            ['1', '2', '']  # -> ValidationError - third entry required.
-            ['1', '', '3']  # -> ValidationError - second entry required.
-            ['', '2', '']  # -> ValidationError - first and third entries required.
+            ["1", "2", "3"]  # -> [1, 2, 3]
+            ["1", "2", ""]  # -> ValidationError - third entry required.
+            ["1", "", "3"]  # -> ValidationError - second entry required.
+            ["", "2", ""]  # -> ValidationError - first and third entries required.
 
             SplitArrayField(IntegerField(required=False), size=3, remove_trailing_nulls=False)
 
-            ['1', '2', '3']  # -> [1, 2, 3]
-            ['1', '2', '']  # -> [1, 2, None]
-            ['1', '', '3']  # -> [1, None, 3]
-            ['', '2', '']  # -> [None, 2, None]
+            ["1", "2", "3"]  # -> [1, 2, 3]
+            ["1", "2", ""]  # -> [1, 2, None]
+            ["1", "", "3"]  # -> [1, None, 3]
+            ["", "2", ""]  # -> [None, 2, None]
 
             SplitArrayField(IntegerField(required=True), size=3, remove_trailing_nulls=True)
 
-            ['1', '2', '3']  # -> [1, 2, 3]
-            ['1', '2', '']  # -> [1, 2]
-            ['1', '', '3']  # -> ValidationError - second entry required.
-            ['', '2', '']  # -> ValidationError - first entry required.
+            ["1", "2", "3"]  # -> [1, 2, 3]
+            ["1", "2", ""]  # -> [1, 2]
+            ["1", "", "3"]  # -> ValidationError - second entry required.
+            ["", "2", ""]  # -> ValidationError - first entry required.
 
             SplitArrayField(IntegerField(required=False), size=3, remove_trailing_nulls=True)
 
-            ['1', '2', '3']  # -> [1, 2, 3]
-            ['1', '2', '']  # -> [1, 2]
-            ['1', '', '3']  # -> [1, None, 3]
-            ['', '2', '']  # -> [None, 2]
+            ["1", "2", "3"]  # -> [1, 2, 3]
+            ["1", "2", ""]  # -> [1, 2]
+            ["1", "", "3"]  # -> [1, None, 3]
+            ["", "2", ""]  # -> [None, 2]
 
 ``HStoreField``
 ---------------

+ 6 - 6
docs/ref/contrib/postgres/indexes.txt

@@ -149,16 +149,16 @@ available from the ``django.contrib.postgres.indexes`` module.
     For example::
 
         Index(
-            OpClass(Lower('username'), name='varchar_pattern_ops'),
-            name='lower_username_idx',
+            OpClass(Lower("username"), name="varchar_pattern_ops"),
+            name="lower_username_idx",
         )
 
     creates an index on ``Lower('username')`` using ``varchar_pattern_ops``.
     ::
 
         UniqueConstraint(
-            OpClass(Upper('description'), name='text_pattern_ops'),
-            name='upper_description_unique',
+            OpClass(Upper("description"), name="text_pattern_ops"),
+            name="upper_description_unique",
         )
 
     creates a unique constraint on ``Upper('description')`` using
@@ -166,9 +166,9 @@ available from the ``django.contrib.postgres.indexes`` module.
     ::
 
         ExclusionConstraint(
-            name='exclude_overlapping_ops',
+            name="exclude_overlapping_ops",
             expressions=[
-                (OpClass('circle', name='circle_ops'), RangeOperators.OVERLAPS),
+                (OpClass("circle", name="circle_ops"), RangeOperators.OVERLAPS),
             ],
         )
 

+ 1 - 1
docs/ref/contrib/postgres/lookups.txt

@@ -53,7 +53,7 @@ The ``trigram_word_similar`` lookup can be used on
 
 .. code-block:: pycon
 
-    >>> Sentence.objects.filter(name__trigram_word_similar='Middlesborough')
+    >>> Sentence.objects.filter(name__trigram_word_similar="Middlesborough")
     ['<Sentence: Gumby rides on the path of Middlesbrough>']
 
 .. fieldlookup:: trigram_strict_word_similar

+ 7 - 8
docs/ref/contrib/postgres/operations.txt

@@ -22,13 +22,11 @@ For example::
 
     from django.contrib.postgres.operations import HStoreExtension
 
+
     class Migration(migrations.Migration):
         ...
 
-        operations = [
-            HStoreExtension(),
-            ...
-        ]
+        operations = [HStoreExtension(), ...]
 
 The operation skips adding the extension if it already exists.
 
@@ -124,16 +122,17 @@ For example, to create a collation for German phone book ordering::
 
     from django.contrib.postgres.operations import CreateCollation
 
+
     class Migration(migrations.Migration):
         ...
 
         operations = [
             CreateCollation(
-                'german_phonebook',
-                provider='icu',
-                locale='und-u-ks-level2',
+                "german_phonebook",
+                provider="icu",
+                locale="und-u-ks-level2",
             ),
-            ...
+            ...,
         ]
 
 .. class:: CreateCollation(name, locale, *, provider='libc', deterministic=True)

+ 59 - 47
docs/ref/contrib/postgres/search.txt

@@ -26,7 +26,7 @@ single column in the database. For example:
 
 .. code-block:: pycon
 
-    >>> Entry.objects.filter(body_text__search='Cheese')
+    >>> Entry.objects.filter(body_text__search="Cheese")
     [<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]
 
 This creates a ``to_tsvector`` in the database from the ``body_text`` field
@@ -50,8 +50,8 @@ To query against both fields, use a ``SearchVector``:
 
     >>> from django.contrib.postgres.search import SearchVector
     >>> Entry.objects.annotate(
-    ...     search=SearchVector('body_text', 'blog__tagline'),
-    ... ).filter(search='Cheese')
+    ...     search=SearchVector("body_text", "blog__tagline"),
+    ... ).filter(search="Cheese")
     [<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]
 
 The arguments to ``SearchVector`` can be any
@@ -65,8 +65,8 @@ For example:
 .. code-block:: pycon
 
     >>> Entry.objects.annotate(
-    ...     search=SearchVector('body_text') + SearchVector('blog__tagline'),
-    ... ).filter(search='Cheese')
+    ...     search=SearchVector("body_text") + SearchVector("blog__tagline"),
+    ... ).filter(search="Cheese")
     [<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]
 
 See :ref:`postgresql-fts-search-configuration` and
@@ -107,9 +107,9 @@ Examples:
 .. code-block:: pycon
 
     >>> from django.contrib.postgres.search import SearchQuery
-    >>> SearchQuery('meat') & SearchQuery('cheese')  # AND
-    >>> SearchQuery('meat') | SearchQuery('cheese')  # OR
-    >>> ~SearchQuery('meat')  # NOT
+    >>> SearchQuery("meat") & SearchQuery("cheese")  # AND
+    >>> SearchQuery("meat") | SearchQuery("cheese")  # OR
+    >>> ~SearchQuery("meat")  # NOT
 
 See :ref:`postgresql-fts-search-configuration` for an explanation of the
 ``config`` parameter.
@@ -130,9 +130,9 @@ order by relevancy:
 .. code-block:: pycon
 
     >>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
-    >>> vector = SearchVector('body_text')
-    >>> query = SearchQuery('cheese')
-    >>> Entry.objects.annotate(rank=SearchRank(vector, query)).order_by('-rank')
+    >>> vector = SearchVector("body_text")
+    >>> query = SearchQuery("cheese")
+    >>> Entry.objects.annotate(rank=SearchRank(vector, query)).order_by("-rank")
     [<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]
 
 See :ref:`postgresql-fts-weighting-queries` for an explanation of the
@@ -199,13 +199,13 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.contrib.postgres.search import SearchHeadline, SearchQuery
-    >>> query = SearchQuery('red tomato')
+    >>> query = SearchQuery("red tomato")
     >>> entry = Entry.objects.annotate(
     ...     headline=SearchHeadline(
-    ...         'body_text',
+    ...         "body_text",
     ...         query,
-    ...         start_sel='<span>',
-    ...         stop_sel='</span>',
+    ...         start_sel="<span>",
+    ...         stop_sel="</span>",
     ...     ),
     ... ).get()
     >>> print(entry.headline)
@@ -229,8 +229,8 @@ different language parsers and dictionaries as defined by the database:
 
     >>> from django.contrib.postgres.search import SearchQuery, SearchVector
     >>> Entry.objects.annotate(
-    ...     search=SearchVector('body_text', config='french'),
-    ... ).filter(search=SearchQuery('œuf', config='french'))
+    ...     search=SearchVector("body_text", config="french"),
+    ... ).filter(search=SearchQuery("œuf", config="french"))
     [<Entry: Pain perdu>]
 
 The value of ``config`` could also be stored in another column:
@@ -239,8 +239,8 @@ The value of ``config`` could also be stored in another column:
 
     >>> from django.db.models import F
     >>> Entry.objects.annotate(
-    ...     search=SearchVector('body_text', config=F('blog__language')),
-    ... ).filter(search=SearchQuery('œuf', config=F('blog__language')))
+    ...     search=SearchVector("body_text", config=F("blog__language")),
+    ... ).filter(search=SearchQuery("œuf", config=F("blog__language")))
     [<Entry: Pain perdu>]
 
 .. _postgresql-fts-weighting-queries:
@@ -254,9 +254,13 @@ of various vectors before you combine them:
 .. code-block:: pycon
 
     >>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
-    >>> vector = SearchVector('body_text', weight='A') + SearchVector('blog__tagline', weight='B')
-    >>> query = SearchQuery('cheese')
-    >>> Entry.objects.annotate(rank=SearchRank(vector, query)).filter(rank__gte=0.3).order_by('rank')
+    >>> vector = SearchVector("body_text", weight="A") + SearchVector(
+    ...     "blog__tagline", weight="B"
+    ... )
+    >>> query = SearchQuery("cheese")
+    >>> Entry.objects.annotate(rank=SearchRank(vector, query)).filter(rank__gte=0.3).order_by(
+    ...     "rank"
+    ... )
 
 The weight should be one of the following letters: D, C, B, A. By default,
 these weights refer to the numbers ``0.1``, ``0.2``, ``0.4``, and ``1.0``,
@@ -266,7 +270,7 @@ floats to :class:`SearchRank` as ``weights`` in the same order above:
 .. code-block:: pycon
 
     >>> rank = SearchRank(vector, query, weights=[0.2, 0.4, 0.6, 0.8])
-    >>> Entry.objects.annotate(rank=rank).filter(rank__gte=0.3).order_by('-rank')
+    >>> Entry.objects.annotate(rank=rank).filter(rank__gte=0.3).order_by("-rank")
 
 Performance
 ===========
@@ -283,8 +287,8 @@ particular model, you can create a functional
 the search vector you wish to use. For example::
 
     GinIndex(
-        SearchVector('body_text', 'headline', config='english'),
-        name='search_vector_idx',
+        SearchVector("body_text", "headline", config="english"),
+        name="search_vector_idx",
     )
 
 The PostgreSQL documentation has details on
@@ -303,8 +307,8 @@ if it were an annotated ``SearchVector``:
 
 .. code-block:: pycon
 
-    >>> Entry.objects.update(search_vector=SearchVector('body_text'))
-    >>> Entry.objects.filter(search_vector='cheese')
+    >>> Entry.objects.update(search_vector=SearchVector("body_text"))
+    >>> Entry.objects.filter(search_vector="cheese")
     [<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]
 
 .. _PostgreSQL documentation: https://www.postgresql.org/docs/current/textsearch-features.html#TEXTSEARCH-UPDATE-TRIGGERS
@@ -336,12 +340,14 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.contrib.postgres.search import TrigramSimilarity
-    >>> Author.objects.create(name='Katy Stevens')
-    >>> Author.objects.create(name='Stephen Keats')
-    >>> test = 'Katie Stephens'
+    >>> Author.objects.create(name="Katy Stevens")
+    >>> Author.objects.create(name="Stephen Keats")
+    >>> test = "Katie Stephens"
     >>> Author.objects.annotate(
-    ...     similarity=TrigramSimilarity('name', test),
-    ... ).filter(similarity__gt=0.3).order_by('-similarity')
+    ...     similarity=TrigramSimilarity("name", test),
+    ... ).filter(
+    ...     similarity__gt=0.3
+    ... ).order_by("-similarity")
     [<Author: Katy Stevens>, <Author: Stephen Keats>]
 
 ``TrigramWordSimilarity``
@@ -357,12 +363,14 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.contrib.postgres.search import TrigramWordSimilarity
-    >>> Author.objects.create(name='Katy Stevens')
-    >>> Author.objects.create(name='Stephen Keats')
-    >>> test = 'Kat'
+    >>> Author.objects.create(name="Katy Stevens")
+    >>> Author.objects.create(name="Stephen Keats")
+    >>> test = "Kat"
     >>> Author.objects.annotate(
-    ...     similarity=TrigramWordSimilarity(test, 'name'),
-    ... ).filter(similarity__gt=0.3).order_by('-similarity')
+    ...     similarity=TrigramWordSimilarity(test, "name"),
+    ... ).filter(
+    ...     similarity__gt=0.3
+    ... ).order_by("-similarity")
     [<Author: Katy Stevens>]
 
 ``TrigramStrictWordSimilarity``
@@ -390,12 +398,14 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.contrib.postgres.search import TrigramDistance
-    >>> Author.objects.create(name='Katy Stevens')
-    >>> Author.objects.create(name='Stephen Keats')
-    >>> test = 'Katie Stephens'
+    >>> Author.objects.create(name="Katy Stevens")
+    >>> Author.objects.create(name="Stephen Keats")
+    >>> test = "Katie Stephens"
     >>> Author.objects.annotate(
-    ...     distance=TrigramDistance('name', test),
-    ... ).filter(distance__lte=0.7).order_by('distance')
+    ...     distance=TrigramDistance("name", test),
+    ... ).filter(
+    ...     distance__lte=0.7
+    ... ).order_by("distance")
     [<Author: Katy Stevens>, <Author: Stephen Keats>]
 
 ``TrigramWordDistance``
@@ -411,12 +421,14 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.contrib.postgres.search import TrigramWordDistance
-    >>> Author.objects.create(name='Katy Stevens')
-    >>> Author.objects.create(name='Stephen Keats')
-    >>> test = 'Kat'
+    >>> Author.objects.create(name="Katy Stevens")
+    >>> Author.objects.create(name="Stephen Keats")
+    >>> test = "Kat"
     >>> Author.objects.annotate(
-    ...     distance=TrigramWordDistance(test, 'name'),
-    ... ).filter(distance__lte=0.7).order_by('distance')
+    ...     distance=TrigramWordDistance(test, "name"),
+    ... ).filter(
+    ...     distance__lte=0.7
+    ... ).order_by("distance")
     [<Author: Katy Stevens>]
 
 ``TrigramStrictWordDistance``

+ 4 - 4
docs/ref/contrib/redirects.txt

@@ -83,16 +83,16 @@ Via the Python API
         >>> # Add a new redirect.
         >>> redirect = Redirect.objects.create(
         ...     site_id=1,
-        ...     old_path='/contact-us/',
-        ...     new_path='/contact/',
+        ...     old_path="/contact-us/",
+        ...     new_path="/contact/",
         ... )
         >>> # Change a redirect.
-        >>> redirect.new_path = '/contact-details/'
+        >>> redirect.new_path = "/contact-details/"
         >>> redirect.save()
         >>> redirect
         <Redirect: /contact-us/ ---> /contact-details/>
         >>> # Delete a redirect.
-        >>> Redirect.objects.filter(site_id=1, old_path='/contact-us/').delete()
+        >>> Redirect.objects.filter(site_id=1, old_path="/contact-us/").delete()
         (1, {'redirects.Redirect': 1})
 
 Middleware

+ 65 - 34
docs/ref/contrib/sitemaps.txt

@@ -54,8 +54,12 @@ To activate sitemap generation on your Django site, add this line to your
 
     from django.contrib.sitemaps.views import sitemap
 
-    path('sitemap.xml', sitemap, {'sitemaps': sitemaps},
-         name='django.contrib.sitemaps.views.sitemap')
+    path(
+        "sitemap.xml",
+        sitemap,
+        {"sitemaps": sitemaps},
+        name="django.contrib.sitemaps.views.sitemap",
+    )
 
 This tells Django to build a sitemap when a client accesses :file:`/sitemap.xml`.
 
@@ -100,6 +104,7 @@ your sitemap class might look::
     from django.contrib.sitemaps import Sitemap
     from blog.models import Entry
 
+
     class BlogSitemap(Sitemap):
         changefreq = "never"
         priority = 0.5
@@ -350,18 +355,20 @@ Here's an example of a :doc:`URLconf </topics/http/urls>` using
     from blog.models import Entry
 
     info_dict = {
-        'queryset': Entry.objects.all(),
-        'date_field': 'pub_date',
+        "queryset": Entry.objects.all(),
+        "date_field": "pub_date",
     }
 
     urlpatterns = [
         # some generic view using info_dict
         # ...
-
         # the sitemap
-        path('sitemap.xml', sitemap,
-             {'sitemaps': {'blog': GenericSitemap(info_dict, priority=0.6)}},
-             name='django.contrib.sitemaps.views.sitemap'),
+        path(
+            "sitemap.xml",
+            sitemap,
+            {"sitemaps": {"blog": GenericSitemap(info_dict, priority=0.6)}},
+            name="django.contrib.sitemaps.views.sitemap",
+        ),
     ]
 
 .. _URLconf: ../url_dispatch/
@@ -378,16 +385,18 @@ the ``location`` method of the sitemap. For example::
     from django.contrib import sitemaps
     from django.urls import reverse
 
+
     class StaticViewSitemap(sitemaps.Sitemap):
         priority = 0.5
-        changefreq = 'daily'
+        changefreq = "daily"
 
         def items(self):
-            return ['main', 'about', 'license']
+            return ["main", "about", "license"]
 
         def location(self, item):
             return reverse(item)
 
+
     # urls.py
     from django.contrib.sitemaps.views import sitemap
     from django.urls import path
@@ -396,16 +405,20 @@ the ``location`` method of the sitemap. For example::
     from . import views
 
     sitemaps = {
-        'static': StaticViewSitemap,
+        "static": StaticViewSitemap,
     }
 
     urlpatterns = [
-        path('', views.main, name='main'),
-        path('about/', views.about, name='about'),
-        path('license/', views.license, name='license'),
+        path("", views.main, name="main"),
+        path("about/", views.about, name="about"),
+        path("license/", views.license, name="license"),
         # ...
-        path('sitemap.xml', sitemap, {'sitemaps': sitemaps},
-             name='django.contrib.sitemaps.views.sitemap')
+        path(
+            "sitemap.xml",
+            sitemap,
+            {"sitemaps": sitemaps},
+            name="django.contrib.sitemaps.views.sitemap",
+        ),
     ]
 
 
@@ -428,10 +441,18 @@ Here's what the relevant URLconf lines would look like for the example above::
     from django.contrib.sitemaps import views
 
     urlpatterns = [
-        path('sitemap.xml', views.index, {'sitemaps': sitemaps},
-             name='django.contrib.sitemaps.views.index'),
-        path('sitemap-<section>.xml', views.sitemap, {'sitemaps': sitemaps},
-             name='django.contrib.sitemaps.views.sitemap'),
+        path(
+            "sitemap.xml",
+            views.index,
+            {"sitemaps": sitemaps},
+            name="django.contrib.sitemaps.views.index",
+        ),
+        path(
+            "sitemap-<section>.xml",
+            views.sitemap,
+            {"sitemaps": sitemaps},
+            name="django.contrib.sitemaps.views.sitemap",
+        ),
     ]
 
 This will automatically generate a :file:`sitemap.xml` file that references
@@ -455,12 +476,17 @@ with a caching decorator -- you must name your sitemap view and pass
     from django.views.decorators.cache import cache_page
 
     urlpatterns = [
-        path('sitemap.xml',
-             cache_page(86400)(sitemaps_views.index),
-             {'sitemaps': sitemaps, 'sitemap_url_name': 'sitemaps'}),
-        path('sitemap-<section>.xml',
-             cache_page(86400)(sitemaps_views.sitemap),
-             {'sitemaps': sitemaps}, name='sitemaps'),
+        path(
+            "sitemap.xml",
+            cache_page(86400)(sitemaps_views.index),
+            {"sitemaps": sitemaps, "sitemap_url_name": "sitemaps"},
+        ),
+        path(
+            "sitemap-<section>.xml",
+            cache_page(86400)(sitemaps_views.sitemap),
+            {"sitemaps": sitemaps},
+            name="sitemaps",
+        ),
     ]
 
 Template customization
@@ -473,14 +499,18 @@ parameter to the ``sitemap`` and ``index`` views via the URLconf::
     from django.contrib.sitemaps import views
 
     urlpatterns = [
-        path('custom-sitemap.xml', views.index, {
-            'sitemaps': sitemaps,
-            'template_name': 'custom_sitemap.html'
-        }, name='django.contrib.sitemaps.views.index'),
-        path('custom-sitemap-<section>.xml', views.sitemap, {
-            'sitemaps': sitemaps,
-            'template_name': 'custom_sitemap.html'
-        }, name='django.contrib.sitemaps.views.sitemap'),
+        path(
+            "custom-sitemap.xml",
+            views.index,
+            {"sitemaps": sitemaps, "template_name": "custom_sitemap.html"},
+            name="django.contrib.sitemaps.views.index",
+        ),
+        path(
+            "custom-sitemap-<section>.xml",
+            views.sitemap,
+            {"sitemaps": sitemaps, "template_name": "custom_sitemap.html"},
+            name="django.contrib.sitemaps.views.sitemap",
+        ),
     ]
 
 
@@ -601,6 +631,7 @@ method::
 
     from django.contrib.sitemaps import ping_google
 
+
     class Entry(models.Model):
         # ...
         def save(self, force_insert=False, force_update=False):

+ 24 - 14
docs/ref/contrib/sites.txt

@@ -65,6 +65,7 @@ Django model terminology, that's represented by a
     from django.contrib.sites.models import Site
     from django.db import models
 
+
     class Article(models.Model):
         headline = models.CharField(max_length=200)
         # ...
@@ -84,6 +85,7 @@ This accomplishes several things quite nicely:
 
       from django.contrib.sites.shortcuts import get_current_site
 
+
       def article_detail(request, article_id):
           try:
               a = Article.objects.get(id=article_id, sites__id=get_current_site(request).id)
@@ -108,6 +110,7 @@ like this::
     from django.contrib.sites.models import Site
     from django.db import models
 
+
     class Article(models.Model):
         headline = models.CharField(max_length=200)
         # ...
@@ -126,6 +129,7 @@ For example::
 
     from django.conf import settings
 
+
     def my_view(request):
         if settings.SITE_ID == 3:
             # Do something.
@@ -140,9 +144,10 @@ domain::
 
     from django.contrib.sites.shortcuts import get_current_site
 
+
     def my_view(request):
         current_site = get_current_site(request)
-        if current_site.domain == 'foo.com':
+        if current_site.domain == "foo.com":
             # Do something
             pass
         else:
@@ -160,9 +165,10 @@ the :setting:`SITE_ID` setting. This example is equivalent to the previous one::
 
     from django.contrib.sites.models import Site
 
+
     def my_function_without_request():
         current_site = Site.objects.get_current()
-        if current_site.domain == 'foo.com':
+        if current_site.domain == "foo.com":
             # Do something
             pass
         else:
@@ -190,17 +196,17 @@ Here's an example of what the form-handling view looks like::
     from django.contrib.sites.shortcuts import get_current_site
     from django.core.mail import send_mail
 
+
     def register_for_newsletter(request):
         # Check form values, etc., and subscribe the user.
         # ...
 
         current_site = get_current_site(request)
         send_mail(
-            'Thanks for subscribing to %s alerts' % current_site.name,
-            'Thanks for your subscription. We appreciate it.\n\n-The %s team.' % (
-                current_site.name,
-            ),
-            'editor@%s' % current_site.domain,
+            "Thanks for subscribing to %s alerts" % current_site.name,
+            "Thanks for your subscription. We appreciate it.\n\n-The %s team."
+            % (current_site.name,),
+            "editor@%s" % current_site.domain,
             [user.email],
         )
 
@@ -218,13 +224,14 @@ farm out to the template system like so::
     from django.core.mail import send_mail
     from django.template import loader
 
+
     def register_for_newsletter(request):
         # Check form values, etc., and subscribe the user.
         # ...
 
-        subject = loader.get_template('alerts/subject.txt').render({})
-        message = loader.get_template('alerts/message.txt').render({})
-        send_mail(subject, message, 'editor@ljworld.com', [user.email])
+        subject = loader.get_template("alerts/subject.txt").render({})
+        message = loader.get_template("alerts/message.txt").render({})
+        send_mail(subject, message, "editor@ljworld.com", [user.email])
 
         # ...
 
@@ -251,7 +258,7 @@ To do this, you can use the sites framework. An example:
     '/mymodel/objects/3/'
     >>> Site.objects.get_current().domain
     'example.com'
-    >>> 'https://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url())
+    >>> "https://%s%s" % (Site.objects.get_current().domain, obj.get_absolute_url())
     'https://example.com/mymodel/objects/3/'
 
 .. _enabling-the-sites-framework:
@@ -328,8 +335,9 @@ your model explicitly. For example::
     from django.contrib.sites.managers import CurrentSiteManager
     from django.db import models
 
+
     class Photo(models.Model):
-        photo = models.FileField(upload_to='photos')
+        photo = models.FileField(upload_to="photos")
         photographer_name = models.CharField(max_length=100)
         pub_date = models.DateField()
         site = models.ForeignKey(Site, on_delete=models.CASCADE)
@@ -365,13 +373,14 @@ demonstrates this::
     from django.contrib.sites.managers import CurrentSiteManager
     from django.db import models
 
+
     class Photo(models.Model):
-        photo = models.FileField(upload_to='photos')
+        photo = models.FileField(upload_to="photos")
         photographer_name = models.CharField(max_length=100)
         pub_date = models.DateField()
         publish_on = models.ForeignKey(Site, on_delete=models.CASCADE)
         objects = models.Manager()
-        on_site = CurrentSiteManager('publish_on')
+        on_site = CurrentSiteManager("publish_on")
 
 If you attempt to use :class:`~django.contrib.sites.managers.CurrentSiteManager`
 and pass a field name that doesn't exist, Django will raise a ``ValueError``.
@@ -397,6 +406,7 @@ If you often use this pattern::
 
     from django.contrib.sites.models import Site
 
+
     def my_view(request):
         site = Site.objects.get_current()
         ...

+ 9 - 5
docs/ref/contrib/staticfiles.txt

@@ -77,10 +77,11 @@ respectively. For example::
 
     from django.contrib.staticfiles import storage
 
+
     class MyStaticFilesStorage(storage.StaticFilesStorage):
         def __init__(self, *args, **kwargs):
-            kwargs['file_permissions_mode'] = 0o640
-            kwargs['directory_permissions_mode'] = 0o760
+            kwargs["file_permissions_mode"] = 0o640
+            kwargs["directory_permissions_mode"] = 0o760
             super().__init__(*args, **kwargs)
 
 Then set the ``staticfiles`` storage backend in :setting:`STORAGES` setting to
@@ -142,6 +143,7 @@ class, override the ``ignore_patterns`` attribute of this class and replace
 
     from django.contrib.staticfiles.apps import StaticFilesConfig
 
+
     class MyStaticFilesConfig(StaticFilesConfig):
         ignore_patterns = [...]  # your custom ignore list
 
@@ -322,9 +324,11 @@ argument. For example::
 
     from django.conf import settings
     from django.contrib.staticfiles.storage import (
-        ManifestStaticFilesStorage, StaticFilesStorage,
+        ManifestStaticFilesStorage,
+        StaticFilesStorage,
     )
 
+
     class MyManifestStaticFilesStorage(ManifestStaticFilesStorage):
         def __init__(self, *args, **kwargs):
             manifest_storage = StaticFilesStorage(location=settings.BASE_DIR)
@@ -421,7 +425,7 @@ of directory paths in which the finders searched. Example usage::
 
     from django.contrib.staticfiles import finders
 
-    result = finders.find('css/base.css')
+    result = finders.find("css/base.css")
     searched_locations = finders.searched_locations
 
 Other Helpers
@@ -499,7 +503,7 @@ primary URL configuration::
 
    if settings.DEBUG:
        urlpatterns += [
-           re_path(r'^static/(?P<path>.*)$', views.serve),
+           re_path(r"^static/(?P<path>.*)$", views.serve),
        ]
 
 Note, the beginning of the pattern (``r'^static/'``) should be your

+ 53 - 44
docs/ref/contrib/syndication.txt

@@ -55,13 +55,14 @@ a feed of the latest five news items::
     from django.urls import reverse
     from policebeat.models import NewsItem
 
+
     class LatestEntriesFeed(Feed):
         title = "Police beat site news"
         link = "/sitenews/"
         description = "Updates on changes and additions to police beat central."
 
         def items(self):
-            return NewsItem.objects.order_by('-pub_date')[:5]
+            return NewsItem.objects.order_by("-pub_date")[:5]
 
         def item_title(self, item):
             return item.title
@@ -71,7 +72,7 @@ a feed of the latest five news items::
 
         # item_link is only needed if NewsItem has no get_absolute_url method.
         def item_link(self, item):
-            return reverse('news-item', args=[item.pk])
+            return reverse("news-item", args=[item.pk])
 
 To connect a URL to this feed, put an instance of the Feed object in
 your :doc:`URLconf </topics/http/urls>`. For example::
@@ -81,7 +82,7 @@ your :doc:`URLconf </topics/http/urls>`. For example::
 
     urlpatterns = [
         # ...
-        path('latest/feed/', LatestEntriesFeed()),
+        path("latest/feed/", LatestEntriesFeed()),
         # ...
     ]
 
@@ -145,16 +146,17 @@ into those elements.
         from mysite.models import Article
         from django.contrib.syndication.views import Feed
 
+
         class ArticlesFeed(Feed):
             title = "My articles"
             description_template = "feeds/articles.html"
 
             def items(self):
-                return Article.objects.order_by('-pub_date')[:5]
+                return Article.objects.order_by("-pub_date")[:5]
 
             def get_context_data(self, **kwargs):
                 context = super().get_context_data(**kwargs)
-                context['foo'] = 'bar'
+                context["foo"] = "bar"
                 return context
 
   And the template:
@@ -215,7 +217,7 @@ The police beat feeds could be accessible via URLs like this:
 
 These can be matched with a :doc:`URLconf </topics/http/urls>` line such as::
 
-    path('beats/<int:beat_id>/rss/', BeatFeed()),
+    path("beats/<int:beat_id>/rss/", BeatFeed()),
 
 Like a view, the arguments in the URL are passed to the ``get_object()``
 method along with the request object.
@@ -224,8 +226,9 @@ Here's the code for these beat-specific feeds::
 
     from django.contrib.syndication.views import Feed
 
+
     class BeatFeed(Feed):
-        description_template = 'feeds/beat_description.html'
+        description_template = "feeds/beat_description.html"
 
         def get_object(self, request, beat_id):
             return Beat.objects.get(pk=beat_id)
@@ -240,7 +243,7 @@ Here's the code for these beat-specific feeds::
             return "Crimes recently reported in police beat %s" % obj.beat
 
         def items(self, obj):
-            return Crime.objects.filter(beat=obj).order_by('-crime_date')[:30]
+            return Crime.objects.filter(beat=obj).order_by("-crime_date")[:30]
 
 To generate the feed's ``<title>``, ``<link>`` and ``<description>``, Django
 uses the ``title()``, ``link()`` and ``description()`` methods. In
@@ -282,6 +285,7 @@ To change that, add a ``feed_type`` attribute to your
 
     from django.utils.feedgenerator import Atom1Feed
 
+
     class MyFeed(Feed):
         feed_type = Atom1Feed
 
@@ -337,13 +341,15 @@ Here's a full example::
     from policebeat.models import NewsItem
     from django.utils.feedgenerator import Atom1Feed
 
+
     class RssSiteNewsFeed(Feed):
         title = "Police beat site news"
         link = "/sitenews/"
         description = "Updates on changes and additions to police beat central."
 
         def items(self):
-            return NewsItem.objects.order_by('-pub_date')[:5]
+            return NewsItem.objects.order_by("-pub_date")[:5]
+
 
     class AtomSiteNewsFeed(RssSiteNewsFeed):
         feed_type = Atom1Feed
@@ -370,8 +376,8 @@ And the accompanying URLconf::
 
     urlpatterns = [
         # ...
-        path('sitenews/rss/', RssSiteNewsFeed()),
-        path('sitenews/atom/', AtomSiteNewsFeed()),
+        path("sitenews/rss/", RssSiteNewsFeed()),
+        path("sitenews/atom/", AtomSiteNewsFeed()),
         # ...
     ]
 
@@ -386,8 +392,8 @@ This example illustrates all possible attributes and methods for a
     from django.contrib.syndication.views import Feed
     from django.utils import feedgenerator
 
-    class ExampleFeed(Feed):
 
+    class ExampleFeed(Feed):
         # FEED TYPE -- Optional. This should be a class that subclasses
         # django.utils.feedgenerator.SyndicationFeed. This designates
         # which type of feed this should be: RSS 2.0, Atom 1.0, etc. If
@@ -407,7 +413,7 @@ This example illustrates all possible attributes and methods for a
 
         # LANGUAGE -- Optional. This should be a string specifying a language
         # code. Defaults to django.utils.translation.get_language().
-        language = 'de'
+        language = "de"
 
         # TITLE -- One of the following three is required. The framework
         # looks for them in this order.
@@ -423,7 +429,7 @@ This example illustrates all possible attributes and methods for a
             Returns the feed's title as a normal Python string.
             """
 
-        title = 'foo' # Hard-coded title.
+        title = "foo"  # Hard-coded title.
 
         # LINK -- One of the following three is required. The framework
         # looks for them in this order.
@@ -440,7 +446,7 @@ This example illustrates all possible attributes and methods for a
             string.
             """
 
-        link = '/blog/' # Hard-coded URL.
+        link = "/blog/"  # Hard-coded URL.
 
         # FEED_URL -- One of the following three is optional. The framework
         # looks for them in this order.
@@ -456,7 +462,7 @@ This example illustrates all possible attributes and methods for a
             Returns the feed's own URL as a normal Python string.
             """
 
-        feed_url = '/blog/rss/' # Hard-coded URL.
+        feed_url = "/blog/rss/"  # Hard-coded URL.
 
         # GUID -- One of the following three is optional. The framework looks
         # for them in this order. This property is only used for Atom feeds
@@ -474,7 +480,7 @@ This example illustrates all possible attributes and methods for a
             Returns the feed's globally unique ID as a normal Python string.
             """
 
-        feed_guid = '/foo/bar/1234' # Hard-coded guid.
+        feed_guid = "/foo/bar/1234"  # Hard-coded guid.
 
         # DESCRIPTION -- One of the following three is required. The framework
         # looks for them in this order.
@@ -490,7 +496,7 @@ This example illustrates all possible attributes and methods for a
             Returns the feed's description as a normal Python string.
             """
 
-        description = 'Foo bar baz.' # Hard-coded description.
+        description = "Foo bar baz."  # Hard-coded description.
 
         # AUTHOR NAME --One of the following three is optional. The framework
         # looks for them in this order.
@@ -506,7 +512,7 @@ This example illustrates all possible attributes and methods for a
             Returns the feed's author's name as a normal Python string.
             """
 
-        author_name = 'Sally Smith' # Hard-coded author name.
+        author_name = "Sally Smith"  # Hard-coded author name.
 
         # AUTHOR EMAIL --One of the following three is optional. The framework
         # looks for them in this order.
@@ -522,7 +528,7 @@ This example illustrates all possible attributes and methods for a
             Returns the feed's author's email as a normal Python string.
             """
 
-        author_email = 'test@example.com' # Hard-coded author email.
+        author_email = "test@example.com"  # Hard-coded author email.
 
         # AUTHOR LINK --One of the following three is optional. The framework
         # looks for them in this order. In each case, the URL should include
@@ -539,7 +545,7 @@ This example illustrates all possible attributes and methods for a
             Returns the feed's author's URL as a normal Python string.
             """
 
-        author_link = 'https://www.example.com/' # Hard-coded author URL.
+        author_link = "https://www.example.com/"  # Hard-coded author URL.
 
         # CATEGORIES -- One of the following three is optional. The framework
         # looks for them in this order. In each case, the method/attribute
@@ -556,7 +562,7 @@ This example illustrates all possible attributes and methods for a
             Returns the feed's categories as iterable over strings.
             """
 
-        categories = ["python", "django"] # Hard-coded list of categories.
+        categories = ["python", "django"]  # Hard-coded list of categories.
 
         # COPYRIGHT NOTICE -- One of the following three is optional. The
         # framework looks for them in this order.
@@ -572,7 +578,7 @@ This example illustrates all possible attributes and methods for a
             Returns the feed's copyright notice as a normal Python string.
             """
 
-        feed_copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice.
+        feed_copyright = "Copyright (c) 2007, Sally Smith"  # Hard-coded copyright notice.
 
         # TTL -- One of the following three is optional. The framework looks
         # for them in this order. Ignored for Atom feeds.
@@ -588,7 +594,7 @@ This example illustrates all possible attributes and methods for a
             Returns the feed's TTL as a normal Python string.
             """
 
-        ttl = 600 # Hard-coded Time To Live.
+        ttl = 600  # Hard-coded Time To Live.
 
         # ITEMS -- One of the following three is required. The framework looks
         # for them in this order.
@@ -604,7 +610,7 @@ This example illustrates all possible attributes and methods for a
             Returns a list of items to publish in this feed.
             """
 
-        items = ['Item 1', 'Item 2'] # Hard-coded items.
+        items = ["Item 1", "Item 2"]  # Hard-coded items.
 
         # GET_OBJECT -- This is required for feeds that publish different data
         # for different URL parameters. (See "A complex example" above.)
@@ -632,7 +638,7 @@ This example illustrates all possible attributes and methods for a
             Returns the title for every item in the feed.
             """
 
-        item_title = 'Breaking News: Nothing Happening' # Hard-coded title.
+        item_title = "Breaking News: Nothing Happening"  # Hard-coded title.
 
         def item_description(self, item):
             """
@@ -645,7 +651,7 @@ This example illustrates all possible attributes and methods for a
             Returns the description for every item in the feed.
             """
 
-        item_description = 'A description of the item.' # Hard-coded description.
+        item_description = "A description of the item."  # Hard-coded description.
 
         def get_context_data(self, **kwargs):
             """
@@ -707,7 +713,7 @@ This example illustrates all possible attributes and methods for a
             Returns the author name for every item in the feed.
             """
 
-        item_author_name = 'Sally Smith' # Hard-coded author name.
+        item_author_name = "Sally Smith"  # Hard-coded author name.
 
         # ITEM AUTHOR EMAIL --One of the following three is optional. The
         # framework looks for them in this order.
@@ -725,7 +731,7 @@ This example illustrates all possible attributes and methods for a
             Returns the author email for every item in the feed.
             """
 
-        item_author_email = 'test@example.com' # Hard-coded author email.
+        item_author_email = "test@example.com"  # Hard-coded author email.
 
         # ITEM AUTHOR LINK -- One of the following three is optional. The
         # framework looks for them in this order. In each case, the URL should
@@ -744,7 +750,7 @@ This example illustrates all possible attributes and methods for a
             Returns the author URL for every item in the feed.
             """
 
-        item_author_link = 'https://www.example.com/' # Hard-coded author URL.
+        item_author_link = "https://www.example.com/"  # Hard-coded author URL.
 
         # ITEM ENCLOSURES -- One of the following three is optional. The
         # framework looks for them in this order. If one of them is defined,
@@ -780,7 +786,7 @@ This example illustrates all possible attributes and methods for a
             Returns the enclosure URL for every item in the feed.
             """
 
-        item_enclosure_url = "/foo/bar.mp3" # Hard-coded enclosure link.
+        item_enclosure_url = "/foo/bar.mp3"  # Hard-coded enclosure link.
 
         # ITEM ENCLOSURE LENGTH -- One of these three is required if you're
         # publishing enclosures and you're not using ``item_enclosures``. The
@@ -799,7 +805,7 @@ This example illustrates all possible attributes and methods for a
             Returns the enclosure length for every item in the feed.
             """
 
-        item_enclosure_length = 32000 # Hard-coded enclosure length.
+        item_enclosure_length = 32000  # Hard-coded enclosure length.
 
         # ITEM ENCLOSURE MIME TYPE -- One of these three is required if you're
         # publishing enclosures and you're not using ``item_enclosures``. The
@@ -816,7 +822,7 @@ This example illustrates all possible attributes and methods for a
             Returns the enclosure MIME type for every item in the feed.
             """
 
-        item_enclosure_mime_type = "audio/mpeg" # Hard-coded enclosure MIME type.
+        item_enclosure_mime_type = "audio/mpeg"  # Hard-coded enclosure MIME type.
 
         # ITEM PUBDATE -- It's optional to use one of these three. This is a
         # hook that specifies how to get the pubdate for a given item.
@@ -834,7 +840,7 @@ This example illustrates all possible attributes and methods for a
             Returns the pubdate for every item in the feed.
             """
 
-        item_pubdate = datetime.datetime(2005, 5, 3) # Hard-coded pubdate.
+        item_pubdate = datetime.datetime(2005, 5, 3)  # Hard-coded pubdate.
 
         # ITEM UPDATED -- It's optional to use one of these three. This is a
         # hook that specifies how to get the updateddate for a given item.
@@ -852,7 +858,7 @@ This example illustrates all possible attributes and methods for a
             Returns the updateddate for every item in the feed.
             """
 
-        item_updateddate = datetime.datetime(2005, 5, 3) # Hard-coded updateddate.
+        item_updateddate = datetime.datetime(2005, 5, 3)  # Hard-coded updateddate.
 
         # ITEM CATEGORIES -- It's optional to use one of these three. This is
         # a hook that specifies how to get the list of categories for a given
@@ -870,7 +876,7 @@ This example illustrates all possible attributes and methods for a
             Returns the categories for every item in the feed.
             """
 
-        item_categories = ["python", "django"] # Hard-coded categories.
+        item_categories = ["python", "django"]  # Hard-coded categories.
 
         # ITEM COPYRIGHT NOTICE (only applicable to Atom feeds) -- One of the
         # following three is optional. The framework looks for them in this
@@ -887,7 +893,7 @@ This example illustrates all possible attributes and methods for a
             Returns the copyright notice for every item in the feed.
             """
 
-        item_copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice.
+        item_copyright = "Copyright (c) 2007, Sally Smith"  # Hard-coded copyright notice.
 
         # ITEM COMMENTS URL -- It's optional to use one of these three. This is
         # a hook that specifies how to get the URL of a page for comments for a
@@ -904,7 +910,7 @@ This example illustrates all possible attributes and methods for a
             Returns the comments URL for every item in the feed.
             """
 
-        item_comments = 'https://www.example.com/comments' # Hard-coded comments URL
+        item_comments = "https://www.example.com/comments"  # Hard-coded comments URL
 
 The low-level framework
 =======================
@@ -1016,12 +1022,15 @@ For example, to create an Atom 1.0 feed and print it to standard output:
     ...     description="In which I write about what I ate today.",
     ...     language="en",
     ...     author_name="Myself",
-    ...     feed_url="https://example.com/atom.xml")
-    >>> f.add_item(title="Hot dog today",
+    ...     feed_url="https://example.com/atom.xml",
+    ... )
+    >>> f.add_item(
+    ...     title="Hot dog today",
     ...     link="https://www.example.com/entries/1/",
     ...     pubdate=datetime.now(),
-    ...     description="<p>Today I had a Vienna Beef hot dog. It was pink, plump and perfect.</p>")
-    >>> print(f.writeString('UTF-8'))
+    ...     description="<p>Today I had a Vienna Beef hot dog. It was pink, plump and perfect.</p>",
+    ... )
+    >>> print(f.writeString("UTF-8"))
     <?xml version="1.0" encoding="UTF-8"?>
     <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
     ...
@@ -1077,12 +1086,12 @@ For example, you might start implementing an iTunes RSS feed generator like so::
     class iTunesFeed(Rss201rev2Feed):
         def root_attributes(self):
             attrs = super().root_attributes()
-            attrs['xmlns:itunes'] = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
+            attrs["xmlns:itunes"] = "http://www.itunes.com/dtds/podcast-1.0.dtd"
             return attrs
 
         def add_root_elements(self, handler):
             super().add_root_elements(handler)
-            handler.addQuickElement('itunes:explicit', 'clean')
+            handler.addQuickElement("itunes:explicit", "clean")
 
 There's a lot more work to be done for a complete custom feed class, but the
 above example should demonstrate the basic idea.

+ 4 - 1
docs/ref/csrf.txt

@@ -145,9 +145,10 @@ class-based views<decorating-class-based-views>`.
         from django.http import HttpResponse
         from django.views.decorators.csrf import csrf_exempt
 
+
         @csrf_exempt
         def my_view(request):
-            return HttpResponse('Hello world')
+            return HttpResponse("Hello world")
 
 .. function:: csrf_protect(view)
 
@@ -158,6 +159,7 @@ class-based views<decorating-class-based-views>`.
         from django.shortcuts import render
         from django.views.decorators.csrf import csrf_protect
 
+
         @csrf_protect
         def my_view(request):
             c = {}
@@ -177,6 +179,7 @@ class-based views<decorating-class-based-views>`.
         from django.shortcuts import render
         from django.views.decorators.csrf import requires_csrf_token
 
+
         @requires_csrf_token
         def my_view(request):
             c = {}

+ 44 - 42
docs/ref/databases.txt

@@ -137,11 +137,11 @@ password from the `password file`_, you must specify them in the
     :caption: ``settings.py``
 
     DATABASES = {
-        'default': {
-            'ENGINE': 'django.db.backends.postgresql',
-            'OPTIONS': {
-                'service': 'my_service',
-                'passfile': '.my_pgpass',
+        "default": {
+            "ENGINE": "django.db.backends.postgresql",
+            "OPTIONS": {
+                "service": "my_service",
+                "passfile": ".my_pgpass",
             },
         }
     }
@@ -206,8 +206,8 @@ configuration in :setting:`DATABASES`::
 
     DATABASES = {
         # ...
-        'OPTIONS': {
-            'isolation_level': IsolationLevel.SERIALIZABLE,
+        "OPTIONS": {
+            "isolation_level": IsolationLevel.SERIALIZABLE,
         },
     }
 
@@ -353,11 +353,10 @@ cause a conflict. For example:
 .. code-block:: pycon
 
     >>> from django.contrib.auth.models import User
-    >>> User.objects.create(username='alice', pk=1)
+    >>> User.objects.create(username="alice", pk=1)
     <User: alice>
     >>> # The sequence hasn't been updated; its next value is 1.
-    >>> User.objects.create(username='bob')
-    ...
+    >>> User.objects.create(username="bob")
     IntegrityError: duplicate key value violates unique constraint
     "auth_user_pkey" DETAIL:  Key (id)=(1) already exists.
 
@@ -567,10 +566,10 @@ Here's a sample configuration which uses a MySQL option file::
 
     # settings.py
     DATABASES = {
-        'default': {
-            'ENGINE': 'django.db.backends.mysql',
-            'OPTIONS': {
-                'read_default_file': '/path/to/my.cnf',
+        "default": {
+            "ENGINE": "django.db.backends.mysql",
+            "OPTIONS": {
+                "read_default_file": "/path/to/my.cnf",
             },
         }
     }
@@ -657,8 +656,8 @@ storage engine, you have a couple of options.
 * Another option is to use the ``init_command`` option for MySQLdb prior to
   creating your tables::
 
-      'OPTIONS': {
-         'init_command': 'SET default_storage_engine=INNODB',
+      "OPTIONS": {
+          "init_command": "SET default_storage_engine=INNODB",
       }
 
   This sets the default storage engine upon connecting to the database.
@@ -864,9 +863,9 @@ If you're getting this error, you can solve it by:
 * Increase the default timeout value by setting the ``timeout`` database
   option::
 
-      'OPTIONS': {
+      "OPTIONS": {
           # ...
-          'timeout': 20,
+          "timeout": 20,
           # ...
       }
 
@@ -976,13 +975,13 @@ To connect using the service name of your Oracle database, your ``settings.py``
 file should look something like this::
 
     DATABASES = {
-        'default': {
-            'ENGINE': 'django.db.backends.oracle',
-            'NAME': 'xe',
-            'USER': 'a_user',
-            'PASSWORD': 'a_password',
-            'HOST': '',
-            'PORT': '',
+        "default": {
+            "ENGINE": "django.db.backends.oracle",
+            "NAME": "xe",
+            "USER": "a_user",
+            "PASSWORD": "a_password",
+            "HOST": "",
+            "PORT": "",
         }
     }
 
@@ -993,13 +992,13 @@ and want to connect using the SID ("xe" in this example), then fill in both
 :setting:`HOST` and :setting:`PORT` like so::
 
     DATABASES = {
-        'default': {
-            'ENGINE': 'django.db.backends.oracle',
-            'NAME': 'xe',
-            'USER': 'a_user',
-            'PASSWORD': 'a_password',
-            'HOST': 'dbprod01ned.mycompany.com',
-            'PORT': '1540',
+        "default": {
+            "ENGINE": "django.db.backends.oracle",
+            "NAME": "xe",
+            "USER": "a_user",
+            "PASSWORD": "a_password",
+            "HOST": "dbprod01ned.mycompany.com",
+            "PORT": "1540",
         }
     }
 
@@ -1016,13 +1015,13 @@ using RAC or pluggable databases without ``tnsnames.ora``, for example.
 
 Example of an Easy Connect string::
 
-    'NAME': 'localhost:1521/orclpdb1'
+    "NAME": "localhost:1521/orclpdb1"
 
 Example of a full DSN string::
 
-    'NAME': (
-        '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))'
-        '(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))'
+    "NAME": (
+        "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))"
+        "(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))"
     )
 
 Threaded option
@@ -1032,8 +1031,8 @@ If you plan to run Django in a multithreaded environment (e.g. Apache using the
 default MPM module on any modern operating system), then you **must** set
 the ``threaded`` option of your Oracle database configuration to ``True``::
 
-    'OPTIONS': {
-        'threaded': True,
+    "OPTIONS": {
+        "threaded": True,
     }
 
 Failure to do this may result in crashes and other odd behavior.
@@ -1048,8 +1047,8 @@ inserting into a remote table, or into a view with an ``INSTEAD OF`` trigger.
 The ``RETURNING INTO`` clause can be disabled by setting the
 ``use_returning_into`` option of the database configuration to ``False``::
 
-    'OPTIONS': {
-        'use_returning_into': False,
+    "OPTIONS": {
+        "use_returning_into": False,
     }
 
 In this case, the Oracle backend will use a separate ``SELECT`` query to
@@ -1071,6 +1070,7 @@ a quoted name as the value for ``db_table``::
         class Meta:
             db_table = '"name_left_in_lowercase"'
 
+
     class ForeignModel(models.Model):
         class Meta:
             db_table = '"OTHER_USER"."NAME_ONLY_SEEMS_OVER_30"'
@@ -1146,10 +1146,12 @@ example of subclassing the PostgreSQL engine to change a feature class
 
     from django.db.backends.postgresql import base, features
 
+
     class DatabaseFeatures(features.DatabaseFeatures):
         def allows_group_by_selected_pks_on_model(self, model):
             return True
 
+
     class DatabaseWrapper(base.DatabaseWrapper):
         features_class = DatabaseFeatures
 
@@ -1157,8 +1159,8 @@ Finally, you must specify a :setting:`DATABASE-ENGINE` in your ``settings.py``
 file::
 
     DATABASES = {
-        'default': {
-            'ENGINE': 'mydbengine',
+        "default": {
+            "ENGINE": "mydbengine",
             # ...
         },
     }

+ 9 - 9
docs/ref/django-admin.txt

@@ -2097,9 +2097,9 @@ Examples::
       from django.core import management
       from django.core.management.commands import loaddata
 
-      management.call_command('flush', verbosity=0, interactive=False)
-      management.call_command('loaddata', 'test_data', verbosity=0)
-      management.call_command(loaddata.Command(), 'test_data', verbosity=0)
+      management.call_command("flush", verbosity=0, interactive=False)
+      management.call_command("loaddata", "test_data", verbosity=0)
+      management.call_command(loaddata.Command(), "test_data", verbosity=0)
 
 Note that command options that take no arguments are passed as keywords
 with ``True`` or ``False``, as you can see with the ``interactive`` option above.
@@ -2107,14 +2107,14 @@ with ``True`` or ``False``, as you can see with the ``interactive`` option above
 Named arguments can be passed by using either one of the following syntaxes::
 
       # Similar to the command line
-      management.call_command('dumpdata', '--natural-foreign')
+      management.call_command("dumpdata", "--natural-foreign")
 
       # Named argument similar to the command line minus the initial dashes and
       # with internal dashes replaced by underscores
-      management.call_command('dumpdata', natural_foreign=True)
+      management.call_command("dumpdata", natural_foreign=True)
 
       # `use_natural_foreign_keys` is the option destination variable
-      management.call_command('dumpdata', use_natural_foreign_keys=True)
+      management.call_command("dumpdata", use_natural_foreign_keys=True)
 
 Some command options have different names when using ``call_command()`` instead
 of ``django-admin`` or ``manage.py``. For example, ``django-admin
@@ -2125,7 +2125,7 @@ passed to ``parser.add_argument()``.
 
 Command options which take multiple options are passed a list::
 
-      management.call_command('dumpdata', exclude=['contenttypes', 'auth'])
+      management.call_command("dumpdata", exclude=["contenttypes", "auth"])
 
 The return value of the ``call_command()`` function is the same as the return
 value of the ``handle()`` method of the command.
@@ -2136,5 +2136,5 @@ Output redirection
 Note that you can redirect standard output and error streams as all commands
 support the ``stdout`` and ``stderr`` options. For example, you could write::
 
-    with open('/path/to/command_output', 'w') as f:
-        management.call_command('dumpdata', stdout=f)
+    with open("/path/to/command_output", "w") as f:
+        management.call_command("dumpdata", stdout=f)

+ 2 - 2
docs/ref/files/file.txt

@@ -139,14 +139,14 @@ below) will also have a couple of extra methods:
 
     .. code-block:: pycon
 
-        >>> car.photo.save('myphoto.jpg', content, save=False)
+        >>> car.photo.save("myphoto.jpg", content, save=False)
         >>> car.save()
 
     are equivalent to:
 
     .. code-block:: pycon
 
-        >>> car.photo.save('myphoto.jpg', content, save=True)
+        >>> car.photo.save("myphoto.jpg", content, save=True)
 
     Note that the ``content`` argument must be an instance of either
     :class:`File` or of a subclass of :class:`File`, such as

+ 127 - 92
docs/ref/forms/api.txt

@@ -36,10 +36,12 @@ your :class:`Form` class constructor:
 
 .. code-block:: pycon
 
-    >>> data = {'subject': 'hello',
-    ...         'message': 'Hi there',
-    ...         'sender': 'foo@example.com',
-    ...         'cc_myself': True}
+    >>> data = {
+    ...     "subject": "hello",
+    ...     "message": "Hi there",
+    ...     "sender": "foo@example.com",
+    ...     "cc_myself": True,
+    ... }
     >>> f = ContactForm(data)
 
 In this dictionary, the keys are the field names, which correspond to the
@@ -58,7 +60,7 @@ check the value of the form's :attr:`~Form.is_bound` attribute:
     >>> f = ContactForm()
     >>> f.is_bound
     False
-    >>> f = ContactForm({'subject': 'hello'})
+    >>> f = ContactForm({"subject": "hello"})
     >>> f.is_bound
     True
 
@@ -93,10 +95,12 @@ and return a boolean designating whether the data was valid:
 
 .. code-block:: pycon
 
-    >>> data = {'subject': 'hello',
-    ...         'message': 'Hi there',
-    ...         'sender': 'foo@example.com',
-    ...         'cc_myself': True}
+    >>> data = {
+    ...     "subject": "hello",
+    ...     "message": "Hi there",
+    ...     "sender": "foo@example.com",
+    ...     "cc_myself": True,
+    ... }
     >>> f = ContactForm(data)
     >>> f.is_valid()
     True
@@ -107,10 +111,12 @@ email address:
 
 .. code-block:: pycon
 
-    >>> data = {'subject': '',
-    ...         'message': 'Hi there',
-    ...         'sender': 'invalid email address',
-    ...         'cc_myself': True}
+    >>> data = {
+    ...     "subject": "",
+    ...     "message": "Hi there",
+    ...     "sender": "invalid email address",
+    ...     "cc_myself": True,
+    ... }
     >>> f = ContactForm(data)
     >>> f.is_valid()
     False
@@ -256,7 +262,7 @@ it's not necessary to include every field in your form. For example:
 
 .. code-block:: pycon
 
-    >>> f = ContactForm(initial={'subject': 'Hi there!'})
+    >>> f = ContactForm(initial={"subject": "Hi there!"})
 
 These values are only displayed for unbound forms, and they're not used as
 fallback values if a particular value isn't provided.
@@ -271,10 +277,11 @@ precedence:
 
     >>> from django import forms
     >>> class CommentForm(forms.Form):
-    ...     name = forms.CharField(initial='class')
+    ...     name = forms.CharField(initial="class")
     ...     url = forms.URLField()
     ...     comment = forms.CharField()
-    >>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
+    ...
+    >>> f = CommentForm(initial={"name": "instance"}, auto_id=False)
     >>> print(f)
     <div>Name:<input type="text" name="name" value="instance" required></div>
     <div>Url:<input type="url" name="url" required></div>
@@ -298,15 +305,16 @@ dealing with callables whose return values can change (e.g. ``datetime.now`` or
     >>> import uuid
     >>> class UUIDCommentForm(CommentForm):
     ...     identifier = forms.UUIDField(initial=uuid.uuid4)
+    ...
     >>> f = UUIDCommentForm()
-    >>> f.get_initial_for_field(f.fields['identifier'], 'identifier')
+    >>> f.get_initial_for_field(f.fields["identifier"], "identifier")
     UUID('972ca9e4-7bfe-4f5b-af7d-07b3aa306334')
-    >>> f.get_initial_for_field(f.fields['identifier'], 'identifier')
+    >>> f.get_initial_for_field(f.fields["identifier"], "identifier")
     UUID('1b411fab-844e-4dec-bd4f-e9b0495f04d0')
     >>> # Using BoundField.initial, for comparison
-    >>> f['identifier'].initial
+    >>> f["identifier"].initial
     UUID('28a09c59-5f00-4ed9-9179-a3b074fa9c30')
-    >>> f['identifier'].initial
+    >>> f["identifier"].initial
     UUID('28a09c59-5f00-4ed9-9179-a3b074fa9c30')
 
 Checking which form data has changed
@@ -358,12 +366,13 @@ attribute:
 
 .. code-block:: pycon
 
-    >>> for row in f.fields.values(): print(row)
+    >>> for row in f.fields.values():
+    ...     print(row)
     ...
     <django.forms.fields.CharField object at 0x7ffaac632510>
     <django.forms.fields.URLField object at 0x7ffaac632f90>
     <django.forms.fields.CharField object at 0x7ffaac3aa050>
-    >>> f.fields['name']
+    >>> f.fields["name"]
     <django.forms.fields.CharField object at 0x7ffaac6324d0>
 
 You can alter the field and :class:`.BoundField` of :class:`Form` instance to
@@ -409,10 +418,12 @@ it, you can access the clean data via its ``cleaned_data`` attribute:
 
 .. code-block:: pycon
 
-    >>> data = {'subject': 'hello',
-    ...         'message': 'Hi there',
-    ...         'sender': 'foo@example.com',
-    ...         'cc_myself': True}
+    >>> data = {
+    ...     "subject": "hello",
+    ...     "message": "Hi there",
+    ...     "sender": "foo@example.com",
+    ...     "cc_myself": True,
+    ... }
     >>> f = ContactForm(data)
     >>> f.is_valid()
     True
@@ -428,10 +439,12 @@ only the valid fields:
 
 .. code-block:: pycon
 
-    >>> data = {'subject': '',
-    ...         'message': 'Hi there',
-    ...         'sender': 'invalid email address',
-    ...         'cc_myself': True}
+    >>> data = {
+    ...     "subject": "",
+    ...     "message": "Hi there",
+    ...     "sender": "invalid email address",
+    ...     "cc_myself": True,
+    ... }
     >>> f = ContactForm(data)
     >>> f.is_valid()
     False
@@ -445,17 +458,19 @@ but ``cleaned_data`` contains only the form's fields:
 
 .. code-block:: pycon
 
-    >>> data = {'subject': 'hello',
-    ...         'message': 'Hi there',
-    ...         'sender': 'foo@example.com',
-    ...         'cc_myself': True,
-    ...         'extra_field_1': 'foo',
-    ...         'extra_field_2': 'bar',
-    ...         'extra_field_3': 'baz'}
+    >>> data = {
+    ...     "subject": "hello",
+    ...     "message": "Hi there",
+    ...     "sender": "foo@example.com",
+    ...     "cc_myself": True,
+    ...     "extra_field_1": "foo",
+    ...     "extra_field_2": "bar",
+    ...     "extra_field_3": "baz",
+    ... }
     >>> f = ContactForm(data)
     >>> f.is_valid()
     True
-    >>> f.cleaned_data # Doesn't contain extra_field_1, etc.
+    >>> f.cleaned_data  # Doesn't contain extra_field_1, etc.
     {'cc_myself': True, 'message': 'Hi there', 'sender': 'foo@example.com', 'subject': 'hello'}
 
 When the ``Form`` is valid, ``cleaned_data`` will include a key and value for
@@ -470,7 +485,8 @@ fields. In this example, the data dictionary doesn't include a value for the
     ...     first_name = forms.CharField()
     ...     last_name = forms.CharField()
     ...     nick_name = forms.CharField(required=False)
-    >>> data = {'first_name': 'John', 'last_name': 'Lennon'}
+    ...
+    >>> data = {"first_name": "John", "last_name": "Lennon"}
     >>> f = OptionalPersonForm(data)
     >>> f.is_valid()
     True
@@ -513,10 +529,12 @@ include ``checked`` if appropriate:
 
 .. code-block:: pycon
 
-    >>> data = {'subject': 'hello',
-    ...         'message': 'Hi there',
-    ...         'sender': 'foo@example.com',
-    ...         'cc_myself': True}
+    >>> data = {
+    ...     "subject": "hello",
+    ...     "message": "Hi there",
+    ...     "sender": "foo@example.com",
+    ...     "cc_myself": True,
+    ... }
     >>> f = ContactForm(data)
     >>> print(f)
     <div><label for="id_subject">Subject:</label><input type="text" name="subject" value="hello" maxlength="100" required id="id_subject"></div>
@@ -764,9 +782,10 @@ attributes::
 
     from django import forms
 
+
     class ContactForm(forms.Form):
-        error_css_class = 'error'
-        required_css_class = 'required'
+        error_css_class = "error"
+        required_css_class = "required"
 
         # ... and the rest of your fields here
 
@@ -781,13 +800,13 @@ classes, as needed. The HTML will look something like:
     <div class="required"><label for="id_message" class="required">Message:</label> ...
     <div class="required"><label for="id_sender" class="required">Sender:</label> ...
     <div><label for="id_cc_myself">Cc myself:</label> ...
-    >>> f['subject'].label_tag()
+    >>> f["subject"].label_tag()
     <label class="required" for="id_subject">Subject:</label>
-    >>> f['subject'].legend_tag()
+    >>> f["subject"].legend_tag()
     <legend class="required" for="id_subject">Subject:</legend>
-    >>> f['subject'].label_tag(attrs={'class': 'foo'})
+    >>> f["subject"].label_tag(attrs={"class": "foo"})
     <label for="id_subject" class="foo required">Subject:</label>
-    >>> f['subject'].legend_tag(attrs={'class': 'foo'})
+    >>> f["subject"].legend_tag(attrs={"class": "foo"})
     <legend for="id_subject" class="foo required">Subject:</legend>
 
 .. _ref-forms-api-configuring-label:
@@ -847,7 +866,7 @@ attributes based on the format string. For example, for a format string
 
 .. code-block:: pycon
 
-    >>> f = ContactForm(auto_id='id_for_%s')
+    >>> f = ContactForm(auto_id="id_for_%s")
     >>> print(f)
     <div><label for="id_for_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
     <div><label for="id_for_message">Message:</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
@@ -869,13 +888,13 @@ It's possible to customize that character, or omit it entirely, using the
 
 .. code-block:: pycon
 
-    >>> f = ContactForm(auto_id='id_for_%s', label_suffix='')
+    >>> f = ContactForm(auto_id="id_for_%s", label_suffix="")
     >>> print(f)
     <div><label for="id_for_subject">Subject</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
     <div><label for="id_for_message">Message</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
     <div><label for="id_for_sender">Sender</label><input type="email" name="sender" required id="id_for_sender"></div>
     <div><label for="id_for_cc_myself">Cc myself</label><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></div>
-    >>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->')
+    >>> f = ContactForm(auto_id="id_for_%s", label_suffix=" ->")
     >>> print(f)
     <div><label for="id_for_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
     <div><label for="id_for_message">Message -&gt;</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
@@ -916,6 +935,7 @@ You can set this as a class attribute when declaring your form or use the
 
     from django import forms
 
+
     class MyForm(forms.Form):
         default_renderer = MyRenderer()
 
@@ -964,10 +984,12 @@ method you're using:
 
 .. code-block:: pycon
 
-    >>> data = {'subject': '',
-    ...         'message': 'Hi there',
-    ...         'sender': 'invalid email address',
-    ...         'cc_myself': True}
+    >>> data = {
+    ...     "subject": "",
+    ...     "message": "Hi there",
+    ...     "sender": "invalid email address",
+    ...     "cc_myself": True,
+    ... }
     >>> f = ContactForm(data, auto_id=False)
     >>> print(f)
     <div>Subject:<ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" required></div>
@@ -1072,7 +1094,7 @@ using the field's name as the key:
 .. code-block:: pycon
 
     >>> form = ContactForm()
-    >>> print(form['subject'])
+    >>> print(form["subject"])
     <input id="id_subject" type="text" name="subject" maxlength="100" required>
 
 To retrieve all ``BoundField`` objects, iterate the form:
@@ -1080,7 +1102,9 @@ To retrieve all ``BoundField`` objects, iterate the form:
 .. code-block:: pycon
 
     >>> form = ContactForm()
-    >>> for boundfield in form: print(boundfield)
+    >>> for boundfield in form:
+    ...     print(boundfield)
+    ...
     <input id="id_subject" type="text" name="subject" maxlength="100" required>
     <input type="text" name="message" id="id_message" required>
     <input type="email" name="sender" id="id_sender" required>
@@ -1091,10 +1115,10 @@ The field-specific output honors the form object's ``auto_id`` setting:
 .. code-block:: pycon
 
     >>> f = ContactForm(auto_id=False)
-    >>> print(f['message'])
+    >>> print(f["message"])
     <input type="text" name="message" required>
-    >>> f = ContactForm(auto_id='id_%s')
-    >>> print(f['message'])
+    >>> f = ContactForm(auto_id="id_%s")
+    >>> print(f["message"])
     <input type="text" name="message" id="id_message" required>
 
 Attributes of ``BoundField``
@@ -1114,10 +1138,10 @@ Attributes of ``BoundField``
     .. code-block:: pycon
 
         >>> unbound_form = ContactForm()
-        >>> print(unbound_form['subject'].data)
+        >>> print(unbound_form["subject"].data)
         None
-        >>> bound_form = ContactForm(data={'subject': 'My Subject'})
-        >>> print(bound_form['subject'].data)
+        >>> bound_form = ContactForm(data={"subject": "My Subject"})
+        >>> print(bound_form["subject"].data)
         My Subject
 
 .. attribute:: BoundField.errors
@@ -1127,19 +1151,19 @@ Attributes of ``BoundField``
 
     .. code-block:: pycon
 
-        >>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''}
+        >>> data = {"subject": "hi", "message": "", "sender": "", "cc_myself": ""}
         >>> f = ContactForm(data, auto_id=False)
-        >>> print(f['message'])
+        >>> print(f["message"])
         <input type="text" name="message" required>
-        >>> f['message'].errors
+        >>> f["message"].errors
         ['This field is required.']
-        >>> print(f['message'].errors)
+        >>> print(f["message"].errors)
         <ul class="errorlist"><li>This field is required.</li></ul>
-        >>> f['subject'].errors
+        >>> f["subject"].errors
         []
-        >>> print(f['subject'].errors)
+        >>> print(f["subject"].errors)
 
-        >>> str(f['subject'].errors)
+        >>> str(f["subject"].errors)
         ''
 
 .. attribute:: BoundField.field
@@ -1177,7 +1201,7 @@ Attributes of ``BoundField``
     :attr:`~django.forms.Widget.attrs` on the field's widget. For example,
     declaring a field like this::
 
-        my_field = forms.CharField(widget=forms.TextInput(attrs={'id': 'myFIELD'}))
+        my_field = forms.CharField(widget=forms.TextInput(attrs={"id": "myFIELD"}))
 
     and using the template above, would render something like:
 
@@ -1201,10 +1225,11 @@ Attributes of ``BoundField``
         >>> from datetime import datetime
         >>> class DatedCommentForm(CommentForm):
         ...     created = forms.DateTimeField(initial=datetime.now)
+        ...
         >>> f = DatedCommentForm()
-        >>> f['created'].initial
+        >>> f["created"].initial
         datetime.datetime(2021, 7, 27, 9, 5, 54)
-        >>> f['created'].initial
+        >>> f["created"].initial
         datetime.datetime(2021, 7, 27, 9, 5, 54)
 
     Using :attr:`BoundField.initial` is recommended over
@@ -1227,9 +1252,9 @@ Attributes of ``BoundField``
     .. code-block:: pycon
 
         >>> f = ContactForm()
-        >>> print(f['subject'].name)
+        >>> print(f["subject"].name)
         subject
-        >>> print(f['message'].name)
+        >>> print(f["message"].name)
         message
 
 .. attribute:: BoundField.use_fieldset
@@ -1282,8 +1307,8 @@ Methods of ``BoundField``
 
     .. code-block:: pycon
 
-        >>> f = ContactForm(data={'message': ''})
-        >>> f['message'].css_classes()
+        >>> f = ContactForm(data={"message": ""})
+        >>> f["message"].css_classes()
         'required'
 
     If you want to provide some additional classes in addition to the
@@ -1292,8 +1317,8 @@ Methods of ``BoundField``
 
     .. code-block:: pycon
 
-        >>> f = ContactForm(data={'message': ''})
-        >>> f['message'].css_classes('foo bar')
+        >>> f = ContactForm(data={"message": ""})
+        >>> f["message"].css_classes("foo bar")
         'foo bar required'
 
 .. method:: BoundField.label_tag(contents=None, attrs=None, label_suffix=None, tag=None)
@@ -1327,8 +1352,8 @@ Methods of ``BoundField``
 
     .. code-block:: pycon
 
-        >>> f = ContactForm(data={'message': ''})
-        >>> print(f['message'].label_tag())
+        >>> f = ContactForm(data={"message": ""})
+        >>> print(f["message"].label_tag())
         <label for="id_message">Message:</label>
 
     If you'd like to customize the rendering this can be achieved by overriding
@@ -1350,12 +1375,12 @@ Methods of ``BoundField``
 
     .. code-block:: pycon
 
-        >>> initial = {'subject': 'welcome'}
+        >>> initial = {"subject": "welcome"}
         >>> unbound_form = ContactForm(initial=initial)
-        >>> bound_form = ContactForm(data={'subject': 'hi'}, initial=initial)
-        >>> print(unbound_form['subject'].value())
+        >>> bound_form = ContactForm(data={"subject": "hi"}, initial=initial)
+        >>> print(unbound_form["subject"].value())
         welcome
-        >>> print(bound_form['subject'].value())
+        >>> print(bound_form["subject"].value())
         hi
 
 Customizing ``BoundField``
@@ -1391,6 +1416,7 @@ be implemented as follows::
             else:
                 return None
 
+
     class GPSCoordinatesField(Field):
         def get_bound_field(self, form, field_name):
             return GPSCoordinatesBoundField(form, self, field_name)
@@ -1425,11 +1451,13 @@ need to bind the file data containing the mugshot image:
 
     # Bound form with an image field
     >>> from django.core.files.uploadedfile import SimpleUploadedFile
-    >>> data = {'subject': 'hello',
-    ...         'message': 'Hi there',
-    ...         'sender': 'foo@example.com',
-    ...         'cc_myself': True}
-    >>> file_data = {'mugshot': SimpleUploadedFile('face.jpg', b"file data")}
+    >>> data = {
+    ...     "subject": "hello",
+    ...     "message": "Hi there",
+    ...     "sender": "foo@example.com",
+    ...     "cc_myself": True,
+    ... }
+    >>> file_data = {"mugshot": SimpleUploadedFile("face.jpg", b"file data")}
     >>> f = ContactFormWithMugshot(data, file_data)
 
 In practice, you will usually specify ``request.FILES`` as the source
@@ -1494,6 +1522,7 @@ fields are ordered first:
 
     >>> class ContactFormWithPriority(ContactForm):
     ...     priority = forms.CharField()
+    ...
     >>> f = ContactFormWithPriority(auto_id=False)
     >>> print(f)
     <div>Subject:<input type="text" name="subject" maxlength="100" required></div>
@@ -1513,10 +1542,13 @@ classes:
     >>> class PersonForm(forms.Form):
     ...     first_name = forms.CharField()
     ...     last_name = forms.CharField()
+    ...
     >>> class InstrumentForm(forms.Form):
     ...     instrument = forms.CharField()
+    ...
     >>> class BeatleForm(InstrumentForm, PersonForm):
     ...     haircut_type = forms.CharField()
+    ...
     >>> b = BeatleForm(auto_id=False)
     >>> print(b)
     <div>First name:<input type="text" name="first_name" required></div>
@@ -1534,9 +1566,11 @@ by setting the name of the field to ``None`` on the subclass. For example:
     >>> class ParentForm(forms.Form):
     ...     name = forms.CharField()
     ...     age = forms.IntegerField()
+    ...
 
     >>> class ChildForm(ParentForm):
     ...     name = None
+    ...
 
     >>> list(ChildForm().fields)
     ['age']
@@ -1568,4 +1602,5 @@ The prefix can also be specified on the form class:
 
     >>> class PersonForm(forms.Form):
     ...     ...
-    ...     prefix = 'person'
+    ...     prefix = "person"
+    ...

+ 61 - 41
docs/ref/forms/fields.txt

@@ -26,9 +26,9 @@ value:
 
     >>> from django import forms
     >>> f = forms.EmailField()
-    >>> f.clean('foo@example.com')
+    >>> f.clean("foo@example.com")
     'foo@example.com'
-    >>> f.clean('invalid email address')
+    >>> f.clean("invalid email address")
     Traceback (most recent call last):
     ...
     ValidationError: ['Enter a valid email address.']
@@ -55,9 +55,9 @@ an empty value -- either ``None`` or the empty string (``""``) -- then
 
     >>> from django import forms
     >>> f = forms.CharField()
-    >>> f.clean('foo')
+    >>> f.clean("foo")
     'foo'
-    >>> f.clean('')
+    >>> f.clean("")
     Traceback (most recent call last):
     ...
     ValidationError: ['This field is required.']
@@ -65,7 +65,7 @@ an empty value -- either ``None`` or the empty string (``""``) -- then
     Traceback (most recent call last):
     ...
     ValidationError: ['This field is required.']
-    >>> f.clean(' ')
+    >>> f.clean(" ")
     ' '
     >>> f.clean(0)
     '0'
@@ -80,9 +80,9 @@ To specify that a field is *not* required, pass ``required=False`` to the
 .. code-block:: pycon
 
     >>> f = forms.CharField(required=False)
-    >>> f.clean('foo')
+    >>> f.clean("foo")
     'foo'
-    >>> f.clean('')
+    >>> f.clean("")
     ''
     >>> f.clean(None)
     ''
@@ -124,9 +124,10 @@ We've specified ``auto_id=False`` to simplify the output:
 
     >>> from django import forms
     >>> class CommentForm(forms.Form):
-    ...     name = forms.CharField(label='Your name')
-    ...     url = forms.URLField(label='Your website', required=False)
+    ...     name = forms.CharField(label="Your name")
+    ...     url = forms.URLField(label="Your website", required=False)
     ...     comment = forms.CharField()
+    ...
     >>> f = CommentForm(auto_id=False)
     >>> print(f)
     <div>Your name:<input type="text" name="name" required></div>
@@ -146,8 +147,9 @@ The ``label_suffix`` argument lets you override the form's
     >>> class ContactForm(forms.Form):
     ...     age = forms.IntegerField()
     ...     nationality = forms.CharField()
-    ...     captcha_answer = forms.IntegerField(label='2 + 2', label_suffix=' =')
-    >>> f = ContactForm(label_suffix='?')
+    ...     captcha_answer = forms.IntegerField(label="2 + 2", label_suffix=" =")
+    ...
+    >>> f = ContactForm(label_suffix="?")
     >>> print(f)
     <div><label for="id_age">Age?</label><input type="number" name="age" required id="id_age"></div>
     <div><label for="id_nationality">Nationality?</label><input type="text" name="nationality" required id="id_nationality"></div>
@@ -170,9 +172,10 @@ field is initialized to a particular value. For example:
 
     >>> from django import forms
     >>> class CommentForm(forms.Form):
-    ...     name = forms.CharField(initial='Your name')
-    ...     url = forms.URLField(initial='http://')
+    ...     name = forms.CharField(initial="Your name")
+    ...     url = forms.URLField(initial="http://")
     ...     comment = forms.CharField()
+    ...
     >>> f = CommentForm(auto_id=False)
     >>> print(f)
     <div>Name:<input type="text" name="name" value="Your name" required></div>
@@ -189,7 +192,8 @@ and the HTML output will include any validation errors:
     ...     name = forms.CharField()
     ...     url = forms.URLField()
     ...     comment = forms.CharField()
-    >>> default_data = {'name': 'Your name', 'url': 'http://'}
+    ...
+    >>> default_data = {"name": "Your name", "url": "http://"}
     >>> f = CommentForm(default_data, auto_id=False)
     >>> print(f)
     <div>Name:<input type="text" name="name" value="Your name" required></div>
@@ -206,10 +210,11 @@ validation if a particular field's value is not given. ``initial`` values are
 .. code-block:: pycon
 
     >>> class CommentForm(forms.Form):
-    ...     name = forms.CharField(initial='Your name')
-    ...     url = forms.URLField(initial='http://')
+    ...     name = forms.CharField(initial="Your name")
+    ...     url = forms.URLField(initial="http://")
     ...     comment = forms.CharField()
-    >>> data = {'name': '', 'url': '', 'comment': 'Foo'}
+    ...
+    >>> data = {"name": "", "url": "", "comment": "Foo"}
     >>> f = CommentForm(data)
     >>> f.is_valid()
     False
@@ -224,6 +229,7 @@ Instead of a constant, you can also pass any callable:
     >>> import datetime
     >>> class DateForm(forms.Form):
     ...     day = forms.DateField(initial=datetime.date.today)
+    ...
     >>> print(DateForm())
     <div><label for="id_day">Day:</label><input type="text" name="day" value="2023-02-11" required id="id_day"></div>
 
@@ -257,10 +263,11 @@ fields. We've specified ``auto_id=False`` to simplify the output:
 
     >>> from django import forms
     >>> class HelpTextContactForm(forms.Form):
-    ...     subject = forms.CharField(max_length=100, help_text='100 characters max.')
+    ...     subject = forms.CharField(max_length=100, help_text="100 characters max.")
     ...     message = forms.CharField()
-    ...     sender = forms.EmailField(help_text='A valid email address, please.')
+    ...     sender = forms.EmailField(help_text="A valid email address, please.")
     ...     cc_myself = forms.BooleanField(required=False)
+    ...
     >>> f = HelpTextContactForm(auto_id=False)
     >>> print(f)
     <div>Subject:<div class="helptext">100 characters max.</div><input type="text" name="subject" maxlength="100" required></div>
@@ -281,7 +288,7 @@ want to override. For example, here is the default error message:
 
     >>> from django import forms
     >>> generic = forms.CharField()
-    >>> generic.clean('')
+    >>> generic.clean("")
     Traceback (most recent call last):
       ...
     ValidationError: ['This field is required.']
@@ -290,8 +297,8 @@ And here is a custom error message:
 
 .. code-block:: pycon
 
-    >>> name = forms.CharField(error_messages={'required': 'Please enter your name'})
-    >>> name.clean('')
+    >>> name = forms.CharField(error_messages={"required": "Please enter your name"})
+    >>> name.clean("")
     Traceback (most recent call last):
       ...
     ValidationError: ['Please enter your name']
@@ -746,12 +753,13 @@ For each field, we describe the default widget used if you don't specify
         >>> from django.core.files.uploadedfile import SimpleUploadedFile
         >>> class ImageForm(forms.Form):
         ...     img = forms.ImageField()
-        >>> file_data = {'img': SimpleUploadedFile('test.png', b"file data")}
+        ...
+        >>> file_data = {"img": SimpleUploadedFile("test.png", b"file data")}
         >>> form = ImageForm({}, file_data)
         # Pillow closes the underlying file descriptor.
         >>> form.is_valid()
         True
-        >>> image_field = form.cleaned_data['img']
+        >>> image_field = form.cleaned_data["img"]
         >>> image_field.image
         <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=191x287 at 0x7F5985045C18>
         >>> image_field.image.width
@@ -893,9 +901,9 @@ For each field, we describe the default widget used if you don't specify
         NullBooleanField(
             widget=Select(
                 choices=[
-                    ('', 'Unknown'),
-                    (True, 'Yes'),
-                    (False, 'No'),
+                    ("", "Unknown"),
+                    (True, "Yes"),
+                    (False, "No"),
                 ]
             )
         )
@@ -1141,32 +1149,35 @@ Slightly complex built-in ``Field`` classes
 
             from django.core.validators import RegexValidator
 
+
             class PhoneField(MultiValueField):
                 def __init__(self, **kwargs):
                     # Define one message for all fields.
                     error_messages = {
-                        'incomplete': 'Enter a country calling code and a phone number.',
+                        "incomplete": "Enter a country calling code and a phone number.",
                     }
                     # Or define a different message for each field.
                     fields = (
                         CharField(
-                            error_messages={'incomplete': 'Enter a country calling code.'},
+                            error_messages={"incomplete": "Enter a country calling code."},
                             validators=[
-                                RegexValidator(r'^[0-9]+$', 'Enter a valid country calling code.'),
+                                RegexValidator(r"^[0-9]+$", "Enter a valid country calling code."),
                             ],
                         ),
                         CharField(
-                            error_messages={'incomplete': 'Enter a phone number.'},
-                            validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid phone number.')],
+                            error_messages={"incomplete": "Enter a phone number."},
+                            validators=[RegexValidator(r"^[0-9]+$", "Enter a valid phone number.")],
                         ),
                         CharField(
-                            validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.')],
+                            validators=[RegexValidator(r"^[0-9]+$", "Enter a valid extension.")],
                             required=False,
                         ),
                     )
                     super().__init__(
-                        error_messages=error_messages, fields=fields,
-                        require_all_fields=False, **kwargs
+                        error_messages=error_messages,
+                        fields=fields,
+                        require_all_fields=False,
+                        **kwargs
                     )
 
     .. attribute:: MultiValueField.widget
@@ -1238,7 +1249,7 @@ method::
 
         def __init__(self, *args, **kwargs):
             super().__init__(*args, **kwargs)
-            self.fields['foo_select'].queryset = ...
+            self.fields["foo_select"].queryset = ...
 
 Both ``ModelChoiceField`` and ``ModelMultipleChoiceField`` have an ``iterator``
 attribute which specifies the class used to iterate over the queryset when
@@ -1351,6 +1362,7 @@ generating choices. See :ref:`iterating-relationship-choices` for details.
 
         from django.forms import ModelChoiceField
 
+
         class MyModelChoiceField(ModelChoiceField):
             def label_from_instance(self, obj):
                 return "My Object #%i" % obj.id
@@ -1416,6 +1428,7 @@ For example, consider the following models::
 
     from django.db import models
 
+
     class Topping(models.Model):
         name = models.CharField(max_length=100)
         price = models.DecimalField(decimal_places=2, max_digits=6)
@@ -1423,6 +1436,7 @@ For example, consider the following models::
         def __str__(self):
             return self.name
 
+
     class Pizza(models.Model):
         topping = models.ForeignKey(Topping, on_delete=models.CASCADE)
 
@@ -1432,18 +1446,24 @@ the value of ``Topping.price`` as the HTML attribute ``data-price`` for each
 
     from django import forms
 
+
     class ToppingSelect(forms.Select):
-        def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
-            option = super().create_option(name, value, label, selected, index, subindex, attrs)
+        def create_option(
+            self, name, value, label, selected, index, subindex=None, attrs=None
+        ):
+            option = super().create_option(
+                name, value, label, selected, index, subindex, attrs
+            )
             if value:
-                option['attrs']['data-price'] = value.instance.price
+                option["attrs"]["data-price"] = value.instance.price
             return option
 
+
     class PizzaForm(forms.ModelForm):
         class Meta:
             model = Pizza
-            fields = ['topping']
-            widgets = {'topping': ToppingSelect}
+            fields = ["topping"]
+            widgets = {"topping": ToppingSelect}
 
 This will render the ``Pizza.topping`` select as:
 

+ 2 - 1
docs/ref/forms/renderers.txt

@@ -137,7 +137,8 @@ Using this renderer along with the built-in templates requires either:
   of one of your template engines. To generate that path::
 
     import django
-    django.__path__[0] + '/forms/templates'  # or '/forms/jinja2'
+
+    django.__path__[0] + "/forms/templates"  # or '/forms/jinja2'
 
 Using this renderer requires you to make sure the form templates your project
 needs can be located.

+ 37 - 29
docs/ref/forms/validation.txt

@@ -120,22 +120,22 @@ following guidelines:
 * Provide a descriptive error ``code`` to the constructor::
 
       # Good
-      ValidationError(_('Invalid value'), code='invalid')
+      ValidationError(_("Invalid value"), code="invalid")
 
       # Bad
-      ValidationError(_('Invalid value'))
+      ValidationError(_("Invalid value"))
 
 * Don't coerce variables into the message; use placeholders and the ``params``
   argument of the constructor::
 
       # Good
       ValidationError(
-          _('Invalid value: %(value)s'),
-          params={'value': '42'},
+          _("Invalid value: %(value)s"),
+          params={"value": "42"},
       )
 
       # Bad
-      ValidationError(_('Invalid value: %s') % value)
+      ValidationError(_("Invalid value: %s") % value)
 
 * Use mapping keys instead of positional formatting. This enables putting
   the variables in any order or omitting them altogether when rewriting the
@@ -143,30 +143,30 @@ following guidelines:
 
       # Good
       ValidationError(
-          _('Invalid value: %(value)s'),
-          params={'value': '42'},
+          _("Invalid value: %(value)s"),
+          params={"value": "42"},
       )
 
       # Bad
       ValidationError(
-          _('Invalid value: %s'),
-          params=('42',),
+          _("Invalid value: %s"),
+          params=("42",),
       )
 
 * Wrap the message with ``gettext`` to enable translation::
 
       # Good
-      ValidationError(_('Invalid value'))
+      ValidationError(_("Invalid value"))
 
       # Bad
-      ValidationError('Invalid value')
+      ValidationError("Invalid value")
 
 Putting it all together::
 
     raise ValidationError(
-        _('Invalid value: %(value)s'),
-        code='invalid',
-        params={'value': '42'},
+        _("Invalid value: %(value)s"),
+        code="invalid",
+        params={"value": "42"},
     )
 
 Following these guidelines is particularly necessary if you write reusable
@@ -176,7 +176,7 @@ While not recommended, if you are at the end of the validation chain
 (i.e. your form ``clean()`` method) and you know you will *never* need
 to override your error message you can still opt for the less verbose::
 
-    ValidationError(_('Invalid value: %s') % value)
+    ValidationError(_("Invalid value: %s") % value)
 
 The :meth:`Form.errors.as_data() <django.forms.Form.errors.as_data()>` and
 :meth:`Form.errors.as_json() <django.forms.Form.errors.as_json()>` methods
@@ -194,16 +194,20 @@ As above, it is recommended to pass a list of ``ValidationError`` instances
 with ``code``\s and ``params`` but a list of strings will also work::
 
     # Good
-    raise ValidationError([
-        ValidationError(_('Error 1'), code='error1'),
-        ValidationError(_('Error 2'), code='error2'),
-    ])
+    raise ValidationError(
+        [
+            ValidationError(_("Error 1"), code="error1"),
+            ValidationError(_("Error 2"), code="error2"),
+        ]
+    )
 
     # Bad
-    raise ValidationError([
-        _('Error 1'),
-        _('Error 2'),
-    ])
+    raise ValidationError(
+        [
+            _("Error 1"),
+            _("Error 2"),
+        ]
+    )
 
 Using validation in practice
 ============================
@@ -232,6 +236,7 @@ at Django's ``SlugField``::
     from django.core import validators
     from django.forms import CharField
 
+
     class SlugField(CharField):
         default_validators = [validators.validate_slug]
 
@@ -262,13 +267,14 @@ containing comma-separated email addresses. The full class looks like this::
     from django import forms
     from django.core.validators import validate_email
 
+
     class MultiEmailField(forms.Field):
         def to_python(self, value):
             """Normalize data to a list of strings."""
             # Return an empty list if no input was given.
             if not value:
                 return []
-            return value.split(',')
+            return value.split(",")
 
         def validate(self, value):
             """Check if value consists only of valid emails."""
@@ -307,12 +313,13 @@ write a cleaning method that operates on the ``recipients`` field, like so::
     from django import forms
     from django.core.exceptions import ValidationError
 
+
     class ContactForm(forms.Form):
         # Everything as before.
         ...
 
         def clean_recipients(self):
-            data = self.cleaned_data['recipients']
+            data = self.cleaned_data["recipients"]
             if "fred@example.com" not in data:
                 raise ValidationError("You have forgotten about Fred!")
 
@@ -349,6 +356,7 @@ example::
     from django import forms
     from django.core.exceptions import ValidationError
 
+
     class ContactForm(forms.Form):
         # Everything as before.
         ...
@@ -362,8 +370,7 @@ example::
                 # Only do something if both fields are valid so far.
                 if "help" not in subject:
                     raise ValidationError(
-                        "Did not send for 'help' in the subject despite "
-                        "CC'ing yourself."
+                        "Did not send for 'help' in the subject despite " "CC'ing yourself."
                     )
 
 In this code, if the validation error is raised, the form will display an
@@ -392,6 +399,7 @@ work out what works effectively in your particular situation. Our new code
 
     from django import forms
 
+
     class ContactForm(forms.Form):
         # Everything as before.
         ...
@@ -403,8 +411,8 @@ work out what works effectively in your particular situation. Our new code
 
             if cc_myself and subject and "help" not in subject:
                 msg = "Must put 'help' in subject when cc'ing yourself."
-                self.add_error('cc_myself', msg)
-                self.add_error('subject', msg)
+                self.add_error("cc_myself", msg)
+                self.add_error("subject", msg)
 
 The second argument of ``add_error()`` can be a string, or preferably an
 instance of ``ValidationError``. See :ref:`raising-validation-error` for more

+ 43 - 28
docs/ref/forms/widgets.txt

@@ -38,6 +38,7 @@ use the :attr:`~Field.widget` argument on the field definition. For example::
 
     from django import forms
 
+
     class CommentForm(forms.Form):
         name = forms.CharField()
         url = forms.URLField()
@@ -56,15 +57,18 @@ widget on the field. In the following example, the
 
     from django import forms
 
-    BIRTH_YEAR_CHOICES = ['1980', '1981', '1982']
+    BIRTH_YEAR_CHOICES = ["1980", "1981", "1982"]
     FAVORITE_COLORS_CHOICES = [
-        ('blue', 'Blue'),
-        ('green', 'Green'),
-        ('black', 'Black'),
+        ("blue", "Blue"),
+        ("green", "Green"),
+        ("black", "Black"),
     ]
 
+
     class SimpleForm(forms.Form):
-        birth_year = forms.DateField(widget=forms.SelectDateWidget(years=BIRTH_YEAR_CHOICES))
+        birth_year = forms.DateField(
+            widget=forms.SelectDateWidget(years=BIRTH_YEAR_CHOICES)
+        )
         favorite_colors = forms.MultipleChoiceField(
             required=False,
             widget=forms.CheckboxSelectMultiple,
@@ -91,14 +95,14 @@ example:
 .. code-block:: pycon
 
     >>> from django import forms
-    >>> CHOICES = [('1', 'First'), ('2', 'Second')]
+    >>> CHOICES = [("1", "First"), ("2", "Second")]
     >>> choice_field = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES)
     >>> choice_field.choices
     [('1', 'First'), ('2', 'Second')]
     >>> choice_field.widget.choices
     [('1', 'First'), ('2', 'Second')]
     >>> choice_field.widget.choices = []
-    >>> choice_field.choices = [('1', 'First and only')]
+    >>> choice_field.choices = [("1", "First and only")]
     >>> choice_field.widget.choices
     [('1', 'First and only')]
 
@@ -132,6 +136,7 @@ For example, take the following form::
 
     from django import forms
 
+
     class CommentForm(forms.Form):
         name = forms.CharField()
         url = forms.URLField()
@@ -156,9 +161,9 @@ the 'type' attribute to take advantage of the new HTML5 input types.  To do
 this, you use the :attr:`Widget.attrs` argument when creating the widget::
 
     class CommentForm(forms.Form):
-        name = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))
+        name = forms.CharField(widget=forms.TextInput(attrs={"class": "special"}))
         url = forms.URLField()
-        comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))
+        comment = forms.CharField(widget=forms.TextInput(attrs={"size": "40"}))
 
 You can also modify a widget in the form definition::
 
@@ -167,8 +172,8 @@ You can also modify a widget in the form definition::
         url = forms.URLField()
         comment = forms.CharField()
 
-        name.widget.attrs.update({'class': 'special'})
-        comment.widget.attrs.update(size='40')
+        name.widget.attrs.update({"class": "special"})
+        comment.widget.attrs.update(size="40")
 
 Or if the field isn't declared directly on the form (such as model form fields),
 you can use the :attr:`Form.fields` attribute::
@@ -176,8 +181,8 @@ you can use the :attr:`Form.fields` attribute::
     class CommentForm(forms.ModelForm):
         def __init__(self, *args, **kwargs):
             super().__init__(*args, **kwargs)
-            self.fields['name'].widget.attrs.update({'class': 'special'})
-            self.fields['comment'].widget.attrs.update(size='40')
+            self.fields["name"].widget.attrs.update({"class": "special"})
+            self.fields["comment"].widget.attrs.update(size="40")
 
 Django will then include the extra attributes in the rendered output:
 
@@ -231,8 +236,8 @@ foundation for custom widgets.
         .. code-block:: pycon
 
             >>> from django import forms
-            >>> name = forms.TextInput(attrs={'size': 10, 'title': 'Your name'})
-            >>> name.render('name', 'A name')
+            >>> name = forms.TextInput(attrs={"size": 10, "title": "Your name"})
+            >>> name.render("name", "A name")
             '<input title="Your name" type="text" name="name" value="A name" size="10">'
 
         If you assign a value of ``True`` or ``False`` to an attribute,
@@ -240,12 +245,12 @@ foundation for custom widgets.
 
         .. code-block:: pycon
 
-            >>> name = forms.TextInput(attrs={'required': True})
-            >>> name.render('name', 'A name')
+            >>> name = forms.TextInput(attrs={"required": True})
+            >>> name.render("name", "A name")
             '<input name="name" type="text" value="A name" required>'
             >>>
-            >>> name = forms.TextInput(attrs={'required': False})
-            >>> name.render('name', 'A name')
+            >>> name = forms.TextInput(attrs={"required": False})
+            >>> name.render("name", "A name")
             '<input name="name" type="text" value="A name">'
 
     .. attribute:: Widget.supports_microseconds
@@ -373,7 +378,7 @@ foundation for custom widgets.
 
             >>> from django.forms import MultiWidget, TextInput
             >>> widget = MultiWidget(widgets=[TextInput, TextInput])
-            >>> widget.render('name', ['john', 'paul'])
+            >>> widget.render("name", ["john", "paul"])
             '<input type="text" name="name_0" value="john"><input type="text" name="name_1" value="paul">'
 
         You may provide a dictionary in order to specify custom suffixes for
@@ -385,8 +390,8 @@ foundation for custom widgets.
 
         .. code-block:: pycon
 
-            >>> widget = MultiWidget(widgets={'': TextInput, 'last': TextInput})
-            >>> widget.render('name', ['john', 'paul'])
+            >>> widget = MultiWidget(widgets={"": TextInput, "last": TextInput})
+            >>> widget.render("name", ["john", "paul"])
             '<input type="text" name="name" value="john"><input type="text" name="name_last" value="paul">'
 
     And one required method:
@@ -409,8 +414,8 @@ foundation for custom widgets.
 
             from django.forms import MultiWidget
 
-            class SplitDateTimeWidget(MultiWidget):
 
+            class SplitDateTimeWidget(MultiWidget):
                 # ...
 
                 def decompress(self, value):
@@ -450,6 +455,7 @@ foundation for custom widgets.
         from datetime import date
         from django import forms
 
+
         class DateSelectorWidget(forms.MultiWidget):
             def __init__(self, attrs=None):
                 days = [(day, day) for day in range(1, 32)]
@@ -466,14 +472,14 @@ foundation for custom widgets.
                 if isinstance(value, date):
                     return [value.day, value.month, value.year]
                 elif isinstance(value, str):
-                    year, month, day = value.split('-')
+                    year, month, day = value.split("-")
                     return [day, month, year]
                 return [None, None, None]
 
             def value_from_datadict(self, data, files, name):
                 day, month, year = super().value_from_datadict(data, files, name)
                 # DateField expects a single string that it can parse into a date.
-                return '{}-{}-{}'.format(year, month, day)
+                return "{}-{}-{}".format(year, month, day)
 
     The constructor creates several :class:`Select` widgets in a list. The
     ``super()`` method uses this list to set up the widget.
@@ -952,9 +958,18 @@ Composite widgets
         the values are the displayed months::
 
             MONTHS = {
-                1:_('jan'), 2:_('feb'), 3:_('mar'), 4:_('apr'),
-                5:_('may'), 6:_('jun'), 7:_('jul'), 8:_('aug'),
-                9:_('sep'), 10:_('oct'), 11:_('nov'), 12:_('dec')
+                1: _("jan"),
+                2: _("feb"),
+                3: _("mar"),
+                4: _("apr"),
+                5: _("may"),
+                6: _("jun"),
+                7: _("jul"),
+                8: _("aug"),
+                9: _("sep"),
+                10: _("oct"),
+                11: _("nov"),
+                12: _("dec"),
             }
 
     .. attribute:: SelectDateWidget.empty_label

+ 76 - 75
docs/ref/logging.txt

@@ -64,51 +64,51 @@ available as ``django.utils.log.DEFAULT_LOGGING`` and defined in
 :source:`django/utils/log.py`::
 
     {
-        'version': 1,
-        'disable_existing_loggers': False,
-        'filters': {
-            'require_debug_false': {
-                '()': 'django.utils.log.RequireDebugFalse',
+        "version": 1,
+        "disable_existing_loggers": False,
+        "filters": {
+            "require_debug_false": {
+                "()": "django.utils.log.RequireDebugFalse",
             },
-            'require_debug_true': {
-                '()': 'django.utils.log.RequireDebugTrue',
+            "require_debug_true": {
+                "()": "django.utils.log.RequireDebugTrue",
             },
         },
-        'formatters': {
-            'django.server': {
-                '()': 'django.utils.log.ServerFormatter',
-                'format': '[{server_time}] {message}',
-                'style': '{',
+        "formatters": {
+            "django.server": {
+                "()": "django.utils.log.ServerFormatter",
+                "format": "[{server_time}] {message}",
+                "style": "{",
             }
         },
-        'handlers': {
-            'console': {
-                'level': 'INFO',
-                'filters': ['require_debug_true'],
-                'class': 'logging.StreamHandler',
+        "handlers": {
+            "console": {
+                "level": "INFO",
+                "filters": ["require_debug_true"],
+                "class": "logging.StreamHandler",
             },
-            'django.server': {
-                'level': 'INFO',
-                'class': 'logging.StreamHandler',
-                'formatter': 'django.server',
+            "django.server": {
+                "level": "INFO",
+                "class": "logging.StreamHandler",
+                "formatter": "django.server",
+            },
+            "mail_admins": {
+                "level": "ERROR",
+                "filters": ["require_debug_false"],
+                "class": "django.utils.log.AdminEmailHandler",
             },
-            'mail_admins': {
-                'level': 'ERROR',
-                'filters': ['require_debug_false'],
-                'class': 'django.utils.log.AdminEmailHandler'
-            }
         },
-        'loggers': {
-            'django': {
-                'handlers': ['console', 'mail_admins'],
-                'level': 'INFO',
+        "loggers": {
+            "django": {
+                "handlers": ["console", "mail_admins"],
+                "level": "INFO",
             },
-            'django.server': {
-                'handlers': ['django.server'],
-                'level': 'INFO',
-                'propagate': False,
+            "django.server": {
+                "handlers": ["django.server"],
+                "level": "INFO",
+                "propagate": False,
             },
-        }
+        },
     }
 
 See :ref:`configuring-logging` on how to complement or replace this default
@@ -230,15 +230,15 @@ specific logger following this example::
 
     LOGGING = {
         # ...
-        'handlers': {
-            'null': {
-                'class': 'logging.NullHandler',
+        "handlers": {
+            "null": {
+                "class": "logging.NullHandler",
             },
         },
-        'loggers': {
-            'django.security.DisallowedHost': {
-                'handlers': ['null'],
-                'propagate': False,
+        "loggers": {
+            "django.security.DisallowedHost": {
+                "handlers": ["null"],
+                "propagate": False,
             },
         },
         # ...
@@ -284,11 +284,11 @@ Python logging module <python:logging.handlers>`.
     configuration, include it in the handler definition for
     ``django.utils.log.AdminEmailHandler``, like this::
 
-        'handlers': {
-            'mail_admins': {
-                'level': 'ERROR',
-                'class': 'django.utils.log.AdminEmailHandler',
-                'include_html': True,
+        "handlers": {
+            "mail_admins": {
+                "level": "ERROR",
+                "class": "django.utils.log.AdminEmailHandler",
+                "include_html": True,
             },
         }
 
@@ -299,11 +299,11 @@ Python logging module <python:logging.handlers>`.
     :ref:`email backend <topic-email-backends>` that is being used by the
     handler can be overridden, like this::
 
-        'handlers': {
-            'mail_admins': {
-                'level': 'ERROR',
-                'class': 'django.utils.log.AdminEmailHandler',
-                'email_backend': 'django.core.mail.backends.filebased.EmailBackend',
+        "handlers": {
+            "mail_admins": {
+                "level": "ERROR",
+                "class": "django.utils.log.AdminEmailHandler",
+                "email_backend": "django.core.mail.backends.filebased.EmailBackend",
             },
         }
 
@@ -315,12 +315,12 @@ Python logging module <python:logging.handlers>`.
     traceback text sent in the email body. You provide a string import path to
     the class you wish to use, like this::
 
-        'handlers': {
-            'mail_admins': {
-                'level': 'ERROR',
-                'class': 'django.utils.log.AdminEmailHandler',
-                'include_html': True,
-                'reporter_class': 'somepackage.error_reporter.CustomErrorReporter',
+        "handlers": {
+            "mail_admins": {
+                "level": "ERROR",
+                "class": "django.utils.log.AdminEmailHandler",
+                "include_html": True,
+                "reporter_class": "somepackage.error_reporter.CustomErrorReporter",
             },
         }
 
@@ -349,6 +349,7 @@ logging module.
 
         from django.http import UnreadablePostError
 
+
         def skip_unreadable_post(record):
             if record.exc_info:
                 exc_type, exc_value = record.exc_info[:2]
@@ -360,17 +361,17 @@ logging module.
 
         LOGGING = {
             # ...
-            'filters': {
-                'skip_unreadable_posts': {
-                    '()': 'django.utils.log.CallbackFilter',
-                    'callback': skip_unreadable_post,
+            "filters": {
+                "skip_unreadable_posts": {
+                    "()": "django.utils.log.CallbackFilter",
+                    "callback": skip_unreadable_post,
                 },
             },
-            'handlers': {
-                'mail_admins': {
-                    'level': 'ERROR',
-                    'filters': ['skip_unreadable_posts'],
-                    'class': 'django.utils.log.AdminEmailHandler',
+            "handlers": {
+                "mail_admins": {
+                    "level": "ERROR",
+                    "filters": ["skip_unreadable_posts"],
+                    "class": "django.utils.log.AdminEmailHandler",
                 },
             },
             # ...
@@ -386,16 +387,16 @@ logging module.
 
         LOGGING = {
             # ...
-            'filters': {
-                'require_debug_false': {
-                    '()': 'django.utils.log.RequireDebugFalse',
+            "filters": {
+                "require_debug_false": {
+                    "()": "django.utils.log.RequireDebugFalse",
                 },
             },
-            'handlers': {
-                'mail_admins': {
-                    'level': 'ERROR',
-                    'filters': ['require_debug_false'],
-                    'class': 'django.utils.log.AdminEmailHandler',
+            "handlers": {
+                "mail_admins": {
+                    "level": "ERROR",
+                    "filters": ["require_debug_false"],
+                    "class": "django.utils.log.AdminEmailHandler",
                 },
             },
             # ...

+ 1 - 0
docs/ref/middleware.txt

@@ -67,6 +67,7 @@ Adds a few conveniences for perfectionists:
 
     from django.views.decorators.common import no_append_slash
 
+
     @no_append_slash
     def sensitive_fbv(request, *args, **kwargs):
         """View to be excluded from APPEND_SLASH."""

+ 16 - 12
docs/ref/migration-operations.txt

@@ -297,7 +297,7 @@ queries and parameters in the same way as :ref:`cursor.execute()
 
     migrations.RunSQL("INSERT INTO musician (name) VALUES ('Reinhardt');")
     migrations.RunSQL([("INSERT INTO musician (name) VALUES ('Reinhardt');", None)])
-    migrations.RunSQL([("INSERT INTO musician (name) VALUES (%s);", ['Reinhardt'])])
+    migrations.RunSQL([("INSERT INTO musician (name) VALUES (%s);", ["Reinhardt"])])
 
 If you want to include literal percent signs in the query, you have to double
 them if you are passing parameters.
@@ -307,8 +307,8 @@ should undo what is done by the ``sql`` queries. For example, to undo the above
 insertion with a deletion::
 
     migrations.RunSQL(
-        sql=[("INSERT INTO musician (name) VALUES (%s);", ['Reinhardt'])],
-        reverse_sql=[("DELETE FROM musician where name=%s;", ['Reinhardt'])],
+        sql=[("INSERT INTO musician (name) VALUES (%s);", ["Reinhardt"])],
+        reverse_sql=[("DELETE FROM musician where name=%s;", ["Reinhardt"])],
     )
 
 If ``reverse_sql`` is ``None`` (the default), the ``RunSQL`` operation is
@@ -325,8 +325,8 @@ operation that adds that field and so will try to run it again. For example::
         "ALTER TABLE musician ADD COLUMN name varchar(255) NOT NULL;",
         state_operations=[
             migrations.AddField(
-                'musician',
-                'name',
+                "musician",
+                "name",
                 models.CharField(max_length=255),
             ),
         ],
@@ -377,15 +377,19 @@ using ``RunPython`` to create some initial objects on a ``Country`` model::
 
     from django.db import migrations
 
+
     def forwards_func(apps, schema_editor):
         # We get the model from the versioned app registry;
         # if we directly import it, it'll be the wrong version
         Country = apps.get_model("myapp", "Country")
         db_alias = schema_editor.connection.alias
-        Country.objects.using(db_alias).bulk_create([
-            Country(name="USA", code="us"),
-            Country(name="France", code="fr"),
-        ])
+        Country.objects.using(db_alias).bulk_create(
+            [
+                Country(name="USA", code="us"),
+                Country(name="France", code="fr"),
+            ]
+        )
+
 
     def reverse_func(apps, schema_editor):
         # forwards_func() creates two Country instances,
@@ -395,8 +399,8 @@ using ``RunPython`` to create some initial objects on a ``Country`` model::
         Country.objects.using(db_alias).filter(name="USA", code="us").delete()
         Country.objects.using(db_alias).filter(name="France", code="fr").delete()
 
-    class Migration(migrations.Migration):
 
+    class Migration(migrations.Migration):
         dependencies = []
 
         operations = [
@@ -484,8 +488,8 @@ structure of an ``Operation`` looks like this::
 
     from django.db.migrations.operations.base import Operation
 
-    class MyCustomOperation(Operation):
 
+    class MyCustomOperation(Operation):
         # If this is False, it means that this operation will be ignored by
         # sqlmigrate; if true, it will be run and the SQL collected for its output.
         reduces_to_sql = False
@@ -574,8 +578,8 @@ state changes, all it does is run one command::
 
     from django.db.migrations.operations.base import Operation
 
-    class LoadExtension(Operation):
 
+    class LoadExtension(Operation):
         reversible = True
 
         def __init__(self, name):

+ 1 - 0
docs/ref/models/class.txt

@@ -55,6 +55,7 @@ Attributes
 
         from django.db import models
 
+
         class Person(models.Model):
             # Add manager with another name
             people = models.Manager()

+ 64 - 56
docs/ref/models/conditional-expressions.txt

@@ -17,14 +17,15 @@ We'll be using the following model in the subsequent examples::
 
     from django.db import models
 
+
     class Client(models.Model):
-        REGULAR = 'R'
-        GOLD = 'G'
-        PLATINUM = 'P'
+        REGULAR = "R"
+        GOLD = "G"
+        PLATINUM = "P"
         ACCOUNT_TYPE_CHOICES = [
-            (REGULAR, 'Regular'),
-            (GOLD, 'Gold'),
-            (PLATINUM, 'Platinum'),
+            (REGULAR, "Regular"),
+            (GOLD, "Gold"),
+            (PLATINUM, "Platinum"),
         ]
         name = models.CharField(max_length=50)
         registered_on = models.DateField()
@@ -54,28 +55,33 @@ Some examples:
 
     >>> from django.db.models import F, Q, When
     >>> # String arguments refer to fields; the following two examples are equivalent:
-    >>> When(account_type=Client.GOLD, then='name')
-    >>> When(account_type=Client.GOLD, then=F('name'))
+    >>> When(account_type=Client.GOLD, then="name")
+    >>> When(account_type=Client.GOLD, then=F("name"))
     >>> # You can use field lookups in the condition
     >>> from datetime import date
-    >>> When(registered_on__gt=date(2014, 1, 1),
-    ...      registered_on__lt=date(2015, 1, 1),
-    ...      then='account_type')
+    >>> When(
+    ...     registered_on__gt=date(2014, 1, 1),
+    ...     registered_on__lt=date(2015, 1, 1),
+    ...     then="account_type",
+    ... )
     >>> # Complex conditions can be created using Q objects
-    >>> When(Q(name__startswith="John") | Q(name__startswith="Paul"),
-    ...      then='name')
+    >>> When(Q(name__startswith="John") | Q(name__startswith="Paul"), then="name")
     >>> # Condition can be created using boolean expressions.
     >>> from django.db.models import Exists, OuterRef
-    >>> non_unique_account_type = Client.objects.filter(
-    ...     account_type=OuterRef('account_type'),
-    ... ).exclude(pk=OuterRef('pk')).values('pk')
-    >>> When(Exists(non_unique_account_type), then=Value('non unique'))
+    >>> non_unique_account_type = (
+    ...     Client.objects.filter(
+    ...         account_type=OuterRef("account_type"),
+    ...     )
+    ...     .exclude(pk=OuterRef("pk"))
+    ...     .values("pk")
+    ... )
+    >>> When(Exists(non_unique_account_type), then=Value("non unique"))
     >>> # Condition can be created using lookup expressions.
     >>> from django.db.models.lookups import GreaterThan, LessThan
     >>> When(
-    ...     GreaterThan(F('registered_on'), date(2014, 1, 1)) &
-    ...     LessThan(F('registered_on'), date(2015, 1, 1)),
-    ...     then='account_type',
+    ...     GreaterThan(F("registered_on"), date(2014, 1, 1))
+    ...     & LessThan(F("registered_on"), date(2015, 1, 1)),
+    ...     then="account_type",
     ... )
 
 Keep in mind that each of these values can be an expression.
@@ -111,25 +117,28 @@ An example:
     >>> from datetime import date, timedelta
     >>> from django.db.models import Case, Value, When
     >>> Client.objects.create(
-    ...     name='Jane Doe',
+    ...     name="Jane Doe",
     ...     account_type=Client.REGULAR,
-    ...     registered_on=date.today() - timedelta(days=36))
+    ...     registered_on=date.today() - timedelta(days=36),
+    ... )
     >>> Client.objects.create(
-    ...     name='James Smith',
+    ...     name="James Smith",
     ...     account_type=Client.GOLD,
-    ...     registered_on=date.today() - timedelta(days=5))
+    ...     registered_on=date.today() - timedelta(days=5),
+    ... )
     >>> Client.objects.create(
-    ...     name='Jack Black',
+    ...     name="Jack Black",
     ...     account_type=Client.PLATINUM,
-    ...     registered_on=date.today() - timedelta(days=10 * 365))
+    ...     registered_on=date.today() - timedelta(days=10 * 365),
+    ... )
     >>> # Get the discount for each Client based on the account type
     >>> Client.objects.annotate(
     ...     discount=Case(
-    ...         When(account_type=Client.GOLD, then=Value('5%')),
-    ...         When(account_type=Client.PLATINUM, then=Value('10%')),
-    ...         default=Value('0%'),
+    ...         When(account_type=Client.GOLD, then=Value("5%")),
+    ...         When(account_type=Client.PLATINUM, then=Value("10%")),
+    ...         default=Value("0%"),
     ...     ),
-    ... ).values_list('name', 'discount')
+    ... ).values_list("name", "discount")
     <QuerySet [('Jane Doe', '0%'), ('James Smith', '5%'), ('Jack Black', '10%')]>
 
 ``Case()`` accepts any number of ``When()`` objects as individual arguments.
@@ -148,11 +157,11 @@ the ``Client`` has been with us, we could do so using lookups:
     >>> # Get the discount for each Client based on the registration date
     >>> Client.objects.annotate(
     ...     discount=Case(
-    ...         When(registered_on__lte=a_year_ago, then=Value('10%')),
-    ...         When(registered_on__lte=a_month_ago, then=Value('5%')),
-    ...         default=Value('0%'),
+    ...         When(registered_on__lte=a_year_ago, then=Value("10%")),
+    ...         When(registered_on__lte=a_month_ago, then=Value("5%")),
+    ...         default=Value("0%"),
     ...     )
-    ... ).values_list('name', 'discount')
+    ... ).values_list("name", "discount")
     <QuerySet [('Jane Doe', '5%'), ('James Smith', '0%'), ('Jack Black', '10%')]>
 
 .. note::
@@ -175,7 +184,7 @@ registered more than a year ago:
     ...         When(account_type=Client.GOLD, then=a_month_ago),
     ...         When(account_type=Client.PLATINUM, then=a_year_ago),
     ...     ),
-    ... ).values_list('name', 'account_type')
+    ... ).values_list("name", "account_type")
     <QuerySet [('Jack Black', 'P')]>
 
 Advanced queries
@@ -199,14 +208,12 @@ their registration dates. We can do this using a conditional expression and the
     >>> # Update the account_type for each Client from the registration date
     >>> Client.objects.update(
     ...     account_type=Case(
-    ...         When(registered_on__lte=a_year_ago,
-    ...              then=Value(Client.PLATINUM)),
-    ...         When(registered_on__lte=a_month_ago,
-    ...              then=Value(Client.GOLD)),
-    ...         default=Value(Client.REGULAR)
+    ...         When(registered_on__lte=a_year_ago, then=Value(Client.PLATINUM)),
+    ...         When(registered_on__lte=a_month_ago, then=Value(Client.GOLD)),
+    ...         default=Value(Client.REGULAR),
     ...     ),
     ... )
-    >>> Client.objects.values_list('name', 'account_type')
+    >>> Client.objects.values_list("name", "account_type")
     <QuerySet [('Jane Doe', 'G'), ('James Smith', 'R'), ('Jack Black', 'P')]>
 
 .. _conditional-aggregation:
@@ -222,23 +229,20 @@ functions <aggregation-functions>` to achieve this:
 
     >>> # Create some more Clients first so we can have something to count
     >>> Client.objects.create(
-    ...     name='Jean Grey',
-    ...     account_type=Client.REGULAR,
-    ...     registered_on=date.today())
+    ...     name="Jean Grey", account_type=Client.REGULAR, registered_on=date.today()
+    ... )
     >>> Client.objects.create(
-    ...     name='James Bond',
-    ...     account_type=Client.PLATINUM,
-    ...     registered_on=date.today())
+    ...     name="James Bond", account_type=Client.PLATINUM, registered_on=date.today()
+    ... )
     >>> Client.objects.create(
-    ...     name='Jane Porter',
-    ...     account_type=Client.PLATINUM,
-    ...     registered_on=date.today())
+    ...     name="Jane Porter", account_type=Client.PLATINUM, registered_on=date.today()
+    ... )
     >>> # Get counts for each value of account_type
     >>> from django.db.models import Count
     >>> Client.objects.aggregate(
-    ...     regular=Count('pk', filter=Q(account_type=Client.REGULAR)),
-    ...     gold=Count('pk', filter=Q(account_type=Client.GOLD)),
-    ...     platinum=Count('pk', filter=Q(account_type=Client.PLATINUM)),
+    ...     regular=Count("pk", filter=Q(account_type=Client.REGULAR)),
+    ...     gold=Count("pk", filter=Q(account_type=Client.GOLD)),
+    ...     platinum=Count("pk", filter=Q(account_type=Client.PLATINUM)),
     ... )
     {'regular': 2, 'gold': 1, 'platinum': 3}
 
@@ -273,9 +277,13 @@ columns, but you can still use it to filter results:
 
 .. code-block:: pycon
 
-    >>> non_unique_account_type = Client.objects.filter(
-    ...     account_type=OuterRef('account_type'),
-    ... ).exclude(pk=OuterRef('pk')).values('pk')
+    >>> non_unique_account_type = (
+    ...     Client.objects.filter(
+    ...         account_type=OuterRef("account_type"),
+    ...     )
+    ...     .exclude(pk=OuterRef("pk"))
+    ...     .values("pk")
+    ... )
     >>> Client.objects.filter(~Exists(non_unique_account_type))
 
 In SQL terms, that evaluates to:

+ 9 - 7
docs/ref/models/constraints.txt

@@ -126,7 +126,7 @@ ensures the age field is never less than 18.
     to behave the same as check constraints validation. For example, if ``age``
     is a nullable field::
 
-        CheckConstraint(check=Q(age__gte=18) | Q(age__isnull=True), name='age_gte_18')
+        CheckConstraint(check=Q(age__gte=18) | Q(age__isnull=True), name="age_gte_18")
 
 ``UniqueConstraint``
 ====================
@@ -145,7 +145,7 @@ constraints on expressions and database functions.
 
 For example::
 
-    UniqueConstraint(Lower('name').desc(), 'category', name='unique_lower_name_category')
+    UniqueConstraint(Lower("name").desc(), "category", name="unique_lower_name_category")
 
 creates a unique constraint on the lowercased value of the ``name`` field in
 descending order and the ``category`` field in the default ascending order.
@@ -175,7 +175,7 @@ enforce.
 
 For example::
 
-    UniqueConstraint(fields=['user'], condition=Q(status='DRAFT'), name='unique_draft_user')
+    UniqueConstraint(fields=["user"], condition=Q(status="DRAFT"), name="unique_draft_user")
 
 ensures that each user only has one draft.
 
@@ -193,8 +193,8 @@ are ``Deferrable.DEFERRED`` or ``Deferrable.IMMEDIATE``. For example::
     from django.db.models import Deferrable, UniqueConstraint
 
     UniqueConstraint(
-        name='unique_order',
-        fields=['order'],
+        name="unique_order",
+        fields=["order"],
         deferrable=Deferrable.DEFERRED,
     )
 
@@ -224,7 +224,7 @@ and filter only by unique fields (:attr:`~UniqueConstraint.fields`).
 
 For example::
 
-    UniqueConstraint(name='unique_booking', fields=['room', 'date'], include=['full_name'])
+    UniqueConstraint(name="unique_booking", fields=["room", "date"], include=["full_name"])
 
 will allow filtering on ``room`` and ``date``, also selecting ``full_name``,
 while fetching data only from the index.
@@ -246,7 +246,9 @@ for each field in the index.
 
 For example::
 
-    UniqueConstraint(name='unique_username', fields=['username'], opclasses=['varchar_pattern_ops'])
+    UniqueConstraint(
+        name="unique_username", fields=["username"], opclasses=["varchar_pattern_ops"]
+    )
 
 creates a unique index on ``username`` using ``varchar_pattern_ops``.
 

+ 237 - 179
docs/ref/models/database-functions.txt

@@ -41,9 +41,9 @@ Usage example:
 
     >>> from django.db.models import FloatField
     >>> from django.db.models.functions import Cast
-    >>> Author.objects.create(age=25, name='Margaret Smith')
+    >>> Author.objects.create(age=25, name="Margaret Smith")
     >>> author = Author.objects.annotate(
-    ...    age_as_float=Cast('age', output_field=FloatField()),
+    ...     age_as_float=Cast("age", output_field=FloatField()),
     ... ).get()
     >>> print(author.age_as_float)
     25.0
@@ -65,24 +65,23 @@ Usage examples:
     >>> # Get a screen name from least to most public
     >>> from django.db.models import Sum
     >>> from django.db.models.functions import Coalesce
-    >>> Author.objects.create(name='Margaret Smith', goes_by='Maggie')
-    >>> author = Author.objects.annotate(
-    ...    screen_name=Coalesce('alias', 'goes_by', 'name')).get()
+    >>> Author.objects.create(name="Margaret Smith", goes_by="Maggie")
+    >>> author = Author.objects.annotate(screen_name=Coalesce("alias", "goes_by", "name")).get()
     >>> print(author.screen_name)
     Maggie
 
     >>> # Prevent an aggregate Sum() from returning None
     >>> # The aggregate default argument uses Coalesce() under the hood.
     >>> aggregated = Author.objects.aggregate(
-    ...    combined_age=Sum('age'),
-    ...    combined_age_default=Sum('age', default=0),
-    ...    combined_age_coalesce=Coalesce(Sum('age'), 0),
+    ...     combined_age=Sum("age"),
+    ...     combined_age_default=Sum("age", default=0),
+    ...     combined_age_coalesce=Coalesce(Sum("age"), 0),
     ... )
-    >>> print(aggregated['combined_age'])
+    >>> print(aggregated["combined_age"])
     None
-    >>> print(aggregated['combined_age_default'])
+    >>> print(aggregated["combined_age_default"])
     0
-    >>> print(aggregated['combined_age_coalesce'])
+    >>> print(aggregated["combined_age_coalesce"])
     0
 
 .. warning::
@@ -107,14 +106,14 @@ For example, to filter case-insensitively in SQLite:
 
 .. code-block:: pycon
 
-    >>> Author.objects.filter(name=Collate(Value('john'), 'nocase'))
+    >>> Author.objects.filter(name=Collate(Value("john"), "nocase"))
     <QuerySet [<Author: John>, <Author: john>]>
 
 It can also be used when ordering, for example with PostgreSQL:
 
 .. code-block:: pycon
 
-    >>> Author.objects.order_by(Collate('name', 'et-x-icu'))
+    >>> Author.objects.order_by(Collate("name", "et-x-icu"))
     <QuerySet [<Author: Ursula>, <Author: Veronika>, <Author: Ülle>]>
 
 ``Greatest``
@@ -132,6 +131,7 @@ Usage example::
         body = models.TextField()
         modified = models.DateTimeField(auto_now=True)
 
+
     class Comment(models.Model):
         body = models.TextField()
         modified = models.DateTimeField(auto_now=True)
@@ -140,9 +140,9 @@ Usage example::
 .. code-block:: pycon
 
     >>> from django.db.models.functions import Greatest
-    >>> blog = Blog.objects.create(body='Greatest is the best.')
-    >>> comment = Comment.objects.create(body='No, Least is better.', blog=blog)
-    >>> comments = Comment.objects.annotate(last_updated=Greatest('modified', 'blog__modified'))
+    >>> blog = Blog.objects.create(body="Greatest is the best.")
+    >>> comment = Comment.objects.create(body="No, Least is better.", blog=blog)
+    >>> comments = Comment.objects.annotate(last_updated=Greatest("modified", "blog__modified"))
     >>> annotated_comment = comments.get()
 
 ``annotated_comment.last_updated`` will be the most recent of ``blog.modified``
@@ -175,12 +175,14 @@ Usage example:
 
     >>> from django.db.models import F
     >>> from django.db.models.functions import JSONObject, Lower
-    >>> Author.objects.create(name='Margaret Smith', alias='msmith', age=25)
-    >>> author = Author.objects.annotate(json_object=JSONObject(
-    ...     name=Lower('name'),
-    ...     alias='alias',
-    ...     age=F('age') * 2,
-    ... )).get()
+    >>> Author.objects.create(name="Margaret Smith", alias="msmith", age=25)
+    >>> author = Author.objects.annotate(
+    ...     json_object=JSONObject(
+    ...         name=Lower("name"),
+    ...         alias="alias",
+    ...         age=F("age") * 2,
+    ...     )
+    ... ).get()
     >>> author.json_object
     {'name': 'margaret smith', 'alias': 'msmith', 'age': 50}
 
@@ -315,16 +317,16 @@ Usage example:
     >>> start = datetime(2015, 6, 15)
     >>> end = datetime(2015, 7, 2)
     >>> Experiment.objects.create(
-    ...    start_datetime=start, start_date=start.date(),
-    ...    end_datetime=end, end_date=end.date())
+    ...     start_datetime=start, start_date=start.date(), end_datetime=end, end_date=end.date()
+    ... )
     >>> # Add the experiment start year as a field in the QuerySet.
     >>> experiment = Experiment.objects.annotate(
-    ...    start_year=Extract('start_datetime', 'year')).get()
+    ...     start_year=Extract("start_datetime", "year")
+    ... ).get()
     >>> experiment.start_year
     2015
     >>> # How many experiments completed in the same year in which they started?
-    >>> Experiment.objects.filter(
-    ...    start_datetime__year=Extract('end_datetime', 'year')).count()
+    >>> Experiment.objects.filter(start_datetime__year=Extract("end_datetime", "year")).count()
     1
 
 ``DateField`` extracts
@@ -378,27 +380,44 @@ that deal with date-parts can be used with ``DateField``:
 
     >>> from datetime import datetime, timezone
     >>> from django.db.models.functions import (
-    ...     ExtractDay, ExtractMonth, ExtractQuarter, ExtractWeek,
-    ...     ExtractIsoWeekDay, ExtractWeekDay, ExtractIsoYear, ExtractYear,
+    ...     ExtractDay,
+    ...     ExtractMonth,
+    ...     ExtractQuarter,
+    ...     ExtractWeek,
+    ...     ExtractIsoWeekDay,
+    ...     ExtractWeekDay,
+    ...     ExtractIsoYear,
+    ...     ExtractYear,
     ... )
     >>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=timezone.utc)
     >>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=timezone.utc)
     >>> Experiment.objects.create(
-    ...    start_datetime=start_2015, start_date=start_2015.date(),
-    ...    end_datetime=end_2015, end_date=end_2015.date())
+    ...     start_datetime=start_2015,
+    ...     start_date=start_2015.date(),
+    ...     end_datetime=end_2015,
+    ...     end_date=end_2015.date(),
+    ... )
     >>> Experiment.objects.annotate(
-    ...     year=ExtractYear('start_date'),
-    ...     isoyear=ExtractIsoYear('start_date'),
-    ...     quarter=ExtractQuarter('start_date'),
-    ...     month=ExtractMonth('start_date'),
-    ...     week=ExtractWeek('start_date'),
-    ...     day=ExtractDay('start_date'),
-    ...     weekday=ExtractWeekDay('start_date'),
-    ...     isoweekday=ExtractIsoWeekDay('start_date'),
+    ...     year=ExtractYear("start_date"),
+    ...     isoyear=ExtractIsoYear("start_date"),
+    ...     quarter=ExtractQuarter("start_date"),
+    ...     month=ExtractMonth("start_date"),
+    ...     week=ExtractWeek("start_date"),
+    ...     day=ExtractDay("start_date"),
+    ...     weekday=ExtractWeekDay("start_date"),
+    ...     isoweekday=ExtractIsoWeekDay("start_date"),
     ... ).values(
-    ...     'year', 'isoyear', 'quarter', 'month', 'week', 'day', 'weekday',
-    ...     'isoweekday',
-    ... ).get(end_date__year=ExtractYear('start_date'))
+    ...     "year",
+    ...     "isoyear",
+    ...     "quarter",
+    ...     "month",
+    ...     "week",
+    ...     "day",
+    ...     "weekday",
+    ...     "isoweekday",
+    ... ).get(
+    ...     end_date__year=ExtractYear("start_date")
+    ... )
     {'year': 2015, 'isoyear': 2015, 'quarter': 2, 'month': 6, 'week': 25,
      'day': 15, 'weekday': 2, 'isoweekday': 1}
 
@@ -430,31 +449,52 @@ Each class is also a ``Transform`` registered on ``DateTimeField`` as
 
     >>> from datetime import datetime, timezone
     >>> from django.db.models.functions import (
-    ...     ExtractDay, ExtractHour, ExtractMinute, ExtractMonth,
-    ...     ExtractQuarter, ExtractSecond, ExtractWeek, ExtractIsoWeekDay,
-    ...     ExtractWeekDay, ExtractIsoYear, ExtractYear,
+    ...     ExtractDay,
+    ...     ExtractHour,
+    ...     ExtractMinute,
+    ...     ExtractMonth,
+    ...     ExtractQuarter,
+    ...     ExtractSecond,
+    ...     ExtractWeek,
+    ...     ExtractIsoWeekDay,
+    ...     ExtractWeekDay,
+    ...     ExtractIsoYear,
+    ...     ExtractYear,
     ... )
     >>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=timezone.utc)
     >>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=timezone.utc)
     >>> Experiment.objects.create(
-    ...    start_datetime=start_2015, start_date=start_2015.date(),
-    ...    end_datetime=end_2015, end_date=end_2015.date())
+    ...     start_datetime=start_2015,
+    ...     start_date=start_2015.date(),
+    ...     end_datetime=end_2015,
+    ...     end_date=end_2015.date(),
+    ... )
     >>> Experiment.objects.annotate(
-    ...     year=ExtractYear('start_datetime'),
-    ...     isoyear=ExtractIsoYear('start_datetime'),
-    ...     quarter=ExtractQuarter('start_datetime'),
-    ...     month=ExtractMonth('start_datetime'),
-    ...     week=ExtractWeek('start_datetime'),
-    ...     day=ExtractDay('start_datetime'),
-    ...     weekday=ExtractWeekDay('start_datetime'),
-    ...     isoweekday=ExtractIsoWeekDay('start_datetime'),
-    ...     hour=ExtractHour('start_datetime'),
-    ...     minute=ExtractMinute('start_datetime'),
-    ...     second=ExtractSecond('start_datetime'),
+    ...     year=ExtractYear("start_datetime"),
+    ...     isoyear=ExtractIsoYear("start_datetime"),
+    ...     quarter=ExtractQuarter("start_datetime"),
+    ...     month=ExtractMonth("start_datetime"),
+    ...     week=ExtractWeek("start_datetime"),
+    ...     day=ExtractDay("start_datetime"),
+    ...     weekday=ExtractWeekDay("start_datetime"),
+    ...     isoweekday=ExtractIsoWeekDay("start_datetime"),
+    ...     hour=ExtractHour("start_datetime"),
+    ...     minute=ExtractMinute("start_datetime"),
+    ...     second=ExtractSecond("start_datetime"),
     ... ).values(
-    ...     'year', 'isoyear', 'month', 'week', 'day',
-    ...     'weekday', 'isoweekday', 'hour', 'minute', 'second',
-    ... ).get(end_datetime__year=ExtractYear('start_datetime'))
+    ...     "year",
+    ...     "isoyear",
+    ...     "month",
+    ...     "week",
+    ...     "day",
+    ...     "weekday",
+    ...     "isoweekday",
+    ...     "hour",
+    ...     "minute",
+    ...     "second",
+    ... ).get(
+    ...     end_datetime__year=ExtractYear("start_datetime")
+    ... )
     {'year': 2015, 'isoyear': 2015, 'quarter': 2, 'month': 6, 'week': 25,
      'day': 15, 'weekday': 2, 'isoweekday': 1, 'hour': 23, 'minute': 30,
      'second': 1}
@@ -469,16 +509,17 @@ values that are returned:
 
     >>> from django.utils import timezone
     >>> import zoneinfo
-    >>> melb = zoneinfo.ZoneInfo('Australia/Melbourne')  # UTC+10:00
+    >>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")  # UTC+10:00
     >>> with timezone.override(melb):
-    ...    Experiment.objects.annotate(
-    ...        day=ExtractDay('start_datetime'),
-    ...        weekday=ExtractWeekDay('start_datetime'),
-    ...        isoweekday=ExtractIsoWeekDay('start_datetime'),
-    ...        hour=ExtractHour('start_datetime'),
-    ...    ).values('day', 'weekday', 'isoweekday', 'hour').get(
-    ...        end_datetime__year=ExtractYear('start_datetime'),
-    ...    )
+    ...     Experiment.objects.annotate(
+    ...         day=ExtractDay("start_datetime"),
+    ...         weekday=ExtractWeekDay("start_datetime"),
+    ...         isoweekday=ExtractIsoWeekDay("start_datetime"),
+    ...         hour=ExtractHour("start_datetime"),
+    ...     ).values("day", "weekday", "isoweekday", "hour").get(
+    ...         end_datetime__year=ExtractYear("start_datetime"),
+    ...     )
+    ...
     {'day': 16, 'weekday': 3, 'isoweekday': 2, 'hour': 9}
 
 Explicitly passing the timezone to the ``Extract`` function behaves in the same
@@ -487,14 +528,14 @@ way, and takes priority over an active timezone:
 .. code-block:: pycon
 
     >>> import zoneinfo
-    >>> melb = zoneinfo.ZoneInfo('Australia/Melbourne')
+    >>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
     >>> Experiment.objects.annotate(
-    ...     day=ExtractDay('start_datetime', tzinfo=melb),
-    ...     weekday=ExtractWeekDay('start_datetime', tzinfo=melb),
-    ...     isoweekday=ExtractIsoWeekDay('start_datetime', tzinfo=melb),
-    ...     hour=ExtractHour('start_datetime', tzinfo=melb),
-    ... ).values('day', 'weekday', 'isoweekday', 'hour').get(
-    ...     end_datetime__year=ExtractYear('start_datetime'),
+    ...     day=ExtractDay("start_datetime", tzinfo=melb),
+    ...     weekday=ExtractWeekDay("start_datetime", tzinfo=melb),
+    ...     isoweekday=ExtractIsoWeekDay("start_datetime", tzinfo=melb),
+    ...     hour=ExtractHour("start_datetime", tzinfo=melb),
+    ... ).values("day", "weekday", "isoweekday", "hour").get(
+    ...     end_datetime__year=ExtractYear("start_datetime"),
     ... )
     {'day': 16, 'weekday': 3, 'isoweekday': 2, 'hour': 9}
 
@@ -594,16 +635,20 @@ Usage example:
     >>> Experiment.objects.create(start_datetime=datetime(2015, 6, 15, 14, 30, 50, 321))
     >>> Experiment.objects.create(start_datetime=datetime(2015, 6, 15, 14, 40, 2, 123))
     >>> Experiment.objects.create(start_datetime=datetime(2015, 12, 25, 10, 5, 27, 999))
-    >>> experiments_per_day = Experiment.objects.annotate(
-    ...    start_day=Trunc('start_datetime', 'day', output_field=DateTimeField())
-    ... ).values('start_day').annotate(experiments=Count('id'))
+    >>> experiments_per_day = (
+    ...     Experiment.objects.annotate(
+    ...         start_day=Trunc("start_datetime", "day", output_field=DateTimeField())
+    ...     )
+    ...     .values("start_day")
+    ...     .annotate(experiments=Count("id"))
+    ... )
     >>> for exp in experiments_per_day:
-    ...     print(exp['start_day'], exp['experiments'])
+    ...     print(exp["start_day"], exp["experiments"])
     ...
     2015-06-15 00:00:00 2
     2015-12-25 00:00:00 1
     >>> experiments = Experiment.objects.annotate(
-    ...    start_day=Trunc('start_datetime', 'day', output_field=DateTimeField())
+    ...     start_day=Trunc("start_datetime", "day", output_field=DateTimeField())
     ... ).filter(start_day=datetime(2015, 6, 15))
     >>> for exp in experiments:
     ...     print(exp.start_datetime)
@@ -651,22 +696,26 @@ that deal with date-parts can be used with ``DateField``:
     >>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
     >>> Experiment.objects.create(start_datetime=start2, start_date=start2.date())
     >>> Experiment.objects.create(start_datetime=start3, start_date=start3.date())
-    >>> experiments_per_year = Experiment.objects.annotate(
-    ...    year=TruncYear('start_date')).values('year').annotate(
-    ...    experiments=Count('id'))
+    >>> experiments_per_year = (
+    ...     Experiment.objects.annotate(year=TruncYear("start_date"))
+    ...     .values("year")
+    ...     .annotate(experiments=Count("id"))
+    ... )
     >>> for exp in experiments_per_year:
-    ...     print(exp['year'], exp['experiments'])
+    ...     print(exp["year"], exp["experiments"])
     ...
     2014-01-01 1
     2015-01-01 2
 
     >>> import zoneinfo
-    >>> melb = zoneinfo.ZoneInfo('Australia/Melbourne')
-    >>> experiments_per_month = Experiment.objects.annotate(
-    ...    month=TruncMonth('start_datetime', tzinfo=melb)).values('month').annotate(
-    ...    experiments=Count('id'))
+    >>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
+    >>> experiments_per_month = (
+    ...     Experiment.objects.annotate(month=TruncMonth("start_datetime", tzinfo=melb))
+    ...     .values("month")
+    ...     .annotate(experiments=Count("id"))
+    ... )
     >>> for exp in experiments_per_month:
-    ...     print(exp['month'], exp['experiments'])
+    ...     print(exp["month"], exp["experiments"])
     ...
     2015-06-01 00:00:00+10:00 1
     2016-01-01 00:00:00+11:00 1
@@ -721,19 +770,23 @@ Usage example:
     >>> from datetime import date, datetime, timezone
     >>> from django.db.models import Count
     >>> from django.db.models.functions import (
-    ...     TruncDate, TruncDay, TruncHour, TruncMinute, TruncSecond,
+    ...     TruncDate,
+    ...     TruncDay,
+    ...     TruncHour,
+    ...     TruncMinute,
+    ...     TruncSecond,
     ... )
     >>> import zoneinfo
     >>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
     >>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
-    >>> melb = zoneinfo.ZoneInfo('Australia/Melbourne')
+    >>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
     >>> Experiment.objects.annotate(
-    ...     date=TruncDate('start_datetime'),
-    ...     day=TruncDay('start_datetime', tzinfo=melb),
-    ...     hour=TruncHour('start_datetime', tzinfo=melb),
-    ...     minute=TruncMinute('start_datetime'),
-    ...     second=TruncSecond('start_datetime'),
-    ... ).values('date', 'day', 'hour', 'minute', 'second').get()
+    ...     date=TruncDate("start_datetime"),
+    ...     day=TruncDay("start_datetime", tzinfo=melb),
+    ...     hour=TruncHour("start_datetime", tzinfo=melb),
+    ...     minute=TruncMinute("start_datetime"),
+    ...     second=TruncSecond("start_datetime"),
+    ... ).values("date", "day", "hour", "minute", "second").get()
     {'date': datetime.date(2014, 6, 15),
      'day': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=zoneinfo.ZoneInfo('Australia/Melbourne')),
      'hour': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=zoneinfo.ZoneInfo('Australia/Melbourne')),
@@ -778,22 +831,30 @@ that deal with time-parts can be used with ``TimeField``:
     >>> Experiment.objects.create(start_datetime=start1, start_time=start1.time())
     >>> Experiment.objects.create(start_datetime=start2, start_time=start2.time())
     >>> Experiment.objects.create(start_datetime=start3, start_time=start3.time())
-    >>> experiments_per_hour = Experiment.objects.annotate(
-    ...    hour=TruncHour('start_datetime', output_field=TimeField()),
-    ... ).values('hour').annotate(experiments=Count('id'))
+    >>> experiments_per_hour = (
+    ...     Experiment.objects.annotate(
+    ...         hour=TruncHour("start_datetime", output_field=TimeField()),
+    ...     )
+    ...     .values("hour")
+    ...     .annotate(experiments=Count("id"))
+    ... )
     >>> for exp in experiments_per_hour:
-    ...     print(exp['hour'], exp['experiments'])
+    ...     print(exp["hour"], exp["experiments"])
     ...
     14:00:00 2
     17:00:00 1
 
     >>> import zoneinfo
-    >>> melb = zoneinfo.ZoneInfo('Australia/Melbourne')
-    >>> experiments_per_hour = Experiment.objects.annotate(
-    ...    hour=TruncHour('start_datetime', tzinfo=melb),
-    ... ).values('hour').annotate(experiments=Count('id'))
+    >>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
+    >>> experiments_per_hour = (
+    ...     Experiment.objects.annotate(
+    ...         hour=TruncHour("start_datetime", tzinfo=melb),
+    ...     )
+    ...     .values("hour")
+    ...     .annotate(experiments=Count("id"))
+    ... )
     >>> for exp in experiments_per_hour:
-    ...     print(exp['hour'], exp['experiments'])
+    ...     print(exp["hour"], exp["experiments"])
     ...
     2014-06-16 00:00:00+10:00 2
     2016-01-01 04:00:00+11:00 1
@@ -822,7 +883,7 @@ Usage example:
 
     >>> from django.db.models.functions import Abs
     >>> Vector.objects.create(x=-0.5, y=1.1)
-    >>> vector = Vector.objects.annotate(x_abs=Abs('x'), y_abs=Abs('y')).get()
+    >>> vector = Vector.objects.annotate(x_abs=Abs("x"), y_abs=Abs("y")).get()
     >>> vector.x_abs, vector.y_abs
     (0.5, 1.1)
 
@@ -850,7 +911,7 @@ Usage example:
 
     >>> from django.db.models.functions import ACos
     >>> Vector.objects.create(x=0.5, y=-0.9)
-    >>> vector = Vector.objects.annotate(x_acos=ACos('x'), y_acos=ACos('y')).get()
+    >>> vector = Vector.objects.annotate(x_acos=ACos("x"), y_acos=ACos("y")).get()
     >>> vector.x_acos, vector.y_acos
     (1.0471975511965979, 2.6905658417935308)
 
@@ -878,7 +939,7 @@ Usage example:
 
     >>> from django.db.models.functions import ASin
     >>> Vector.objects.create(x=0, y=1)
-    >>> vector = Vector.objects.annotate(x_asin=ASin('x'), y_asin=ASin('y')).get()
+    >>> vector = Vector.objects.annotate(x_asin=ASin("x"), y_asin=ASin("y")).get()
     >>> vector.x_asin, vector.y_asin
     (0.0, 1.5707963267948966)
 
@@ -905,7 +966,7 @@ Usage example:
 
     >>> from django.db.models.functions import ATan
     >>> Vector.objects.create(x=3.12, y=6.987)
-    >>> vector = Vector.objects.annotate(x_atan=ATan('x'), y_atan=ATan('y')).get()
+    >>> vector = Vector.objects.annotate(x_atan=ATan("x"), y_atan=ATan("y")).get()
     >>> vector.x_atan, vector.y_atan
     (1.2606282660069106, 1.428638798133829)
 
@@ -932,7 +993,7 @@ Usage example:
 
     >>> from django.db.models.functions import ATan2
     >>> Vector.objects.create(x=2.5, y=1.9)
-    >>> vector = Vector.objects.annotate(atan2=ATan2('x', 'y')).get()
+    >>> vector = Vector.objects.annotate(atan2=ATan2("x", "y")).get()
     >>> vector.atan2
     0.9209258773829491
 
@@ -950,7 +1011,7 @@ Usage example:
 
     >>> from django.db.models.functions import Ceil
     >>> Vector.objects.create(x=3.12, y=7.0)
-    >>> vector = Vector.objects.annotate(x_ceil=Ceil('x'), y_ceil=Ceil('y')).get()
+    >>> vector = Vector.objects.annotate(x_ceil=Ceil("x"), y_ceil=Ceil("y")).get()
     >>> vector.x_ceil, vector.y_ceil
     (4.0, 7.0)
 
@@ -977,7 +1038,7 @@ Usage example:
 
     >>> from django.db.models.functions import Cos
     >>> Vector.objects.create(x=-8.0, y=3.1415926)
-    >>> vector = Vector.objects.annotate(x_cos=Cos('x'), y_cos=Cos('y')).get()
+    >>> vector = Vector.objects.annotate(x_cos=Cos("x"), y_cos=Cos("y")).get()
     >>> vector.x_cos, vector.y_cos
     (-0.14550003380861354, -0.9999999999999986)
 
@@ -1004,7 +1065,7 @@ Usage example:
 
     >>> from django.db.models.functions import Cot
     >>> Vector.objects.create(x=12.0, y=1.0)
-    >>> vector = Vector.objects.annotate(x_cot=Cot('x'), y_cot=Cot('y')).get()
+    >>> vector = Vector.objects.annotate(x_cot=Cot("x"), y_cot=Cot("y")).get()
     >>> vector.x_cot, vector.y_cot
     (-1.5726734063976826, 0.642092615934331)
 
@@ -1031,7 +1092,7 @@ Usage example:
 
     >>> from django.db.models.functions import Degrees
     >>> Vector.objects.create(x=-1.57, y=3.14)
-    >>> vector = Vector.objects.annotate(x_d=Degrees('x'), y_d=Degrees('y')).get()
+    >>> vector = Vector.objects.annotate(x_d=Degrees("x"), y_d=Degrees("y")).get()
     >>> vector.x_d, vector.y_d
     (-89.95437383553924, 179.9087476710785)
 
@@ -1059,7 +1120,7 @@ Usage example:
 
     >>> from django.db.models.functions import Exp
     >>> Vector.objects.create(x=5.4, y=-2.0)
-    >>> vector = Vector.objects.annotate(x_exp=Exp('x'), y_exp=Exp('y')).get()
+    >>> vector = Vector.objects.annotate(x_exp=Exp("x"), y_exp=Exp("y")).get()
     >>> vector.x_exp, vector.y_exp
     (221.40641620418717, 0.1353352832366127)
 
@@ -1087,7 +1148,7 @@ Usage example:
 
     >>> from django.db.models.functions import Floor
     >>> Vector.objects.create(x=5.4, y=-2.3)
-    >>> vector = Vector.objects.annotate(x_floor=Floor('x'), y_floor=Floor('y')).get()
+    >>> vector = Vector.objects.annotate(x_floor=Floor("x"), y_floor=Floor("y")).get()
     >>> vector.x_floor, vector.y_floor
     (5.0, -3.0)
 
@@ -1114,7 +1175,7 @@ Usage example:
 
     >>> from django.db.models.functions import Ln
     >>> Vector.objects.create(x=5.4, y=233.0)
-    >>> vector = Vector.objects.annotate(x_ln=Ln('x'), y_ln=Ln('y')).get()
+    >>> vector = Vector.objects.annotate(x_ln=Ln("x"), y_ln=Ln("y")).get()
     >>> vector.x_ln, vector.y_ln
     (1.6863989535702288, 5.4510384535657)
 
@@ -1142,7 +1203,7 @@ Usage example:
 
     >>> from django.db.models.functions import Log
     >>> Vector.objects.create(x=2.0, y=4.0)
-    >>> vector = Vector.objects.annotate(log=Log('x', 'y')).get()
+    >>> vector = Vector.objects.annotate(log=Log("x", "y")).get()
     >>> vector.log
     2.0
 
@@ -1160,7 +1221,7 @@ Usage example:
 
     >>> from django.db.models.functions import Mod
     >>> Vector.objects.create(x=5.4, y=2.3)
-    >>> vector = Vector.objects.annotate(mod=Mod('x', 'y')).get()
+    >>> vector = Vector.objects.annotate(mod=Mod("x", "y")).get()
     >>> vector.mod
     0.8
 
@@ -1185,7 +1246,7 @@ Usage example:
 
     >>> from django.db.models.functions import Power
     >>> Vector.objects.create(x=2, y=-2)
-    >>> vector = Vector.objects.annotate(power=Power('x', 'y')).get()
+    >>> vector = Vector.objects.annotate(power=Power("x", "y")).get()
     >>> vector.power
     0.25
 
@@ -1202,7 +1263,7 @@ Usage example:
 
     >>> from django.db.models.functions import Radians
     >>> Vector.objects.create(x=-90, y=180)
-    >>> vector = Vector.objects.annotate(x_r=Radians('x'), y_r=Radians('y')).get()
+    >>> vector = Vector.objects.annotate(x_r=Radians("x"), y_r=Radians("y")).get()
     >>> vector.x_r, vector.y_r
     (-1.5707963267948966, 3.141592653589793)
 
@@ -1238,7 +1299,7 @@ Usage example:
 
     >>> from django.db.models.functions import Round
     >>> Vector.objects.create(x=5.4, y=-2.37)
-    >>> vector = Vector.objects.annotate(x_r=Round('x'), y_r=Round('y', precision=1)).get()
+    >>> vector = Vector.objects.annotate(x_r=Round("x"), y_r=Round("y", precision=1)).get()
     >>> vector.x_r, vector.y_r
     (5.0, -2.4)
 
@@ -1265,7 +1326,7 @@ Usage example:
 
     >>> from django.db.models.functions import Sign
     >>> Vector.objects.create(x=5.4, y=-2.3)
-    >>> vector = Vector.objects.annotate(x_sign=Sign('x'), y_sign=Sign('y')).get()
+    >>> vector = Vector.objects.annotate(x_sign=Sign("x"), y_sign=Sign("y")).get()
     >>> vector.x_sign, vector.y_sign
     (1, -1)
 
@@ -1292,7 +1353,7 @@ Usage example:
 
     >>> from django.db.models.functions import Sin
     >>> Vector.objects.create(x=5.4, y=-2.3)
-    >>> vector = Vector.objects.annotate(x_sin=Sin('x'), y_sin=Sin('y')).get()
+    >>> vector = Vector.objects.annotate(x_sin=Sin("x"), y_sin=Sin("y")).get()
     >>> vector.x_sin, vector.y_sin
     (-0.7727644875559871, -0.7457052121767203)
 
@@ -1319,7 +1380,7 @@ Usage example:
 
     >>> from django.db.models.functions import Sqrt
     >>> Vector.objects.create(x=4.0, y=12.0)
-    >>> vector = Vector.objects.annotate(x_sqrt=Sqrt('x'), y_sqrt=Sqrt('y')).get()
+    >>> vector = Vector.objects.annotate(x_sqrt=Sqrt("x"), y_sqrt=Sqrt("y")).get()
     >>> vector.x_sqrt, vector.y_sqrt
     (2.0, 3.46410)
 
@@ -1346,7 +1407,7 @@ Usage example:
 
     >>> from django.db.models.functions import Tan
     >>> Vector.objects.create(x=0, y=12)
-    >>> vector = Vector.objects.annotate(x_tan=Tan('x'), y_tan=Tan('y')).get()
+    >>> vector = Vector.objects.annotate(x_tan=Tan("x"), y_tan=Tan("y")).get()
     >>> vector.x_tan, vector.y_tan
     (0.0, -0.6358599286615808)
 
@@ -1382,8 +1443,8 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.db.models.functions import Chr
-    >>> Author.objects.create(name='Margaret Smith')
-    >>> author = Author.objects.filter(name__startswith=Chr(ord('M'))).get()
+    >>> Author.objects.create(name="Margaret Smith")
+    >>> author = Author.objects.filter(name__startswith=Chr(ord("M"))).get()
     >>> print(author.name)
     Margaret Smith
 
@@ -1410,12 +1471,9 @@ Usage example:
     >>> # Get the display name as "name (goes_by)"
     >>> from django.db.models import CharField, Value as V
     >>> from django.db.models.functions import Concat
-    >>> Author.objects.create(name='Margaret Smith', goes_by='Maggie')
+    >>> Author.objects.create(name="Margaret Smith", goes_by="Maggie")
     >>> author = Author.objects.annotate(
-    ...     screen_name=Concat(
-    ...         'name', V(' ('), 'goes_by', V(')'),
-    ...         output_field=CharField()
-    ...     )
+    ...     screen_name=Concat("name", V(" ("), "goes_by", V(")"), output_field=CharField())
     ... ).get()
     >>> print(author.screen_name)
     Margaret Smith (Maggie)
@@ -1432,8 +1490,8 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.db.models.functions import Left
-    >>> Author.objects.create(name='Margaret Smith')
-    >>> author = Author.objects.annotate(first_initial=Left('name', 1)).get()
+    >>> Author.objects.create(name="Margaret Smith")
+    >>> author = Author.objects.annotate(first_initial=Left("name", 1)).get()
     >>> print(author.first_initial)
     M
 
@@ -1451,10 +1509,10 @@ Usage example:
 
     >>> # Get the length of the name and goes_by fields
     >>> from django.db.models.functions import Length
-    >>> Author.objects.create(name='Margaret Smith')
+    >>> Author.objects.create(name="Margaret Smith")
     >>> author = Author.objects.annotate(
-    ...    name_length=Length('name'),
-    ...    goes_by_length=Length('goes_by')).get()
+    ...     name_length=Length("name"), goes_by_length=Length("goes_by")
+    ... ).get()
     >>> print(author.name_length, author.goes_by_length)
     (14, None)
 
@@ -1483,8 +1541,8 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.db.models.functions import Lower
-    >>> Author.objects.create(name='Margaret Smith')
-    >>> author = Author.objects.annotate(name_lower=Lower('name')).get()
+    >>> Author.objects.create(name="Margaret Smith")
+    >>> author = Author.objects.annotate(name_lower=Lower("name")).get()
     >>> print(author.name_lower)
     margaret smith
 
@@ -1503,10 +1561,10 @@ Usage example:
 
     >>> from django.db.models import Value
     >>> from django.db.models.functions import LPad
-    >>> Author.objects.create(name='John', alias='j')
-    >>> Author.objects.update(name=LPad('name', 8, Value('abc')))
+    >>> Author.objects.create(name="John", alias="j")
+    >>> Author.objects.update(name=LPad("name", 8, Value("abc")))
     1
-    >>> print(Author.objects.get(alias='j').name)
+    >>> print(Author.objects.get(alias="j").name)
     abcaJohn
 
 ``LTrim``
@@ -1532,8 +1590,8 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.db.models.functions import MD5
-    >>> Author.objects.create(name='Margaret Smith')
-    >>> author = Author.objects.annotate(name_md5=MD5('name')).get()
+    >>> Author.objects.create(name="Margaret Smith")
+    >>> author = Author.objects.annotate(name_md5=MD5("name")).get()
     >>> print(author.name_md5)
     749fb689816b2db85f5b169c2055b247
 
@@ -1555,8 +1613,8 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.db.models.functions import Ord
-    >>> Author.objects.create(name='Margaret Smith')
-    >>> author = Author.objects.annotate(name_code_point=Ord('name')).get()
+    >>> Author.objects.create(name="Margaret Smith")
+    >>> author = Author.objects.annotate(name_code_point=Ord("name")).get()
     >>> print(author.name_code_point)
     77
 
@@ -1573,10 +1631,10 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.db.models.functions import Repeat
-    >>> Author.objects.create(name='John', alias='j')
-    >>> Author.objects.update(name=Repeat('name', 3))
+    >>> Author.objects.create(name="John", alias="j")
+    >>> Author.objects.update(name=Repeat("name", 3))
     1
-    >>> print(Author.objects.get(alias='j').name)
+    >>> print(Author.objects.get(alias="j").name)
     JohnJohnJohn
 
 ``Replace``
@@ -1594,11 +1652,11 @@ Usage example:
 
     >>> from django.db.models import Value
     >>> from django.db.models.functions import Replace
-    >>> Author.objects.create(name='Margaret Johnson')
-    >>> Author.objects.create(name='Margaret Smith')
-    >>> Author.objects.update(name=Replace('name', Value('Margaret'), Value('Margareth')))
+    >>> Author.objects.create(name="Margaret Johnson")
+    >>> Author.objects.create(name="Margaret Smith")
+    >>> Author.objects.update(name=Replace("name", Value("Margaret"), Value("Margareth")))
     2
-    >>> Author.objects.values('name')
+    >>> Author.objects.values("name")
     <QuerySet [{'name': 'Margareth Johnson'}, {'name': 'Margareth Smith'}]>
 
 ``Reverse``
@@ -1617,8 +1675,8 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.db.models.functions import Reverse
-    >>> Author.objects.create(name='Margaret Smith')
-    >>> author = Author.objects.annotate(backward=Reverse('name')).get()
+    >>> Author.objects.create(name="Margaret Smith")
+    >>> author = Author.objects.annotate(backward=Reverse("name")).get()
     >>> print(author.backward)
     htimS teragraM
 
@@ -1634,8 +1692,8 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.db.models.functions import Right
-    >>> Author.objects.create(name='Margaret Smith')
-    >>> author = Author.objects.annotate(last_letter=Right('name', 1)).get()
+    >>> Author.objects.create(name="Margaret Smith")
+    >>> author = Author.objects.annotate(last_letter=Right("name", 1)).get()
     >>> print(author.last_letter)
     h
 
@@ -1674,8 +1732,8 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.db.models.functions import SHA1
-    >>> Author.objects.create(name='Margaret Smith')
-    >>> author = Author.objects.annotate(name_sha1=SHA1('name')).get()
+    >>> Author.objects.create(name="Margaret Smith")
+    >>> author = Author.objects.annotate(name_sha1=SHA1("name")).get()
     >>> print(author.name_sha1)
     b87efd8a6c991c390be5a68e8a7945a7851c7e5c
 
@@ -1705,16 +1763,16 @@ Usage example:
 
     >>> from django.db.models import Value as V
     >>> from django.db.models.functions import StrIndex
-    >>> Author.objects.create(name='Margaret Smith')
-    >>> Author.objects.create(name='Smith, Margaret')
-    >>> Author.objects.create(name='Margaret Jackson')
-    >>> Author.objects.filter(name='Margaret Jackson').annotate(
-    ...     smith_index=StrIndex('name', V('Smith'))
+    >>> Author.objects.create(name="Margaret Smith")
+    >>> Author.objects.create(name="Smith, Margaret")
+    >>> Author.objects.create(name="Margaret Jackson")
+    >>> Author.objects.filter(name="Margaret Jackson").annotate(
+    ...     smith_index=StrIndex("name", V("Smith"))
     ... ).get().smith_index
     0
-    >>> authors = Author.objects.annotate(
-    ...    smith_index=StrIndex('name', V('Smith'))
-    ... ).filter(smith_index__gt=0)
+    >>> authors = Author.objects.annotate(smith_index=StrIndex("name", V("Smith"))).filter(
+    ...     smith_index__gt=0
+    ... )
     <QuerySet [<Author: Margaret Smith>, <Author: Smith, Margaret>]>
 
 .. warning::
@@ -1739,10 +1797,10 @@ Usage example:
 
     >>> # Set the alias to the first 5 characters of the name as lowercase
     >>> from django.db.models.functions import Lower, Substr
-    >>> Author.objects.create(name='Margaret Smith')
-    >>> Author.objects.update(alias=Lower(Substr('name', 1, 5)))
+    >>> Author.objects.create(name="Margaret Smith")
+    >>> Author.objects.update(alias=Lower(Substr("name", 1, 5)))
     1
-    >>> print(Author.objects.get(name='Margaret Smith').alias)
+    >>> print(Author.objects.get(name="Margaret Smith").alias)
     marga
 
 ``Trim``
@@ -1758,10 +1816,10 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.db.models.functions import Trim
-    >>> Author.objects.create(name='  John  ', alias='j')
-    >>> Author.objects.update(name=Trim('name'))
+    >>> Author.objects.create(name="  John  ", alias="j")
+    >>> Author.objects.update(name=Trim("name"))
     1
-    >>> print(Author.objects.get(alias='j').name)
+    >>> print(Author.objects.get(alias="j").name)
     John
 
 ``Upper``
@@ -1779,8 +1837,8 @@ Usage example:
 .. code-block:: pycon
 
     >>> from django.db.models.functions import Upper
-    >>> Author.objects.create(name='Margaret Smith')
-    >>> author = Author.objects.annotate(name_upper=Upper('name')).get()
+    >>> Author.objects.create(name="Margaret Smith")
+    >>> author = Author.objects.annotate(name_upper=Upper("name")).get()
     >>> print(author.name_upper)
     MARGARET SMITH
 

+ 99 - 88
docs/ref/models/expressions.txt

@@ -28,18 +28,19 @@ Some examples
     >>> from django.db.models.lookups import GreaterThan
 
     # Find companies that have more employees than chairs.
-    >>> Company.objects.filter(num_employees__gt=F('num_chairs'))
+    >>> Company.objects.filter(num_employees__gt=F("num_chairs"))
 
     # Find companies that have at least twice as many employees
     # as chairs. Both the querysets below are equivalent.
-    >>> Company.objects.filter(num_employees__gt=F('num_chairs') * 2)
-    >>> Company.objects.filter(
-    ...     num_employees__gt=F('num_chairs') + F('num_chairs'))
+    >>> Company.objects.filter(num_employees__gt=F("num_chairs") * 2)
+    >>> Company.objects.filter(num_employees__gt=F("num_chairs") + F("num_chairs"))
 
     # How many chairs are needed for each company to seat all employees?
-    >>> company = Company.objects.filter(
-    ...    num_employees__gt=F('num_chairs')).annotate(
-    ...    chairs_needed=F('num_employees') - F('num_chairs')).first()
+    >>> company = (
+    ...     Company.objects.filter(num_employees__gt=F("num_chairs"))
+    ...     .annotate(chairs_needed=F("num_employees") - F("num_chairs"))
+    ...     .first()
+    ... )
     >>> company.num_employees
     120
     >>> company.num_chairs
@@ -48,7 +49,7 @@ Some examples
     70
 
     # Create a new company using expressions.
-    >>> company = Company.objects.create(name='Google', ticker=Upper(Value('goog')))
+    >>> company = Company.objects.create(name="Google", ticker=Upper(Value("goog")))
     # Be sure to refresh it if you need to access the field.
     >>> company.refresh_from_db()
     >>> company.ticker
@@ -109,7 +110,7 @@ describes the required operation at the database level.
 Let's try this with an example. Normally, one might do something like this::
 
     # Tintin filed a news story!
-    reporter = Reporters.objects.get(name='Tintin')
+    reporter = Reporters.objects.get(name="Tintin")
     reporter.stories_filed += 1
     reporter.save()
 
@@ -119,8 +120,8 @@ the object back to the database. But instead we could also have done::
 
     from django.db.models import F
 
-    reporter = Reporters.objects.get(name='Tintin')
-    reporter.stories_filed = F('stories_filed') + 1
+    reporter = Reporters.objects.get(name="Tintin")
+    reporter.stories_filed = F("stories_filed") + 1
     reporter.save()
 
 Although ``reporter.stories_filed = F('stories_filed') + 1`` looks like a
@@ -148,15 +149,15 @@ be used on ``QuerySets`` of object instances, with ``update()``. This reduces
 the two queries we were using above - the ``get()`` and the
 :meth:`~Model.save()` - to just one::
 
-    reporter = Reporters.objects.filter(name='Tintin')
-    reporter.update(stories_filed=F('stories_filed') + 1)
+    reporter = Reporters.objects.filter(name="Tintin")
+    reporter.update(stories_filed=F("stories_filed") + 1)
 
 We can also use :meth:`~django.db.models.query.QuerySet.update()` to increment
 the field value on multiple objects - which could be very much faster than
 pulling them all into Python from the database, looping over them, incrementing
 the field value of each one, and saving each one back to the database::
 
-    Reporter.objects.update(stories_filed=F('stories_filed') + 1)
+    Reporter.objects.update(stories_filed=F("stories_filed") + 1)
 
 ``F()`` therefore can offer performance advantages by:
 
@@ -187,11 +188,11 @@ than based on its value when the instance was retrieved.
 ``F()`` objects assigned to model fields persist after saving the model
 instance and will be applied on each :meth:`~Model.save()`. For example::
 
-    reporter = Reporters.objects.get(name='Tintin')
-    reporter.stories_filed = F('stories_filed') + 1
+    reporter = Reporters.objects.get(name="Tintin")
+    reporter.stories_filed = F("stories_filed") + 1
     reporter.save()
 
-    reporter.name = 'Tintin Jr.'
+    reporter.name = "Tintin Jr."
     reporter.save()
 
 ``stories_filed`` will be updated twice in this case. If it's initially ``1``,
@@ -217,8 +218,7 @@ Using ``F()`` with annotations
 ``F()`` can be used to create dynamic fields on your models by combining
 different fields with arithmetic::
 
-    company = Company.objects.annotate(
-        chairs_needed=F('num_employees') - F('num_chairs'))
+    company = Company.objects.annotate(chairs_needed=F("num_employees") - F("num_chairs"))
 
 If the fields that you're combining are of different types you'll need
 to tell Django what kind of field will be returned. Since ``F()`` does not
@@ -229,7 +229,9 @@ directly support ``output_field`` you will need to wrap the expression with
 
     Ticket.objects.annotate(
         expires=ExpressionWrapper(
-            F('active_at') + F('duration'), output_field=DateTimeField()))
+            F("active_at") + F("duration"), output_field=DateTimeField()
+        )
+    )
 
 When referencing relational fields such as ``ForeignKey``, ``F()`` returns the
 primary key value rather than a model instance:
@@ -255,7 +257,8 @@ For example, to sort companies that haven't been contacted (``last_contacted``
 is null) after companies that have been contacted::
 
     from django.db.models import F
-    Company.objects.order_by(F('last_contacted').desc(nulls_last=True))
+
+    Company.objects.order_by(F("last_contacted").desc(nulls_last=True))
 
 Using ``F()`` with logical operations
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -268,7 +271,7 @@ companies::
 
     from django.db.models import F
 
-    Company.objects.update(is_active=~F('is_active'))
+    Company.objects.update(is_active=~F("is_active"))
 
 .. _func-expressions:
 
@@ -281,14 +284,15 @@ They can be used directly::
 
     from django.db.models import F, Func
 
-    queryset.annotate(field_lower=Func(F('field'), function='LOWER'))
+    queryset.annotate(field_lower=Func(F("field"), function="LOWER"))
 
 or they can be used to build a library of database functions::
 
     class Lower(Func):
-        function = 'LOWER'
+        function = "LOWER"
+
 
-    queryset.annotate(field_lower=Lower('field'))
+    queryset.annotate(field_lower=Lower("field"))
 
 But both cases will result in a queryset where each model is annotated with an
 extra attribute ``field_lower`` produced, roughly, from the following SQL:
@@ -350,13 +354,14 @@ The ``Func`` API is as follows:
 
             class ConcatPair(Func):
                 ...
-                function = 'CONCAT'
+                function = "CONCAT"
                 ...
 
                 def as_mysql(self, compiler, connection, **extra_context):
                     return super().as_sql(
-                        compiler, connection,
-                        function='CONCAT_WS',
+                        compiler,
+                        connection,
+                        function="CONCAT_WS",
                         template="%(function)s('', %(expressions)s)",
                         **extra_context
                     )
@@ -400,7 +405,8 @@ some complex computations::
     from django.db.models import Count
 
     Company.objects.annotate(
-        managers_required=(Count('num_employees') / 4) + Count('num_managers'))
+        managers_required=(Count("num_employees") / 4) + Count("num_managers")
+    )
 
 The ``Aggregate`` API is as follows:
 
@@ -477,18 +483,15 @@ generated. Here's a brief example::
 
     from django.db.models import Aggregate
 
+
     class Sum(Aggregate):
         # Supports SUM(ALL field).
-        function = 'SUM'
-        template = '%(function)s(%(all_values)s%(expressions)s)'
+        function = "SUM"
+        template = "%(function)s(%(all_values)s%(expressions)s)"
         allow_distinct = False
 
         def __init__(self, expression, all_values=False, **extra):
-            super().__init__(
-                expression,
-                all_values='ALL ' if all_values else '',
-                **extra
-            )
+            super().__init__(expression, all_values="ALL " if all_values else "", **extra)
 
 ``Value()`` expressions
 -----------------------
@@ -554,8 +557,8 @@ newest comment on that post:
 .. code-block:: pycon
 
     >>> from django.db.models import OuterRef, Subquery
-    >>> newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
-    >>> Post.objects.annotate(newest_commenter_email=Subquery(newest.values('email')[:1]))
+    >>> newest = Comment.objects.filter(post=OuterRef("pk")).order_by("-created_at")
+    >>> Post.objects.annotate(newest_commenter_email=Subquery(newest.values("email")[:1]))
 
 On PostgreSQL, the SQL looks like:
 
@@ -592,7 +595,7 @@ parent. For example, this queryset would need to be within a nested pair of
 
 .. code-block:: pycon
 
-    >>> Book.objects.filter(author=OuterRef(OuterRef('pk')))
+    >>> Book.objects.filter(author=OuterRef(OuterRef("pk")))
 
 Limiting a subquery to a single column
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -607,7 +610,7 @@ all comments for posts published within the last day:
     >>> from django.utils import timezone
     >>> one_day_ago = timezone.now() - timedelta(days=1)
     >>> posts = Post.objects.filter(published_at__gte=one_day_ago)
-    >>> Comment.objects.filter(post__in=Subquery(posts.values('pk')))
+    >>> Comment.objects.filter(post__in=Subquery(posts.values("pk")))
 
 In this case, the subquery must use :meth:`~.QuerySet.values`
 to return only a single column: the primary key of the post.
@@ -620,7 +623,7 @@ queryset is used:
 
 .. code-block:: pycon
 
-    >>> subquery = Subquery(newest.values('email')[:1])
+    >>> subquery = Subquery(newest.values("email")[:1])
     >>> Post.objects.annotate(newest_commenter_email=subquery)
 
 In this case, the subquery must only return a single column *and* a single
@@ -649,7 +652,7 @@ within the last day:
     >>> from django.utils import timezone
     >>> one_day_ago = timezone.now() - timedelta(days=1)
     >>> recent_comments = Comment.objects.filter(
-    ...     post=OuterRef('pk'),
+    ...     post=OuterRef("pk"),
     ...     created_at__gte=one_day_ago,
     ... )
     >>> Post.objects.annotate(recent_comment=Exists(recent_comments))
@@ -703,8 +706,8 @@ length is greater than the total length of all combined comments:
 .. code-block:: pycon
 
     >>> from django.db.models import OuterRef, Subquery, Sum
-    >>> comments = Comment.objects.filter(post=OuterRef('pk')).order_by().values('post')
-    >>> total_comments = comments.annotate(total=Sum('length')).values('total')
+    >>> comments = Comment.objects.filter(post=OuterRef("pk")).order_by().values("post")
+    >>> total_comments = comments.annotate(total=Sum("length")).values("total")
     >>> Post.objects.filter(length__gt=Subquery(total_comments))
 
 The initial ``filter(...)`` limits the subquery to the relevant parameters.
@@ -814,9 +817,9 @@ the same studio in the same genre and release year:
     >>> from django.db.models import Avg, F, Window
     >>> Movie.objects.annotate(
     ...     avg_rating=Window(
-    ...         expression=Avg('rating'),
-    ...         partition_by=[F('studio'), F('genre')],
-    ...         order_by='released__year',
+    ...         expression=Avg("rating"),
+    ...         partition_by=[F("studio"), F("genre")],
+    ...         order_by="released__year",
     ...     ),
     ... )
 
@@ -833,18 +836,21 @@ to reduce repetition:
 
     >>> from django.db.models import Avg, F, Max, Min, Window
     >>> window = {
-    ...    'partition_by': [F('studio'), F('genre')],
-    ...    'order_by': 'released__year',
+    ...     "partition_by": [F("studio"), F("genre")],
+    ...     "order_by": "released__year",
     ... }
     >>> Movie.objects.annotate(
     ...     avg_rating=Window(
-    ...         expression=Avg('rating'), **window,
+    ...         expression=Avg("rating"),
+    ...         **window,
     ...     ),
     ...     best=Window(
-    ...         expression=Max('rating'), **window,
+    ...         expression=Max("rating"),
+    ...         **window,
     ...     ),
     ...     worst=Window(
-    ...         expression=Min('rating'), **window,
+    ...         expression=Min("rating"),
+    ...         **window,
     ...     ),
     ... )
 
@@ -860,13 +866,9 @@ from groups to be included:
 .. code-block:: pycon
 
     >>> qs = Movie.objects.annotate(
-    ...     category_rank=Window(
-    ...         Rank(), partition_by='category', order_by='-rating'
-    ...     ),
-    ...     scenes_count=Count('actors'),
-    ... ).filter(
-    ...     Q(category_rank__lte=3) | Q(title__contains='Batman')
-    ... )
+    ...     category_rank=Window(Rank(), partition_by="category", order_by="-rating"),
+    ...     scenes_count=Count("actors"),
+    ... ).filter(Q(category_rank__lte=3) | Q(title__contains="Batman"))
     >>> list(qs)
     NotImplementedError: Heterogeneous disjunctive predicates against window functions
     are not implemented when performing conditional aggregation.
@@ -946,9 +948,9 @@ with the average rating of a movie's two prior and two following peers:
     >>> from django.db.models import Avg, F, RowRange, Window
     >>> Movie.objects.annotate(
     ...     avg_rating=Window(
-    ...         expression=Avg('rating'),
-    ...         partition_by=[F('studio'), F('genre')],
-    ...         order_by='released__year',
+    ...         expression=Avg("rating"),
+    ...         partition_by=[F("studio"), F("genre")],
+    ...         order_by="released__year",
     ...         frame=RowRange(start=-2, end=2),
     ...     ),
     ... )
@@ -964,9 +966,9 @@ released between twelve months before and twelve months after the each movie:
     >>> from django.db.models import Avg, F, ValueRange, Window
     >>> Movie.objects.annotate(
     ...     avg_rating=Window(
-    ...         expression=Avg('rating'),
-    ...         partition_by=[F('studio'), F('genre')],
-    ...         order_by='released__year',
+    ...         expression=Avg("rating"),
+    ...         partition_by=[F("studio"), F("genre")],
+    ...         order_by="released__year",
     ...         frame=ValueRange(start=-12, end=12),
     ...     ),
     ... )
@@ -1050,7 +1052,7 @@ calling the appropriate methods on the wrapped expression.
 
         .. code-block:: pycon
 
-          >>> Sum(F('foo')).get_source_expressions()
+          >>> Sum(F("foo")).get_source_expressions()
           [F('foo')]
 
     .. method:: set_source_expressions(expressions)
@@ -1133,17 +1135,18 @@ an ``__init__()`` method to set some attributes::
   import copy
   from django.db.models import Expression
 
+
   class Coalesce(Expression):
-      template = 'COALESCE( %(expressions)s )'
+      template = "COALESCE( %(expressions)s )"
 
       def __init__(self, expressions, output_field):
-        super().__init__(output_field=output_field)
-        if len(expressions) < 2:
-            raise ValueError('expressions must have at least 2 elements')
-        for expression in expressions:
-            if not hasattr(expression, 'resolve_expression'):
-                raise TypeError('%r is not an Expression' % expression)
-        self.expressions = expressions
+          super().__init__(output_field=output_field)
+          if len(expressions) < 2:
+              raise ValueError("expressions must have at least 2 elements")
+          for expression in expressions:
+              if not hasattr(expression, "resolve_expression"):
+                  raise TypeError("%r is not an Expression" % expression)
+          self.expressions = expressions
 
 We do some basic validation on the parameters, including requiring at least
 2 columns or values, and ensuring they are expressions. We are requiring
@@ -1154,11 +1157,15 @@ Now we implement the preprocessing and validation. Since we do not have
 any of our own validation at this point, we delegate to the nested
 expressions::
 
-    def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
+    def resolve_expression(
+        self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False
+    ):
         c = self.copy()
         c.is_summary = summarize
         for pos, expression in enumerate(self.expressions):
-            c.expressions[pos] = expression.resolve_expression(query, allow_joins, reuse, summarize, for_save)
+            c.expressions[pos] = expression.resolve_expression(
+                query, allow_joins, reuse, summarize, for_save
+            )
         return c
 
 Next, we write the method responsible for generating the SQL::
@@ -1170,15 +1177,16 @@ Next, we write the method responsible for generating the SQL::
             sql_expressions.append(sql)
             sql_params.extend(params)
         template = template or self.template
-        data = {'expressions': ','.join(sql_expressions)}
+        data = {"expressions": ",".join(sql_expressions)}
         return template % data, sql_params
 
+
     def as_oracle(self, compiler, connection):
         """
         Example of vendor specific handling (Oracle in this case).
         Let's make the function name lowercase.
         """
-        return self.as_sql(compiler, connection, template='coalesce( %(expressions)s )')
+        return self.as_sql(compiler, connection, template="coalesce( %(expressions)s )")
 
 ``as_sql()`` methods can support custom keyword arguments, allowing
 ``as_vendorname()`` methods to override data used to generate the SQL string.
@@ -1203,6 +1211,7 @@ to play nice with other query expressions::
     def get_source_expressions(self):
         return self.expressions
 
+
     def set_source_expressions(self, expressions):
         self.expressions = expressions
 
@@ -1212,12 +1221,11 @@ Let's see how it works:
 
     >>> from django.db.models import F, Value, CharField
     >>> qs = Company.objects.annotate(
-    ...    tagline=Coalesce([
-    ...        F('motto'),
-    ...        F('ticker_name'),
-    ...        F('description'),
-    ...        Value('No Tagline')
-    ...        ], output_field=CharField()))
+    ...     tagline=Coalesce(
+    ...         [F("motto"), F("ticker_name"), F("description"), Value("No Tagline")],
+    ...         output_field=CharField(),
+    ...     )
+    ... )
     >>> for c in qs:
     ...     print("%s: %s" % (c.name, c.tagline))
     ...
@@ -1241,8 +1249,9 @@ SQL injection::
 
     from django.db.models import Func
 
+
     class Position(Func):
-        function = 'POSITION'
+        function = "POSITION"
         template = "%(function)s('%(substring)s' in %(expressions)s)"
 
         def __init__(self, expression, substring):
@@ -1256,8 +1265,8 @@ interpolated into the SQL string before the query is sent to the database.
 Here's a corrected rewrite::
 
     class Position(Func):
-        function = 'POSITION'
-        arg_joiner = ' IN '
+        function = "POSITION"
+        arg_joiner = " IN "
 
         def __init__(self, expression, substring):
             super().__init__(substring, expression)
@@ -1279,8 +1288,10 @@ class::
 
     from django.db.models.functions import Length
 
+
     def sqlserver_length(self, compiler, connection):
-        return self.as_sql(compiler, connection, function='LEN')
+        return self.as_sql(compiler, connection, function="LEN")
+
 
     Length.as_sqlserver = sqlserver_length
 

+ 93 - 65
docs/ref/models/fields.txt

@@ -96,11 +96,11 @@ The first element in each tuple is the actual value to be set on the model,
 and the second element is the human-readable name. For example::
 
     YEAR_IN_SCHOOL_CHOICES = [
-        ('FR', 'Freshman'),
-        ('SO', 'Sophomore'),
-        ('JR', 'Junior'),
-        ('SR', 'Senior'),
-        ('GR', 'Graduate'),
+        ("FR", "Freshman"),
+        ("SO", "Sophomore"),
+        ("JR", "Junior"),
+        ("SR", "Senior"),
+        ("GR", "Graduate"),
     ]
 
 Generally, it's best to define choices inside a model class, and to
@@ -108,18 +108,19 @@ define a suitably-named constant for each value::
 
     from django.db import models
 
+
     class Student(models.Model):
-        FRESHMAN = 'FR'
-        SOPHOMORE = 'SO'
-        JUNIOR = 'JR'
-        SENIOR = 'SR'
-        GRADUATE = 'GR'
+        FRESHMAN = "FR"
+        SOPHOMORE = "SO"
+        JUNIOR = "JR"
+        SENIOR = "SR"
+        GRADUATE = "GR"
         YEAR_IN_SCHOOL_CHOICES = [
-            (FRESHMAN, 'Freshman'),
-            (SOPHOMORE, 'Sophomore'),
-            (JUNIOR, 'Junior'),
-            (SENIOR, 'Senior'),
-            (GRADUATE, 'Graduate'),
+            (FRESHMAN, "Freshman"),
+            (SOPHOMORE, "Sophomore"),
+            (JUNIOR, "Junior"),
+            (SENIOR, "Senior"),
+            (GRADUATE, "Graduate"),
         ]
         year_in_school = models.CharField(
             max_length=2,
@@ -142,17 +143,21 @@ You can also collect your available choices into named groups that can
 be used for organizational purposes::
 
     MEDIA_CHOICES = [
-        ('Audio', (
-                ('vinyl', 'Vinyl'),
-                ('cd', 'CD'),
-            )
+        (
+            "Audio",
+            (
+                ("vinyl", "Vinyl"),
+                ("cd", "CD"),
+            ),
         ),
-        ('Video', (
-                ('vhs', 'VHS Tape'),
-                ('dvd', 'DVD'),
-            )
+        (
+            "Video",
+            (
+                ("vhs", "VHS Tape"),
+                ("dvd", "DVD"),
+            ),
         ),
-        ('unknown', 'Unknown'),
+        ("unknown", "Unknown"),
     ]
 
 The first element in each tuple is the name to apply to the group. The
@@ -194,14 +199,14 @@ choices in a concise way::
 
     from django.utils.translation import gettext_lazy as _
 
-    class Student(models.Model):
 
+    class Student(models.Model):
         class YearInSchool(models.TextChoices):
-            FRESHMAN = 'FR', _('Freshman')
-            SOPHOMORE = 'SO', _('Sophomore')
-            JUNIOR = 'JR', _('Junior')
-            SENIOR = 'SR', _('Senior')
-            GRADUATE = 'GR', _('Graduate')
+            FRESHMAN = "FR", _("Freshman")
+            SOPHOMORE = "SO", _("Sophomore")
+            JUNIOR = "JR", _("Junior")
+            SENIOR = "SR", _("Senior")
+            GRADUATE = "GR", _("Graduate")
 
         year_in_school = models.CharField(
             max_length=2,
@@ -254,9 +259,9 @@ title-case):
 .. code-block:: pycon
 
     >>> class Vehicle(models.TextChoices):
-    ...     CAR = 'C'
-    ...     TRUCK = 'T'
-    ...     JET_SKI = 'J'
+    ...     CAR = "C"
+    ...     TRUCK = "T"
+    ...     JET_SKI = "J"
     ...
     >>> Vehicle.JET_SKI.label
     'Jet Ski'
@@ -265,7 +270,6 @@ Since the case where the enum values need to be integers is extremely common,
 Django provides an ``IntegerChoices`` class. For example::
 
     class Card(models.Model):
-
         class Suit(models.IntegerChoices):
             DIAMOND = 1
             SPADE = 2
@@ -280,10 +284,10 @@ that labels are automatically generated as highlighted above:
 
 .. code-block:: pycon
 
-    >>> MedalType = models.TextChoices('MedalType', 'GOLD SILVER BRONZE')
+    >>> MedalType = models.TextChoices("MedalType", "GOLD SILVER BRONZE")
     >>> MedalType.choices
     [('GOLD', 'Gold'), ('SILVER', 'Silver'), ('BRONZE', 'Bronze')]
-    >>> Place = models.IntegerChoices('Place', 'FIRST SECOND THIRD')
+    >>> Place = models.IntegerChoices("Place", "FIRST SECOND THIRD")
     >>> Place.choices
     [(1, 'First'), (2, 'Second'), (3, 'Third')]
 
@@ -294,12 +298,12 @@ you can subclass ``Choices`` and the required concrete data type, e.g.
 :class:`~datetime.date` for use with :class:`~django.db.models.DateField`::
 
     class MoonLandings(datetime.date, models.Choices):
-        APOLLO_11 = 1969, 7, 20, 'Apollo 11 (Eagle)'
-        APOLLO_12 = 1969, 11, 19, 'Apollo 12 (Intrepid)'
-        APOLLO_14 = 1971, 2, 5, 'Apollo 14 (Antares)'
-        APOLLO_15 = 1971, 7, 30, 'Apollo 15 (Falcon)'
-        APOLLO_16 = 1972, 4, 21, 'Apollo 16 (Orion)'
-        APOLLO_17 = 1972, 12, 11, 'Apollo 17 (Challenger)'
+        APOLLO_11 = 1969, 7, 20, "Apollo 11 (Eagle)"
+        APOLLO_12 = 1969, 11, 19, "Apollo 12 (Intrepid)"
+        APOLLO_14 = 1971, 2, 5, "Apollo 14 (Antares)"
+        APOLLO_15 = 1971, 7, 30, "Apollo 15 (Falcon)"
+        APOLLO_16 = 1972, 4, 21, "Apollo 16 (Orion)"
+        APOLLO_17 = 1972, 12, 11, "Apollo 17 (Challenger)"
 
 There are some additional caveats to be aware of:
 
@@ -311,10 +315,10 @@ There are some additional caveats to be aware of:
   set the ``__empty__`` attribute on the class::
 
     class Answer(models.IntegerChoices):
-        NO = 0, _('No')
-        YES = 1, _('Yes')
+        NO = 0, _("No")
+        YES = 1, _("Yes")
 
-        __empty__ = _('(Unknown)')
+        __empty__ = _("(Unknown)")
 
 ``db_column``
 -------------
@@ -386,6 +390,7 @@ callable. For example, if you want to specify a default ``dict`` for
     def contact_default():
         return {"email": "to1@example.com"}
 
+
     contact_info = JSONField("ContactInfo", default=contact_default)
 
 ``lambda``\s can't be used for field options like ``default`` because they
@@ -437,7 +442,7 @@ Note that this value is *not* HTML-escaped in automatically-generated
 forms. This lets you include HTML in :attr:`~Field.help_text` if you so
 desire. For example::
 
-    help_text="Please use the following format: <em>YYYY-MM-DD</em>."
+    help_text = "Please use the following format: <em>YYYY-MM-DD</em>."
 
 Alternatively you can use plain text and
 :func:`django.utils.html.escape` to escape any HTML special characters. Ensure
@@ -822,10 +827,10 @@ Has the following optional arguments:
 
         class MyModel(models.Model):
             # file will be uploaded to MEDIA_ROOT/uploads
-            upload = models.FileField(upload_to='uploads/')
+            upload = models.FileField(upload_to="uploads/")
             # or...
             # file will be saved to MEDIA_ROOT/uploads/2015/01/30
-            upload = models.FileField(upload_to='uploads/%Y/%m/%d/')
+            upload = models.FileField(upload_to="uploads/%Y/%m/%d/")
 
     If you are using the default
     :class:`~django.core.files.storage.FileSystemStorage`, the string value
@@ -861,7 +866,8 @@ Has the following optional arguments:
 
         def user_directory_path(instance, filename):
             # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
-            return 'user_{0}/{1}'.format(instance.user.id, filename)
+            return "user_{0}/{1}".format(instance.user.id, filename)
+
 
         class MyModel(models.Model):
             upload = models.FileField(upload_to=user_directory_path)
@@ -1023,13 +1029,15 @@ You can construct a :class:`~django.core.files.File` from an existing
 Python file object like this::
 
     from django.core.files import File
+
     # Open an existing file using Python's built-in open()
-    f = open('/path/to/hello.world')
+    f = open("/path/to/hello.world")
     myfile = File(f)
 
 Or you can construct one from a Python string like this::
 
     from django.core.files.base import ContentFile
+
     myfile = ContentFile("hello world")
 
 For more information, see :doc:`/topics/files`.
@@ -1072,8 +1080,10 @@ directory on the filesystem. Has some special arguments, of which the first is
         from django.conf import settings
         from django.db import models
 
+
         def images_path():
-            return os.path.join(settings.LOCAL_FILE_DIR, 'images')
+            return os.path.join(settings.LOCAL_FILE_DIR, "images")
+
 
         class MyModel(models.Model):
             file = models.FilePathField(path=images_path)
@@ -1423,6 +1433,7 @@ it is recommended to use :attr:`~Field.default`::
     import uuid
     from django.db import models
 
+
     class MyUUIDModel(models.Model):
         id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
         # other fields
@@ -1470,13 +1481,15 @@ you can use the name of the model, rather than the model object itself::
 
     from django.db import models
 
+
     class Car(models.Model):
         manufacturer = models.ForeignKey(
-            'Manufacturer',
+            "Manufacturer",
             on_delete=models.CASCADE,
         )
         # ...
 
+
     class Manufacturer(models.Model):
         # ...
         pass
@@ -1490,8 +1503,9 @@ concrete model and are not relative to the abstract model's ``app_label``:
 
     from django.db import models
 
+
     class AbstractCar(models.Model):
-        manufacturer = models.ForeignKey('Manufacturer', on_delete=models.CASCADE)
+        manufacturer = models.ForeignKey("Manufacturer", on_delete=models.CASCADE)
 
         class Meta:
             abstract = True
@@ -1502,12 +1516,15 @@ concrete model and are not relative to the abstract model's ``app_label``:
     from django.db import models
     from products.models import AbstractCar
 
+
     class Manufacturer(models.Model):
         pass
 
+
     class Car(AbstractCar):
         pass
 
+
     # Car.manufacturer will point to `production.Manufacturer` here.
 
 To refer to models defined in another application, you can explicitly specify
@@ -1517,7 +1534,7 @@ need to use::
 
     class Car(models.Model):
         manufacturer = models.ForeignKey(
-            'production.Manufacturer',
+            "production.Manufacturer",
             on_delete=models.CASCADE,
         )
 
@@ -1599,9 +1616,11 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
         class Artist(models.Model):
             name = models.CharField(max_length=10)
 
+
         class Album(models.Model):
             artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
 
+
         class Song(models.Model):
             artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
             album = models.ForeignKey(Album, on_delete=models.RESTRICT)
@@ -1612,8 +1631,8 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
 
     .. code-block:: pycon
 
-        >>> artist_one = Artist.objects.create(name='artist one')
-        >>> artist_two = Artist.objects.create(name='artist two')
+        >>> artist_one = Artist.objects.create(name="artist one")
+        >>> artist_two = Artist.objects.create(name="artist two")
         >>> album_one = Album.objects.create(artist=artist_one)
         >>> album_two = Album.objects.create(artist=artist_two)
         >>> song_one = Song.objects.create(artist=artist_one, album=album_one)
@@ -1647,8 +1666,10 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
         from django.contrib.auth import get_user_model
         from django.db import models
 
+
         def get_sentinel_user():
-            return get_user_model().objects.get_or_create(username='deleted')[0]
+            return get_user_model().objects.get_or_create(username="deleted")[0]
+
 
         class MyModel(models.Model):
             user = models.ForeignKey(
@@ -1675,7 +1696,7 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
         staff_member = models.ForeignKey(
             User,
             on_delete=models.CASCADE,
-            limit_choices_to={'is_staff': True},
+            limit_choices_to={"is_staff": True},
         )
 
     causes the corresponding field on the ``ModelForm`` to list only ``Users``
@@ -1686,7 +1707,8 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
     example::
 
         def limit_pub_date_choices():
-            return {'pub_date__lte': datetime.date.today()}
+            return {"pub_date__lte": datetime.date.today()}
+
 
         limit_choices_to = limit_pub_date_choices
 
@@ -1724,7 +1746,7 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
         user = models.ForeignKey(
             User,
             on_delete=models.CASCADE,
-            related_name='+',
+            related_name="+",
         )
 
 .. attribute:: ForeignKey.related_query_name
@@ -1744,6 +1766,7 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
             )
             name = models.CharField(max_length=255)
 
+
         # That's now the name of the reverse filter
         Article.objects.filter(tag__name="important")
 
@@ -1841,6 +1864,7 @@ that control how the relationship functions.
 
         from django.db import models
 
+
         class Person(models.Model):
             friends = models.ManyToManyField("self")
 
@@ -1918,17 +1942,20 @@ that control how the relationship functions.
 
         from django.db import models
 
+
         class Person(models.Model):
             name = models.CharField(max_length=50)
 
+
         class Group(models.Model):
             name = models.CharField(max_length=128)
             members = models.ManyToManyField(
                 Person,
-                through='Membership',
-                through_fields=('group', 'person'),
+                through="Membership",
+                through_fields=("group", "person"),
             )
 
+
         class Membership(models.Model):
             group = models.ForeignKey(Group, on_delete=models.CASCADE)
             person = models.ForeignKey(Person, on_delete=models.CASCADE)
@@ -2027,6 +2054,7 @@ With the following example::
     from django.conf import settings
     from django.db import models
 
+
     class MySpecialUser(models.Model):
         user = models.OneToOneField(
             settings.AUTH_USER_MODEL,
@@ -2035,7 +2063,7 @@ With the following example::
         supervisor = models.OneToOneField(
             settings.AUTH_USER_MODEL,
             on_delete=models.CASCADE,
-            related_name='supervisor_of',
+            related_name="supervisor_of",
         )
 
 your resulting ``User`` model will have the following attributes:
@@ -2043,9 +2071,9 @@ your resulting ``User`` model will have the following attributes:
 .. code-block:: pycon
 
     >>> user = User.objects.get(pk=1)
-    >>> hasattr(user, 'myspecialuser')
+    >>> hasattr(user, "myspecialuser")
     True
-    >>> hasattr(user, 'supervisor_of')
+    >>> hasattr(user, "supervisor_of")
     True
 
 A ``RelatedObjectDoesNotExist`` exception is raised when accessing the reverse

+ 3 - 3
docs/ref/models/indexes.txt

@@ -35,14 +35,14 @@ expressions and database functions.
 
 For example::
 
-    Index(Lower('title').desc(), 'pub_date', name='lower_title_date_idx')
+    Index(Lower("title").desc(), "pub_date", name="lower_title_date_idx")
 
 creates an index on the lowercased value of the ``title`` field in descending
 order and the ``pub_date`` field in the default ascending order.
 
 Another example::
 
-    Index(F('height') * F('weight'), Round('weight'), name='calc_idx')
+    Index(F("height") * F("weight"), Round("weight"), name="calc_idx")
 
 creates an index on the result of multiplying fields ``height`` and ``weight``
 and the ``weight`` rounded to the nearest integer.
@@ -197,7 +197,7 @@ fields (:attr:`~Index.fields`).
 
 For example::
 
-    Index(name='covering_index', fields=['headline'], include=['pub_date'])
+    Index(name="covering_index", fields=["headline"], include=["pub_date"])
 
 will allow filtering on ``headline``, also selecting ``pub_date``, while
 fetching data only from the index.

+ 63 - 38
docs/ref/models/instances.txt

@@ -36,6 +36,7 @@ need to :meth:`~Model.save()`.
 
         from django.db import models
 
+
         class Book(models.Model):
             title = models.CharField(max_length=100)
 
@@ -45,6 +46,7 @@ need to :meth:`~Model.save()`.
                 # do something with the book
                 return book
 
+
         book = Book.create("Pride and Prejudice")
 
     #. Add a method on a custom manager (usually preferred)::
@@ -55,11 +57,13 @@ need to :meth:`~Model.save()`.
                 # do something with the book
                 return book
 
+
         class Book(models.Model):
             title = models.CharField(max_length=100)
 
             objects = BookManager()
 
+
         book = Book.objects.create_book("Pride and Prejudice")
 
 Customizing model loading
@@ -88,6 +92,7 @@ are loaded from the database::
 
     from django.db.models import DEFERRED
 
+
     @classmethod
     def from_db(cls, db, field_names, values):
         # Default implementation of from_db() (subject to change and could
@@ -108,12 +113,14 @@ are loaded from the database::
         )
         return instance
 
+
     def save(self, *args, **kwargs):
         # Check how the current values differ from ._loaded_values. For example,
         # prevent changing the creator_id of the model. (This example doesn't
         # support cases where 'creator_id' is deferred).
         if not self._state.adding and (
-                self.creator_id != self._loaded_values['creator_id']):
+            self.creator_id != self._loaded_values["creator_id"]
+        ):
             raise ValueError("Updating the value of creator isn't allowed")
         super().save(*args, **kwargs)
 
@@ -163,7 +170,7 @@ update, you could write a test similar to this::
 
     def test_update_result(self):
         obj = MyModel.objects.create(val=1)
-        MyModel.objects.filter(pk=obj.pk).update(val=F('val') + 1)
+        MyModel.objects.filter(pk=obj.pk).update(val=F("val") + 1)
         # At this point obj.val is still 1, but the value in the database
         # was updated to 2. The object's updated value needs to be reloaded
         # from the database.
@@ -251,6 +258,7 @@ when you want to run one-step model validation for your own manually created
 models. For example::
 
     from django.core.exceptions import ValidationError
+
     try:
         article.full_clean()
     except ValidationError as e:
@@ -282,14 +290,16 @@ access to more than a single field::
     from django.db import models
     from django.utils.translation import gettext_lazy as _
 
+
     class Article(models.Model):
         ...
+
         def clean(self):
             # Don't allow draft entries to have a pub_date.
-            if self.status == 'draft' and self.pub_date is not None:
-                raise ValidationError(_('Draft entries may not have a publication date.'))
+            if self.status == "draft" and self.pub_date is not None:
+                raise ValidationError(_("Draft entries may not have a publication date."))
             # Set the pub_date for published items if it hasn't been set already.
-            if self.status == 'published' and self.pub_date is None:
+            if self.status == "published" and self.pub_date is None:
                 self.pub_date = datetime.date.today()
 
 Note, however, that like :meth:`Model.full_clean()`, a model's ``clean()``
@@ -302,6 +312,7 @@ will be stored in a special error dictionary key,
 that are tied to the entire model instead of to a specific field::
 
     from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
+
     try:
         article.full_clean()
     except ValidationError as e:
@@ -314,19 +325,24 @@ error to the ``pub_date`` field::
 
     class Article(models.Model):
         ...
+
         def clean(self):
             # Don't allow draft entries to have a pub_date.
-            if self.status == 'draft' and self.pub_date is not None:
-                raise ValidationError({'pub_date': _('Draft entries may not have a publication date.')})
+            if self.status == "draft" and self.pub_date is not None:
+                raise ValidationError(
+                    {"pub_date": _("Draft entries may not have a publication date.")}
+                )
             ...
 
 If you detect errors in multiple fields during ``Model.clean()``, you can also
 pass a dictionary mapping field names to errors::
 
-    raise ValidationError({
-        'title': ValidationError(_('Missing title.'), code='required'),
-        'pub_date': ValidationError(_('Invalid date.'), code='invalid'),
-    })
+    raise ValidationError(
+        {
+            "title": ValidationError(_("Missing title."), code="required"),
+            "pub_date": ValidationError(_("Invalid date."), code="invalid"),
+        }
+    )
 
 Then, ``full_clean()`` will check unique constraints on your model.
 
@@ -344,20 +360,22 @@ Then, ``full_clean()`` will check unique constraints on your model.
 
         class Article(models.Model):
             ...
+
             def clean_fields(self, exclude=None):
                 super().clean_fields(exclude=exclude)
-                if self.status == 'draft' and self.pub_date is not None:
-                    if exclude and 'status' in exclude:
+                if self.status == "draft" and self.pub_date is not None:
+                    if exclude and "status" in exclude:
                         raise ValidationError(
-                            _('Draft entries may not have a publication date.')
+                            _("Draft entries may not have a publication date.")
                         )
                     else:
-                        raise ValidationError({
-                            'status': _(
-                                'Set status to draft if there is not a '
-                                'publication date.'
-                             ),
-                        })
+                        raise ValidationError(
+                            {
+                                "status": _(
+                                    "Set status to draft if there is not a " "publication date."
+                                ),
+                            }
+                        )
 
 .. method:: Model.validate_unique(exclude=None)
 
@@ -421,10 +439,10 @@ an attribute on your object the first time you call ``save()``:
 
 .. code-block:: pycon
 
-    >>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
-    >>> b2.id     # Returns None, because b2 doesn't have an ID yet.
+    >>> b2 = Blog(name="Cheddar Talk", tagline="Thoughts on cheese.")
+    >>> b2.id  # Returns None, because b2 doesn't have an ID yet.
     >>> b2.save()
-    >>> b2.id     # Returns the ID of your new object.
+    >>> b2.id  # Returns the ID of your new object.
 
 There's no way to tell what the value of an ID will be before you call
 ``save()``, because that value is calculated by your database, not by Django.
@@ -455,10 +473,10 @@ rather than relying on the auto-assignment of the ID:
 
 .. code-block:: pycon
 
-    >>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
-    >>> b3.id     # Returns 3.
+    >>> b3 = Blog(id=3, name="Cheddar Talk", tagline="Thoughts on cheese.")
+    >>> b3.id  # Returns 3.
     >>> b3.save()
-    >>> b3.id     # Returns 3.
+    >>> b3.id  # Returns 3.
 
 If you assign auto-primary-key values manually, make sure not to use an
 already-existing primary-key value! If you create a new object with an explicit
@@ -468,7 +486,7 @@ changing the existing record rather than creating a new one.
 Given the above ``'Cheddar Talk'`` blog example, this example would override the
 previous record in the database::
 
-    b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
+    b4 = Blog(id=3, name="Not Cheddar", tagline="Anything but cheese.")
     b4.save()  # Overrides the previous blog with ID=3!
 
 See `How Django knows to UPDATE vs. INSERT`_, below, for the reason this
@@ -583,7 +601,7 @@ doing the arithmetic in Python like:
 
 .. code-block:: pycon
 
-    >>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
+    >>> product = Product.objects.get(name="Venezuelan Beaver Cheese")
     >>> product.number_sold += 1
     >>> product.save()
 
@@ -601,8 +619,8 @@ as:
 .. code-block:: pycon
 
     >>> from django.db.models import F
-    >>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
-    >>> product.number_sold = F('number_sold') + 1
+    >>> product = Product.objects.get(name="Venezuelan Beaver Cheese")
+    >>> product.number_sold = F("number_sold") + 1
     >>> product.save()
 
 For more details, see the documentation on :class:`F expressions
@@ -620,8 +638,8 @@ This may be desirable if you want to update just one or a few fields on
 an object. There will be a slight performance benefit from preventing
 all of the model fields from being updated in the database. For example::
 
-    product.name = 'Name changed again'
-    product.save(update_fields=['name'])
+    product.name = "Name changed again"
+    product.save(update_fields=["name"])
 
 The ``update_fields`` argument can be any iterable containing strings. An
 empty ``update_fields`` iterable will skip the save. A value of ``None`` will
@@ -714,12 +732,13 @@ For example::
 
     from django.db import models
 
+
     class Person(models.Model):
         first_name = models.CharField(max_length=50)
         last_name = models.CharField(max_length=50)
 
         def __str__(self):
-            return f'{self.first_name} {self.last_name}'
+            return f"{self.first_name} {self.last_name}"
 
 ``__eq__()``
 ------------
@@ -736,16 +755,20 @@ For example::
 
     from django.db import models
 
+
     class MyModel(models.Model):
         id = models.AutoField(primary_key=True)
 
+
     class MyProxyModel(MyModel):
         class Meta:
             proxy = True
 
+
     class MultitableInherited(MyModel):
         pass
 
+
     # Primary keys compared
     MyModel(id=1) == MyModel(id=1)
     MyModel(id=1) != MyModel(id=2)
@@ -793,7 +816,8 @@ For example::
 
     def get_absolute_url(self):
         from django.urls import reverse
-        return reverse('people-detail', kwargs={'pk' : self.pk})
+
+        return reverse("people-detail", kwargs={"pk": self.pk})
 
 One place Django uses ``get_absolute_url()`` is in the admin app. If an object
 defines this method, the object-editing page will have a "View on site" link
@@ -811,7 +835,7 @@ URL, you should define ``get_absolute_url()``.
     reduce possibilities of link or redirect poisoning::
 
         def get_absolute_url(self):
-            return '/%s/' % self.name
+            return "/%s/" % self.name
 
     If ``self.name`` is ``'/example.com'`` this returns ``'//example.com/'``
     which, in turn, is a valid schema relative URL but not the expected
@@ -863,11 +887,12 @@ For example::
 
     from django.db import models
 
+
     class Person(models.Model):
         SHIRT_SIZES = [
-            ('S', 'Small'),
-            ('M', 'Medium'),
-            ('L', 'Large'),
+            ("S", "Small"),
+            ("M", "Medium"),
+            ("L", "Large"),
         ]
         name = models.CharField(max_length=60)
         shirt_size = models.CharField(max_length=2, choices=SHIRT_SIZES)

Some files were not shown because too many files changed in this diff