diff options
| author | django-bot <ops@djangoproject.com> | 2023-03-01 13:35:43 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-03-01 13:39:03 +0100 |
| commit | 62510f01e76ad0526c94ea6d1bc6399c1ddf3df4 (patch) | |
| tree | 79844be246eba809a4ca09c6f4c3448f2276321a /docs/ref/models | |
| parent | 32f224e359c68e70e3f9a230be0265dcd6677079 (diff) | |
[4.2.x] Fixed #34140 -- Reformatted code blocks in docs with blacken-docs.
Diffstat (limited to 'docs/ref/models')
| -rw-r--r-- | docs/ref/models/class.txt | 1 | ||||
| -rw-r--r-- | docs/ref/models/conditional-expressions.txt | 120 | ||||
| -rw-r--r-- | docs/ref/models/constraints.txt | 16 | ||||
| -rw-r--r-- | docs/ref/models/database-functions.txt | 416 | ||||
| -rw-r--r-- | docs/ref/models/expressions.txt | 187 | ||||
| -rw-r--r-- | docs/ref/models/fields.txt | 158 | ||||
| -rw-r--r-- | docs/ref/models/indexes.txt | 6 | ||||
| -rw-r--r-- | docs/ref/models/instances.txt | 101 | ||||
| -rw-r--r-- | docs/ref/models/lookups.txt | 6 | ||||
| -rw-r--r-- | docs/ref/models/meta.txt | 6 | ||||
| -rw-r--r-- | docs/ref/models/options.txt | 34 | ||||
| -rw-r--r-- | docs/ref/models/querysets.txt | 364 | ||||
| -rw-r--r-- | docs/ref/models/relations.txt | 18 |
13 files changed, 793 insertions, 640 deletions
diff --git a/docs/ref/models/class.txt b/docs/ref/models/class.txt index 81414973a9..c0ccb6caff 100644 --- a/docs/ref/models/class.txt +++ b/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() diff --git a/docs/ref/models/conditional-expressions.txt b/docs/ref/models/conditional-expressions.txt index 8dd477a187..d14312870f 100644 --- a/docs/ref/models/conditional-expressions.txt +++ b/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: diff --git a/docs/ref/models/constraints.txt b/docs/ref/models/constraints.txt index c8a3eac013..7a71530742 100644 --- a/docs/ref/models/constraints.txt +++ b/docs/ref/models/constraints.txt @@ -120,7 +120,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") .. versionchanged:: 4.1 @@ -143,7 +143,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. @@ -173,7 +173,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. @@ -191,8 +191,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, ) @@ -222,7 +222,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. @@ -244,7 +244,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``. diff --git a/docs/ref/models/database-functions.txt b/docs/ref/models/database-functions.txt index 765a988d08..9a3f17325c 100644 --- a/docs/ref/models/database-functions.txt +++ b/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} @@ -602,16 +643,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) @@ -663,22 +708,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 @@ -737,19 +786,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')), @@ -798,22 +851,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 @@ -842,7 +903,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) @@ -870,7 +931,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) @@ -898,7 +959,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) @@ -925,7 +986,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) @@ -952,7 +1013,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 @@ -970,7 +1031,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) @@ -997,7 +1058,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) @@ -1024,7 +1085,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) @@ -1051,7 +1112,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) @@ -1079,7 +1140,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) @@ -1107,7 +1168,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) @@ -1134,7 +1195,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) @@ -1162,7 +1223,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 @@ -1180,7 +1241,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 @@ -1205,7 +1266,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 @@ -1222,7 +1283,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) @@ -1258,7 +1319,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) @@ -1285,7 +1346,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) @@ -1312,7 +1373,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) @@ -1339,7 +1400,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) @@ -1366,7 +1427,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) @@ -1402,8 +1463,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 @@ -1430,12 +1491,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) @@ -1452,8 +1510,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 @@ -1471,10 +1529,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) @@ -1503,8 +1561,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 @@ -1523,10 +1581,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`` @@ -1552,8 +1610,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 @@ -1575,8 +1633,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 @@ -1593,10 +1651,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`` @@ -1614,11 +1672,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`` @@ -1637,8 +1695,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 @@ -1654,8 +1712,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 @@ -1694,8 +1752,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 @@ -1725,16 +1783,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:: @@ -1759,10 +1817,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`` @@ -1778,10 +1836,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`` @@ -1799,8 +1857,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 diff --git a/docs/ref/models/expressions.txt b/docs/ref/models/expressions.txt index d2f2d0e8b9..a21b2e3ca8 100644 --- a/docs/ref/models/expressions.txt +++ b/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. @@ -818,9 +821,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", ... ), ... ) @@ -837,18 +840,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, ... ), ... ) @@ -864,13 +870,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. @@ -950,9 +952,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), ... ), ... ) @@ -968,9 +970,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), ... ), ... ) @@ -1054,7 +1056,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) @@ -1157,17 +1159,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 @@ -1178,11 +1181,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:: @@ -1194,15 +1201,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. @@ -1227,6 +1235,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 @@ -1236,12 +1245,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)) ... @@ -1265,8 +1273,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): @@ -1280,8 +1289,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) @@ -1303,8 +1312,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 diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt index c449a1381c..c1267507b2 100644 --- a/docs/ref/models/fields.txt +++ b/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 diff --git a/docs/ref/models/indexes.txt b/docs/ref/models/indexes.txt index c6633d6998..c82f710be0 100644 --- a/docs/ref/models/indexes.txt +++ b/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. diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt index dc73267427..8d2aa637f2 100644 --- a/docs/ref/models/instances.txt +++ b/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. @@ -256,6 +263,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: @@ -295,14 +303,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()`` @@ -315,6 +325,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: @@ -327,19 +338,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. @@ -357,20 +373,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) @@ -441,10 +459,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. @@ -475,10 +493,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 @@ -488,7 +506,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 @@ -603,7 +621,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() @@ -621,8 +639,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 @@ -640,8 +658,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 @@ -734,12 +752,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__()`` ------------ @@ -756,16 +775,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) @@ -813,7 +836,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 @@ -831,7 +855,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 @@ -883,11 +907,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) diff --git a/docs/ref/models/lookups.txt b/docs/ref/models/lookups.txt index d71424c906..3998eb3705 100644 --- a/docs/ref/models/lookups.txt +++ b/docs/ref/models/lookups.txt @@ -47,7 +47,7 @@ register lookups on itself or its instances. The two prominent examples are Registers a new lookup in the class or class instance. For example:: DateField.register_lookup(YearExact) - User._meta.get_field('date_joined').register_lookup(MonthExact) + User._meta.get_field("date_joined").register_lookup(MonthExact) will register ``YearExact`` lookup on ``DateField`` and ``MonthExact`` lookup on the ``User.date_joined`` (you can use :ref:`Field Access API @@ -195,11 +195,11 @@ following methods: ``<lhs>__<lookup_name>=<rhs>``. Lookups can also be used directly in ``QuerySet`` filters:: - Book.objects.filter(LessThan(F('word_count'), 7500)) + Book.objects.filter(LessThan(F("word_count"), 7500)) …or annotations:: - Book.objects.annotate(is_short_story=LessThan(F('word_count'), 7500)) + Book.objects.annotate(is_short_story=LessThan(F("word_count"), 7500)) .. attribute:: lhs diff --git a/docs/ref/models/meta.txt b/docs/ref/models/meta.txt index 251705d84e..a96c563d49 100644 --- a/docs/ref/models/meta.txt +++ b/docs/ref/models/meta.txt @@ -49,15 +49,15 @@ Retrieving a single field instance of a model by name >>> from django.contrib.auth.models import User # A field on the model - >>> User._meta.get_field('username') + >>> User._meta.get_field("username") <django.db.models.fields.CharField: username> # A field from another model that has a relation with the current model - >>> User._meta.get_field('logentry') + >>> User._meta.get_field("logentry") <ManyToOneRel: admin.logentry> # A non existent field - >>> User._meta.get_field('does_not_exist') + >>> User._meta.get_field("does_not_exist") Traceback (most recent call last): ... FieldDoesNotExist: User has no field named 'does_not_exist' diff --git a/docs/ref/models/options.txt b/docs/ref/models/options.txt index 4426e8bfcd..06bf09fba0 100644 --- a/docs/ref/models/options.txt +++ b/docs/ref/models/options.txt @@ -27,7 +27,7 @@ Available ``Meta`` options If a model is defined outside of an application in :setting:`INSTALLED_APPS`, it must declare which app it belongs to:: - app_label = 'myapp' + app_label = "myapp" If you want to represent a model with the format ``app_label.object_name`` or ``app_label.model_name`` you can use ``model._meta.label`` @@ -48,7 +48,7 @@ Available ``Meta`` options The name of the database table to use for the model:: - db_table = 'music_album' + db_table = "music_album" .. _table-names: @@ -161,7 +161,7 @@ not be looking at your Django code. For example:: get_latest_by = "order_date" # Latest by priority descending, order_date ascending. - get_latest_by = ['-priority', 'order_date'] + get_latest_by = ["-priority", "order_date"] See the :meth:`~django.db.models.query.QuerySet.latest` docs for more. @@ -218,16 +218,18 @@ not be looking at your Django code. For example:: from django.db import models + class Question(models.Model): text = models.TextField() # ... + class Answer(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE) # ... class Meta: - order_with_respect_to = 'question' + order_with_respect_to = "question" When ``order_with_respect_to`` is set, two additional methods are provided to retrieve and to set the order of the related objects: ``get_RELATED_order()`` @@ -283,7 +285,7 @@ not be looking at your Django code. For example:: The default ordering for the object, for use when obtaining lists of objects:: - ordering = ['-order_date'] + ordering = ["-order_date"] This is a tuple or list of strings and/or query expressions. Each string is a field name with an optional "-" prefix, which indicates descending order. @@ -292,22 +294,22 @@ not be looking at your Django code. For example:: For example, to order by a ``pub_date`` field ascending, use this:: - ordering = ['pub_date'] + ordering = ["pub_date"] To order by ``pub_date`` descending, use this:: - ordering = ['-pub_date'] + ordering = ["-pub_date"] To order by ``pub_date`` descending, then by ``author`` ascending, use this:: - ordering = ['-pub_date', 'author'] + ordering = ["-pub_date", "author"] You can also use :doc:`query expressions </ref/models/expressions>`. To order by ``author`` ascending and make null values sort last, use this:: from django.db.models import F - ordering = [F('author').asc(nulls_last=True)] + ordering = [F("author").asc(nulls_last=True)] .. warning:: @@ -330,7 +332,7 @@ not be looking at your Django code. For example:: Add, change, delete, and view permissions are automatically created for each model. This example specifies an extra permission, ``can_deliver_pizzas``:: - permissions = [('can_deliver_pizzas', 'Can deliver pizzas')] + permissions = [("can_deliver_pizzas", "Can deliver pizzas")] This is a list or tuple of 2-tuples in the format ``(permission_code, human_readable_permission_name)``. @@ -406,14 +408,15 @@ not be looking at your Django code. For example:: from django.db import models + class Customer(models.Model): first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) class Meta: indexes = [ - models.Index(fields=['last_name', 'first_name']), - models.Index(fields=['first_name'], name='first_name_idx'), + models.Index(fields=["last_name", "first_name"]), + models.Index(fields=["first_name"], name="first_name_idx"), ] ``unique_together`` @@ -429,7 +432,7 @@ not be looking at your Django code. For example:: Sets of field names that, taken together, must be unique:: - unique_together = [['driver', 'restaurant']] + unique_together = [["driver", "restaurant"]] This is a list of lists that must be unique when considered together. It's used in the Django admin and is enforced at the database level (i.e., the @@ -439,7 +442,7 @@ not be looking at your Django code. For example:: For convenience, ``unique_together`` can be a single list when dealing with a single set of fields:: - unique_together = ['driver', 'restaurant'] + unique_together = ["driver", "restaurant"] A :class:`~django.db.models.ManyToManyField` cannot be included in unique_together. (It's not clear what that would even mean!) If you @@ -483,12 +486,13 @@ not be looking at your Django code. For example:: from django.db import models + class Customer(models.Model): age = models.IntegerField() class Meta: constraints = [ - models.CheckConstraint(check=models.Q(age__gte=18), name='age_gte_18'), + models.CheckConstraint(check=models.Q(age__gte=18), name="age_gte_18"), ] ``verbose_name`` diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index 54797d363b..38364559b2 100644 --- a/docs/ref/models/querysets.txt +++ b/docs/ref/models/querysets.txt @@ -38,7 +38,7 @@ You can evaluate a ``QuerySet`` in the following ways: ``async for``:: async for e in Entry.objects.all(): - results.append(e) + results.append(e) Both synchronous and asynchronous iterators of QuerySets share the same underlying cache. @@ -86,7 +86,7 @@ You can evaluate a ``QuerySet`` in the following ways: ``True``, otherwise ``False``. For example:: if Entry.objects.filter(headline="Test"): - print("There is at least one Entry with the headline Test") + print("There is at least one Entry with the headline Test") Note: If you only want to determine if at least one result exists (and don't need the actual objects), it's more efficient to use :meth:`~QuerySet.exists`. @@ -112,9 +112,9 @@ any results loaded) using some code like this: .. code-block:: pycon >>> import pickle - >>> query = pickle.loads(s) # Assuming 's' is the pickled string. + >>> query = pickle.loads(s) # Assuming 's' is the pickled string. >>> qs = MyModel.objects.all() - >>> qs.query = query # Restore the original 'query'. + >>> qs.query = query # Restore the original 'query'. The ``query`` attribute is an opaque object. It represents the internals of the query construction and is not part of the public API. However, it is safe @@ -129,7 +129,7 @@ described here. .. code-block:: pycon >>> import pickle - >>> qs = Blog.objects.values_list('id', 'name') + >>> qs = Blog.objects.values_list("id", "name") >>> qs <QuerySet [(1, 'Beatles Blog')]> >>> reloaded_qs = Blog.objects.all() @@ -229,7 +229,7 @@ underlying SQL statement, and the whole thing is enclosed in a ``NOT()``. This example excludes all entries whose ``pub_date`` is later than 2005-1-3 AND whose ``headline`` is "Hello":: - Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello') + Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline="Hello") In SQL terms, that evaluates to: @@ -241,7 +241,7 @@ In SQL terms, that evaluates to: This example excludes all entries whose ``pub_date`` is later than 2005-1-3 OR whose headline is "Hello":: - Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello') + Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline="Hello") In SQL terms, that evaluates to: @@ -286,7 +286,7 @@ to determine how many entries have been made in each blog: .. code-block:: pycon >>> from django.db.models import Count - >>> q = Blog.objects.annotate(Count('entry')) + >>> q = Blog.objects.annotate(Count("entry")) # The name of the first blog >>> q[0].name 'Blogasaurus' @@ -300,7 +300,7 @@ control the name of the annotation: .. code-block:: pycon - >>> q = Blog.objects.annotate(number_of_entries=Count('entry')) + >>> q = Blog.objects.annotate(number_of_entries=Count("entry")) # The number of entries on the first blog, using the name provided >>> q[0].number_of_entries 42 @@ -326,16 +326,16 @@ interested in the exact number of entries, you could do this: .. code-block:: pycon >>> from django.db.models import Count - >>> blogs = Blog.objects.alias(entries=Count('entry')).filter(entries__gt=5) + >>> blogs = Blog.objects.alias(entries=Count("entry")).filter(entries__gt=5) ``alias()`` can be used in conjunction with :meth:`annotate`, :meth:`exclude`, :meth:`filter`, :meth:`order_by`, and :meth:`update`. To use aliased expression with other methods (e.g. :meth:`aggregate`), you must promote it to an annotation:: - Blog.objects.alias(entries=Count('entry')).annotate( - entries=F('entries'), - ).aggregate(Sum('entries')) + Blog.objects.alias(entries=Count("entry")).annotate( + entries=F("entries"), + ).aggregate(Sum("entries")) :meth:`filter` and :meth:`order_by` can take expressions directly, but expression construction and usage often does not happen in the same place (for @@ -355,14 +355,14 @@ override this on a per-``QuerySet`` basis by using the ``order_by`` method. Example:: - Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline') + Entry.objects.filter(pub_date__year=2005).order_by("-pub_date", "headline") The result above will be ordered by ``pub_date`` descending, then by ``headline`` ascending. The negative sign in front of ``"-pub_date"`` indicates *descending* order. Ascending order is implied. To order randomly, use ``"?"``, like so:: - Entry.objects.order_by('?') + Entry.objects.order_by("?") Note: ``order_by('?')`` queries may be expensive and slow, depending on the database backend you're using. @@ -372,7 +372,7 @@ querying across model relations. That is, the name of the field, followed by a double underscore (``__``), followed by the name of the field in the new model, and so on for as many models as you want to join. For example:: - Entry.objects.order_by('blog__name', 'headline') + Entry.objects.order_by("blog__name", "headline") If you try to order by a field that is a relation to another model, Django will use the default ordering on the related model, or order by the related model's @@ -380,22 +380,22 @@ primary key if there is no :attr:`Meta.ordering <django.db.models.Options.ordering>` specified. For example, since the ``Blog`` model has no default ordering specified:: - Entry.objects.order_by('blog') + Entry.objects.order_by("blog") ...is identical to:: - Entry.objects.order_by('blog__id') + Entry.objects.order_by("blog__id") If ``Blog`` had ``ordering = ['name']``, then the first queryset would be identical to:: - Entry.objects.order_by('blog__name') + Entry.objects.order_by("blog__name") You can also order by :doc:`query expressions </ref/models/expressions>` by calling :meth:`~.Expression.asc` or :meth:`~.Expression.desc` on the expression:: - Entry.objects.order_by(Coalesce('summary', 'headline').desc()) + Entry.objects.order_by(Coalesce("summary", "headline").desc()) :meth:`~.Expression.asc` and :meth:`~.Expression.desc` have arguments (``nulls_first`` and ``nulls_last``) that control how null values are sorted. @@ -412,14 +412,15 @@ related model ordering can change the expected results. Consider this case:: class Event(Model): - parent = models.ForeignKey( - 'self', - on_delete=models.CASCADE, - related_name='children', - ) - date = models.DateField() + parent = models.ForeignKey( + "self", + on_delete=models.CASCADE, + related_name="children", + ) + date = models.DateField() + - Event.objects.order_by('children__date') + Event.objects.order_by("children__date") Here, there could potentially be multiple ordering data for each ``Event``; each ``Event`` with multiple ``children`` will be returned multiple times @@ -441,7 +442,7 @@ You can order by a field converted to lowercase with :class:`~django.db.models.functions.Lower` which will achieve case-consistent ordering:: - Entry.objects.order_by(Lower('headline').desc()) + Entry.objects.order_by(Lower("headline").desc()) If you don't want any ordering to be applied to a query, not even the default ordering, call :meth:`order_by()` with no parameters. @@ -453,7 +454,7 @@ You can tell if a query is ordered or not by checking the Each ``order_by()`` call will clear any previous ordering. For example, this query will be ordered by ``pub_date`` and not ``headline``:: - Entry.objects.order_by('headline').order_by('pub_date') + Entry.objects.order_by("headline").order_by("pub_date") .. warning:: @@ -549,19 +550,19 @@ Examples (those after the first will only work on PostgreSQL): >>> Author.objects.distinct() [...] - >>> Entry.objects.order_by('pub_date').distinct('pub_date') + >>> Entry.objects.order_by("pub_date").distinct("pub_date") [...] - >>> Entry.objects.order_by('blog').distinct('blog') + >>> Entry.objects.order_by("blog").distinct("blog") [...] - >>> Entry.objects.order_by('author', 'pub_date').distinct('author', 'pub_date') + >>> Entry.objects.order_by("author", "pub_date").distinct("author", "pub_date") [...] - >>> Entry.objects.order_by('blog__name', 'mod_date').distinct('blog__name', 'mod_date') + >>> Entry.objects.order_by("blog__name", "mod_date").distinct("blog__name", "mod_date") [...] - >>> Entry.objects.order_by('author', 'pub_date').distinct('author') + >>> Entry.objects.order_by("author", "pub_date").distinct("author") [...] .. note:: @@ -572,7 +573,7 @@ Examples (those after the first will only work on PostgreSQL): the ``Blog`` model defined an :attr:`~django.db.models.Options.ordering` by ``name``:: - Entry.objects.order_by('blog').distinct('blog') + Entry.objects.order_by("blog").distinct("blog") ...wouldn't work because the query would be ordered by ``blog__name`` thus mismatching the ``DISTINCT ON`` expression. You'd have to explicitly order @@ -596,11 +597,11 @@ objects: .. code-block:: pycon # This list contains a Blog object. - >>> Blog.objects.filter(name__startswith='Beatles') + >>> Blog.objects.filter(name__startswith="Beatles") <QuerySet [<Blog: Beatles Blog>]> # This list contains a dictionary. - >>> Blog.objects.filter(name__startswith='Beatles').values() + >>> Blog.objects.filter(name__startswith="Beatles").values() <QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]> The ``values()`` method takes optional positional arguments, ``*fields``, which @@ -615,7 +616,7 @@ Example: >>> Blog.objects.values() <QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]> - >>> Blog.objects.values('id', 'name') + >>> Blog.objects.values("id", "name") <QuerySet [{'id': 1, 'name': 'Beatles Blog'}]> The ``values()`` method also takes optional keyword arguments, @@ -624,7 +625,7 @@ The ``values()`` method also takes optional keyword arguments, .. code-block:: pycon >>> from django.db.models.functions import Lower - >>> Blog.objects.values(lower_name=Lower('name')) + >>> Blog.objects.values(lower_name=Lower("name")) <QuerySet [{'lower_name': 'beatles blog'}]> You can use built-in and :doc:`custom lookups </howto/custom-lookups>` in @@ -635,7 +636,7 @@ ordering. For example: >>> from django.db.models import CharField >>> from django.db.models.functions import Lower >>> CharField.register_lookup(Lower) - >>> Blog.objects.values('name__lower') + >>> Blog.objects.values("name__lower") <QuerySet [{'name__lower': 'beatles blog'}]> An aggregate within a ``values()`` clause is applied before other arguments @@ -645,9 +646,9 @@ add it to an earlier ``values()`` clause instead. For example: .. code-block:: pycon >>> from django.db.models import Count - >>> Blog.objects.values('entry__authors', entries=Count('entry')) + >>> Blog.objects.values("entry__authors", entries=Count("entry")) <QuerySet [{'entry__authors': 1, 'entries': 20}, {'entry__authors': 1, 'entries': 13}]> - >>> Blog.objects.values('entry__authors').annotate(entries=Count('entry')) + >>> Blog.objects.values("entry__authors").annotate(entries=Count("entry")) <QuerySet [{'entry__authors': 1, 'entries': 33}]> A few subtleties that are worth mentioning: @@ -668,10 +669,10 @@ A few subtleties that are worth mentioning: >>> Entry.objects.values() <QuerySet [{'blog_id': 1, 'headline': 'First Entry', ...}, ...]> - >>> Entry.objects.values('blog') + >>> Entry.objects.values("blog") <QuerySet [{'blog': 1}, ...]> - >>> Entry.objects.values('blog_id') + >>> Entry.objects.values("blog_id") <QuerySet [{'blog_id': 1}, ...]> * When using ``values()`` together with :meth:`distinct()`, be aware that @@ -697,15 +698,15 @@ A few subtleties that are worth mentioning: >>> from django.db.models import CharField, Count >>> from django.db.models.functions import Lower >>> CharField.register_lookup(Lower) - >>> Blog.objects.values('entry__authors__name__lower').annotate(entries=Count('entry')) + >>> Blog.objects.values("entry__authors__name__lower").annotate(entries=Count("entry")) <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]> - >>> Blog.objects.values( - ... entry__authors__name__lower=Lower('entry__authors__name') - ... ).annotate(entries=Count('entry')) + >>> Blog.objects.values(entry__authors__name__lower=Lower("entry__authors__name")).annotate( + ... entries=Count("entry") + ... ) <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]> - >>> Blog.objects.annotate( - ... entry__authors__name__lower=Lower('entry__authors__name') - ... ).values('entry__authors__name__lower').annotate(entries=Count('entry')) + >>> Blog.objects.annotate(entry__authors__name__lower=Lower("entry__authors__name")).values( + ... "entry__authors__name__lower" + ... ).annotate(entries=Count("entry")) <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]> It is useful when you know you're only going to need values from a small number @@ -715,8 +716,8 @@ instance object. It's more efficient to select only the fields you need to use. Finally, note that you can call ``filter()``, ``order_by()``, etc. after the ``values()`` call, that means that these two calls are identical:: - Blog.objects.values().order_by('id') - Blog.objects.order_by('id').values() + Blog.objects.values().order_by("id") + Blog.objects.order_by("id").values() The people who made Django prefer to put all the SQL-affecting methods first, followed (optionally) by any output-affecting methods (such as ``values()``), @@ -728,7 +729,7 @@ You can also refer to fields on related models with reverse relations through .. code-block:: pycon - >>> Blog.objects.values('name', 'entry__headline') + >>> Blog.objects.values("name", "entry__headline") <QuerySet [{'name': 'My blog', 'entry__headline': 'An entry'}, {'name': 'My blog', 'entry__headline': 'Another entry'}, ...]> @@ -760,10 +761,10 @@ first item is the first field, etc. For example: .. code-block:: pycon - >>> Entry.objects.values_list('id', 'headline') + >>> Entry.objects.values_list("id", "headline") <QuerySet [(1, 'First entry'), ...]> >>> from django.db.models.functions import Lower - >>> Entry.objects.values_list('id', Lower('headline')) + >>> Entry.objects.values_list("id", Lower("headline")) <QuerySet [(1, 'first entry'), ...]> If you only pass in a single field, you can also pass in the ``flat`` @@ -772,10 +773,10 @@ rather than one-tuples. An example should make the difference clearer: .. code-block:: pycon - >>> Entry.objects.values_list('id').order_by('id') + >>> Entry.objects.values_list("id").order_by("id") <QuerySet[(1,), (2,), (3,), ...]> - >>> Entry.objects.values_list('id', flat=True).order_by('id') + >>> Entry.objects.values_list("id", flat=True).order_by("id") <QuerySet [1, 2, 3, ...]> It is an error to pass in ``flat`` when there is more than one field. @@ -785,7 +786,7 @@ You can pass ``named=True`` to get results as a .. code-block:: pycon - >>> Entry.objects.values_list('id', 'headline', named=True) + >>> Entry.objects.values_list("id", "headline", named=True) <QuerySet [Row(id=1, headline='First entry'), ...]> Using a named tuple may make use of the results more readable, at the expense @@ -799,7 +800,7 @@ achieve that, use ``values_list()`` followed by a ``get()`` call: .. code-block:: pycon - >>> Entry.objects.values_list('headline', flat=True).get(pk=1) + >>> Entry.objects.values_list("headline", flat=True).get(pk=1) 'First entry' ``values()`` and ``values_list()`` are both intended as optimizations for a @@ -813,7 +814,7 @@ For example, notice the behavior when querying across a .. code-block:: pycon - >>> Author.objects.values_list('name', 'entry__headline') + >>> Author.objects.values_list("name", "entry__headline") <QuerySet [('Noam Chomsky', 'Impressions of Gaza'), ('George Orwell', 'Why Socialists Do Not Believe in Fun'), ('George Orwell', 'In Defence of English Cooking'), @@ -827,7 +828,7 @@ not having any author: .. code-block:: pycon - >>> Entry.objects.values_list('authors') + >>> Entry.objects.values_list("authors") <QuerySet [('Noam Chomsky',), ('George Orwell',), (None,)]> .. admonition:: Special values for ``JSONField`` on SQLite @@ -867,17 +868,17 @@ Examples: .. code-block:: pycon - >>> Entry.objects.dates('pub_date', 'year') + >>> Entry.objects.dates("pub_date", "year") [datetime.date(2005, 1, 1)] - >>> Entry.objects.dates('pub_date', 'month') + >>> Entry.objects.dates("pub_date", "month") [datetime.date(2005, 2, 1), datetime.date(2005, 3, 1)] - >>> Entry.objects.dates('pub_date', 'week') + >>> Entry.objects.dates("pub_date", "week") [datetime.date(2005, 2, 14), datetime.date(2005, 3, 14)] - >>> Entry.objects.dates('pub_date', 'day') + >>> Entry.objects.dates("pub_date", "day") [datetime.date(2005, 2, 20), datetime.date(2005, 3, 20)] - >>> Entry.objects.dates('pub_date', 'day', order='DESC') + >>> Entry.objects.dates("pub_date", "day", order="DESC") [datetime.date(2005, 3, 20), datetime.date(2005, 2, 20)] - >>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day') + >>> Entry.objects.filter(headline__contains="Lennon").dates("pub_date", "day") [datetime.date(2005, 3, 20)] ``datetimes()`` @@ -989,9 +990,9 @@ resulting ``QuerySet``. For example: .. code-block:: pycon - >>> qs1 = Author.objects.values_list('name') - >>> qs2 = Entry.objects.values_list('headline') - >>> qs1.union(qs2).order_by('name') + >>> qs1 = Author.objects.values_list("name") + >>> qs2 = Entry.objects.values_list("headline") + >>> qs1.union(qs2).order_by("name") In addition, only ``LIMIT``, ``OFFSET``, ``COUNT(*)``, ``ORDER BY``, and specifying columns (i.e. slicing, :meth:`count`, :meth:`exists`, @@ -1048,7 +1049,7 @@ The following examples illustrate the difference between plain lookups and And here's ``select_related`` lookup:: # Hits the database. - e = Entry.objects.select_related('blog').get(id=5) + e = Entry.objects.select_related("blog").get(id=5) # Doesn't hit the database, because e.blog has been prepopulated # in the previous query. @@ -1061,7 +1062,7 @@ You can use ``select_related()`` with any queryset of objects:: # Find all the blogs with entries scheduled to be published in the future. blogs = set() - for e in Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog'): + for e in Entry.objects.filter(pub_date__gt=timezone.now()).select_related("blog"): # Without select_related(), this would make a database query for each # loop iteration in order to fetch the related blog for each entry. blogs.add(e.blog) @@ -1069,18 +1070,20 @@ You can use ``select_related()`` with any queryset of objects:: The order of ``filter()`` and ``select_related()`` chaining isn't important. These querysets are equivalent:: - Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog') - Entry.objects.select_related('blog').filter(pub_date__gt=timezone.now()) + Entry.objects.filter(pub_date__gt=timezone.now()).select_related("blog") + Entry.objects.select_related("blog").filter(pub_date__gt=timezone.now()) You can follow foreign keys in a similar way to querying them. If you have the following models:: from django.db import models + class City(models.Model): # ... pass + class Person(models.Model): # ... hometown = models.ForeignKey( @@ -1090,6 +1093,7 @@ following models:: null=True, ) + class Book(models.Model): # ... author = models.ForeignKey(Person, on_delete=models.CASCADE) @@ -1098,14 +1102,14 @@ following models:: will cache the related ``Person`` *and* the related ``City``:: # Hits the database with joins to the author and hometown tables. - b = Book.objects.select_related('author__hometown').get(id=4) - p = b.author # Doesn't hit the database. - c = p.hometown # Doesn't hit the database. + b = Book.objects.select_related("author__hometown").get(id=4) + p = b.author # Doesn't hit the database. + c = p.hometown # Doesn't hit the database. # Without select_related()... b = Book.objects.get(id=4) # Hits the database. - p = b.author # Hits the database. - c = p.hometown # Hits the database. + p = b.author # Hits the database. + c = p.hometown # Hits the database. You can refer to any :class:`~django.db.models.ForeignKey` or :class:`~django.db.models.OneToOneField` relation in the list of fields @@ -1170,9 +1174,11 @@ For example, suppose you have these models:: from django.db import models + class Topping(models.Model): name = models.CharField(max_length=30) + class Pizza(models.Model): name = models.CharField(max_length=50) toppings = models.ManyToManyField(Topping) @@ -1250,14 +1256,16 @@ You can also use the normal join syntax to do related fields of related fields. Suppose we have an additional model to the example above:: class Restaurant(models.Model): - pizzas = models.ManyToManyField(Pizza, related_name='restaurants') - best_pizza = models.ForeignKey(Pizza, related_name='championed_by', on_delete=models.CASCADE) + pizzas = models.ManyToManyField(Pizza, related_name="restaurants") + best_pizza = models.ForeignKey( + Pizza, related_name="championed_by", on_delete=models.CASCADE + ) The following are all legal: .. code-block:: pycon - >>> Restaurant.objects.prefetch_related('pizzas__toppings') + >>> Restaurant.objects.prefetch_related("pizzas__toppings") This will prefetch all pizzas belonging to restaurants, and all toppings belonging to those pizzas. This will result in a total of 3 database queries - @@ -1265,7 +1273,7 @@ one for the restaurants, one for the pizzas, and one for the toppings. .. code-block:: pycon - >>> Restaurant.objects.prefetch_related('best_pizza__toppings') + >>> Restaurant.objects.prefetch_related("best_pizza__toppings") This will fetch the best pizza and all the toppings for the best pizza for each restaurant. This will be done in 3 database queries - one for the restaurants, @@ -1276,7 +1284,7 @@ to reduce the query count to 2: .. code-block:: pycon - >>> Restaurant.objects.select_related('best_pizza').prefetch_related('best_pizza__toppings') + >>> Restaurant.objects.select_related("best_pizza").prefetch_related("best_pizza__toppings") Since the prefetch is executed after the main query (which includes the joins needed by ``select_related``), it is able to detect that the ``best_pizza`` @@ -1393,20 +1401,20 @@ database selected by the outer query. All of the following are valid: .. code-block:: pycon >>> # Both inner and outer queries will use the 'replica' database - >>> Restaurant.objects.prefetch_related('pizzas__toppings').using('replica') + >>> Restaurant.objects.prefetch_related("pizzas__toppings").using("replica") >>> Restaurant.objects.prefetch_related( - ... Prefetch('pizzas__toppings'), - ... ).using('replica') + ... Prefetch("pizzas__toppings"), + ... ).using("replica") >>> >>> # Inner will use the 'replica' database; outer will use 'default' database >>> Restaurant.objects.prefetch_related( - ... Prefetch('pizzas__toppings', queryset=Toppings.objects.using('replica')), + ... Prefetch("pizzas__toppings", queryset=Toppings.objects.using("replica")), ... ) >>> >>> # Inner will use 'replica' database; outer will use 'cold-storage' database >>> Restaurant.objects.prefetch_related( - ... Prefetch('pizzas__toppings', queryset=Toppings.objects.using('replica')), - ... ).using('cold-storage') + ... Prefetch("pizzas__toppings", queryset=Toppings.objects.using("replica")), + ... ).using("cold-storage") .. note:: @@ -1463,7 +1471,7 @@ generated by a ``QuerySet``. .. code-block:: pycon >>> qs.extra( - ... select={'val': "select col from sometable where othercol = %s"}, + ... select={"val": "select col from sometable where othercol = %s"}, ... select_params=(someparam,), ... ) @@ -1510,7 +1518,7 @@ of the arguments is required, but you should use at least one of them. Example:: - Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) + Entry.objects.extra(select={"is_recent": "pub_date > '2006-01-01'"}) As a result, each ``Entry`` object will have an extra attribute, ``is_recent``, a boolean representing whether the entry's ``pub_date`` @@ -1531,7 +1539,7 @@ of the arguments is required, but you should use at least one of them. Blog.objects.extra( select={ - 'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id' + "entry_count": "SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id" }, ) @@ -1557,8 +1565,8 @@ of the arguments is required, but you should use at least one of them. This will work, for example:: Blog.objects.extra( - select={'a': '%s', 'b': '%s'}, - select_params=('one', 'two'), + select={"a": "%s", "b": "%s"}, + select_params=("one", "two"), ) If you need to use a literal ``%s`` inside your select string, use @@ -1616,8 +1624,8 @@ of the arguments is required, but you should use at least one of them. For example:: - q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) - q = q.extra(order_by = ['-is_recent']) + q = Entry.objects.extra(select={"is_recent": "pub_date > '2006-01-01'"}) + q = q.extra(order_by=["-is_recent"]) This would sort all the items for which ``is_recent`` is true to the front of the result set (``True`` sorts before ``False`` in a @@ -1635,7 +1643,7 @@ of the arguments is required, but you should use at least one of them. Example:: - Entry.objects.extra(where=['headline=%s'], params=['Lennon']) + Entry.objects.extra(where=["headline=%s"], params=["Lennon"]) Always use ``params`` instead of embedding values directly into ``where`` because ``params`` will ensure values are quoted correctly @@ -1648,7 +1656,7 @@ of the arguments is required, but you should use at least one of them. Good:: - Entry.objects.extra(where=['headline=%s'], params=['Lennon']) + Entry.objects.extra(where=["headline=%s"], params=["Lennon"]) .. warning:: @@ -1743,18 +1751,20 @@ one, doing so will result in an error. class Meta: managed = False - db_table = 'app_largetable' + db_table = "app_largetable" + class ManagedModel(models.Model): f1 = models.CharField(max_length=10) f2 = models.CharField(max_length=10) class Meta: - db_table = 'app_largetable' + db_table = "app_largetable" + # Two equivalent QuerySets: CommonlyUsedModel.objects.all() - ManagedModel.objects.defer('f2') + ManagedModel.objects.defer("f2") If many fields need to be duplicated in the unmanaged model, it may be best to create an abstract model with the shared fields and then have the @@ -1844,7 +1854,7 @@ For example: >>> Entry.objects.all() # queries the database with the 'backup' alias - >>> Entry.objects.using('backup') + >>> Entry.objects.using("backup") ``select_for_update()`` ~~~~~~~~~~~~~~~~~~~~~~~ @@ -1892,7 +1902,7 @@ to refer to the queryset's model. <multi-table-inheritance>`, you must specify parent link fields (by default ``<parent_model_name>_ptr``) in the ``of`` argument. For example:: - Restaurant.objects.select_for_update(of=('self', 'place_ptr')) + Restaurant.objects.select_for_update(of=("self", "place_ptr")) .. admonition:: Using ``select_for_update(of=(...))`` with specified fields @@ -1910,7 +1920,7 @@ You can't use ``select_for_update()`` on nullable relations: .. code-block:: pycon - >>> Person.objects.select_related('hometown').select_for_update() + >>> Person.objects.select_related("hometown").select_for_update() Traceback (most recent call last): ... django.db.utils.NotSupportedError: FOR UPDATE cannot be applied to the nullable side of an outer join @@ -1920,7 +1930,7 @@ them: .. code-block:: pycon - >>> Person.objects.select_related('hometown').select_for_update().exclude(hometown=None) + >>> Person.objects.select_related("hometown").select_for_update().exclude(hometown=None) <QuerySet [<Person: ...)>, ...]> The ``postgresql``, ``oracle``, and ``mysql`` database backends support @@ -1994,6 +2004,7 @@ The following are equivalent:: Model.objects.filter(x=1) & Model.objects.filter(y=2) Model.objects.filter(x=1, y=2) from django.db.models import Q + Model.objects.filter(Q(x=1) & Q(y=2)) SQL equivalent: @@ -2011,6 +2022,7 @@ The following are equivalent:: Model.objects.filter(x=1) | Model.objects.filter(y=2) from django.db.models import Q + Model.objects.filter(Q(x=1) | Q(y=2)) SQL equivalent: @@ -2033,6 +2045,7 @@ The following are equivalent:: Model.objects.filter(x=1) ^ Model.objects.filter(y=2) from django.db.models import Q + Model.objects.filter(Q(x=1) ^ Q(y=2)) SQL equivalent: @@ -2101,13 +2114,13 @@ without any arguments to return the object for that row:: If ``get()`` doesn't find any object, it raises a :exc:`Model.DoesNotExist <django.db.models.Model.DoesNotExist>` exception:: - Entry.objects.get(id=-999) # raises Entry.DoesNotExist + Entry.objects.get(id=-999) # raises Entry.DoesNotExist If ``get()`` finds more than one object, it raises a :exc:`Model.MultipleObjectsReturned <django.db.models.Model.MultipleObjectsReturned>` exception:: - Entry.objects.get(name='A Duplicated Name') # raises Entry.MultipleObjectsReturned + Entry.objects.get(name="A Duplicated Name") # raises Entry.MultipleObjectsReturned Both these exception classes are attributes of the model class, and specific to that model. If you want to handle such exceptions from several ``get()`` calls @@ -2177,9 +2190,9 @@ This is meant to prevent duplicate objects from being created when requests are made in parallel, and as a shortcut to boilerplatish code. For example:: try: - obj = Person.objects.get(first_name='John', last_name='Lennon') + obj = Person.objects.get(first_name="John", last_name="Lennon") except Person.DoesNotExist: - obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9)) + obj = Person(first_name="John", last_name="Lennon", birthday=date(1940, 10, 9)) obj.save() Here, with concurrent requests, multiple attempts to save a ``Person`` with @@ -2187,9 +2200,9 @@ the same parameters may be made. To avoid this race condition, the above example can be rewritten using ``get_or_create()`` like so:: obj, created = Person.objects.get_or_create( - first_name='John', - last_name='Lennon', - defaults={'birthday': date(1940, 10, 9)}, + first_name="John", + last_name="Lennon", + defaults={"birthday": date(1940, 10, 9)}, ) Any keyword arguments passed to ``get_or_create()`` — *except* an optional one @@ -2213,8 +2226,8 @@ exists, and create the latter otherwise:: from django.db.models import Q obj, created = Person.objects.filter( - Q(first_name='Bob') | Q(first_name='Robert'), - ).get_or_create(last_name='Marley', defaults={'first_name': 'Bob'}) + Q(first_name="Bob") | Q(first_name="Robert"), + ).get_or_create(last_name="Marley", defaults={"first_name": "Bob"}) If multiple objects are found, ``get_or_create()`` raises :exc:`~django.core.exceptions.MultipleObjectsReturned`. If an object is *not* @@ -2222,7 +2235,7 @@ found, ``get_or_create()`` will instantiate and save a new object, returning a tuple of the new object and ``True``. The new object will be created roughly according to this algorithm:: - params = {k: v for k, v in kwargs.items() if '__' not in k} + params = {k: v for k, v in kwargs.items() if "__" not in k} params.update({k: v() if callable(v) else v for k, v in defaults.items()}) obj = self.model(**params) obj.save() @@ -2239,7 +2252,7 @@ handles some extra edge-conditions; if you're interested, read the code. If you have a field named ``defaults`` and want to use it as an exact lookup in ``get_or_create()``, use ``'defaults__exact'``, like so:: - Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'}) + Foo.objects.get_or_create(defaults__exact="bar", defaults={"defaults": "baz"}) The ``get_or_create()`` method has similar error behavior to :meth:`create()` when you're using manually specified primary keys. If an object needs to be @@ -2264,6 +2277,7 @@ whenever a request to a page has a side effect on your data. For more, see class Chapter(models.Model): title = models.CharField(max_length=255, unique=True) + class Book(models.Model): title = models.CharField(max_length=256) chapters = models.ManyToManyField(Chapter) @@ -2314,14 +2328,14 @@ the given ``kwargs``. If a match is found, it updates the fields passed in the This is meant as a shortcut to boilerplatish code. For example:: - defaults = {'first_name': 'Bob'} + defaults = {"first_name": "Bob"} try: - obj = Person.objects.get(first_name='John', last_name='Lennon') + obj = Person.objects.get(first_name="John", last_name="Lennon") for key, value in defaults.items(): setattr(obj, key, value) obj.save() except Person.DoesNotExist: - new_values = {'first_name': 'John', 'last_name': 'Lennon'} + new_values = {"first_name": "John", "last_name": "Lennon"} new_values.update(defaults) obj = Person(**new_values) obj.save() @@ -2330,8 +2344,9 @@ This pattern gets quite unwieldy as the number of fields in a model goes up. The above example can be rewritten using ``update_or_create()`` like so:: obj, created = Person.objects.update_or_create( - first_name='John', last_name='Lennon', - defaults={'first_name': 'Bob'}, + first_name="John", + last_name="Lennon", + defaults={"first_name": "Bob"}, ) For a detailed description of how names passed in ``kwargs`` are resolved, see @@ -2368,10 +2383,12 @@ are), and returns created objects as a list, in the same order as provided: .. code-block:: pycon - >>> objs = Entry.objects.bulk_create([ - ... Entry(headline='This is a test'), - ... Entry(headline='This is only a test'), - ... ]) + >>> objs = Entry.objects.bulk_create( + ... [ + ... Entry(headline="This is a test"), + ... Entry(headline="This is only a test"), + ... ] + ... ) This has a number of caveats though: @@ -2392,7 +2409,7 @@ This has a number of caveats though: from itertools import islice batch_size = 100 - objs = (Entry(headline='Test %s' % i) for i in range(1000)) + objs = (Entry(headline="Test %s" % i) for i in range(1000)) while True: batch = list(islice(objs, batch_size)) if not batch: @@ -2451,12 +2468,12 @@ updated: .. code-block:: pycon >>> objs = [ - ... Entry.objects.create(headline='Entry 1'), - ... Entry.objects.create(headline='Entry 2'), + ... Entry.objects.create(headline="Entry 1"), + ... Entry.objects.create(headline="Entry 2"), ... ] - >>> objs[0].headline = 'This is entry 1' - >>> objs[1].headline = 'This is entry 2' - >>> Entry.objects.bulk_update(objs, ['headline']) + >>> objs[0].headline = "This is entry 1" + >>> objs[1].headline = "This is entry 2" + >>> Entry.objects.bulk_update(objs, ["headline"]) 2 :meth:`.QuerySet.update` is used to save the changes, so this is more efficient @@ -2504,7 +2521,7 @@ Example:: Entry.objects.count() # Returns the number of entries whose headline contains 'Lennon' - Entry.objects.filter(headline__contains='Lennon').count() + Entry.objects.filter(headline__contains="Lennon").count() A ``count()`` call performs a ``SELECT COUNT(*)`` behind the scenes, so you should always use ``count()`` rather than loading all of the record into Python @@ -2553,9 +2570,9 @@ Example: {} >>> Blog.objects.in_bulk() {1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>, 3: <Blog: Django Weblog>} - >>> Blog.objects.in_bulk(['beatles_blog'], field_name='slug') + >>> Blog.objects.in_bulk(["beatles_blog"], field_name="slug") {'beatles_blog': <Blog: Beatles Blog>} - >>> Blog.objects.distinct('name').in_bulk(field_name='name') + >>> Blog.objects.distinct("name").in_bulk(field_name="name") {'Beatles Blog': <Blog: Beatles Blog>, 'Cheddar Talk': <Blog: Cheddar Talk>, 'Django Weblog': <Blog: Django Weblog>} If you pass ``in_bulk()`` an empty list, you'll get an empty dictionary. @@ -2683,13 +2700,13 @@ Returns the latest object in the table based on the given field(s). This example returns the latest ``Entry`` in the table, according to the ``pub_date`` field:: - Entry.objects.latest('pub_date') + Entry.objects.latest("pub_date") You can also choose the latest based on several fields. For example, to select the ``Entry`` with the earliest ``expire_date`` when two entries have the same ``pub_date``:: - Entry.objects.latest('pub_date', '-expire_date') + Entry.objects.latest("pub_date", "-expire_date") The negative sign in ``'-expire_date'`` means to sort ``expire_date`` in *descending* order. Since ``latest()`` gets the last result, the ``Entry`` with @@ -2716,7 +2733,7 @@ readability. You may want to filter out null values:: - Entry.objects.filter(pub_date__isnull=False).latest('pub_date') + Entry.objects.filter(pub_date__isnull=False).latest("pub_date") .. versionchanged:: 4.1 @@ -2752,13 +2769,13 @@ aggregation results as described in :ref:`aggregation-ordering-interaction`. Example:: - p = Article.objects.order_by('title', 'pub_date').first() + p = Article.objects.order_by("title", "pub_date").first() Note that ``first()`` is a convenience method, the following code sample is equivalent to the above example:: try: - p = Article.objects.order_by('title', 'pub_date')[0] + p = Article.objects.order_by("title", "pub_date")[0] except IndexError: p = None @@ -2809,7 +2826,7 @@ number of authors that have contributed blog entries: .. code-block:: pycon >>> from django.db.models import Count - >>> q = Blog.objects.aggregate(Count('entry')) + >>> q = Blog.objects.aggregate(Count("entry")) {'entry__count': 16} By using a keyword argument to specify the aggregate function, you can @@ -2817,7 +2834,7 @@ control the name of the aggregation value that is returned: .. code-block:: pycon - >>> q = Blog.objects.aggregate(number_of_entries=Count('entry')) + >>> q = Blog.objects.aggregate(number_of_entries=Count("entry")) {'number_of_entries': 16} For an in-depth discussion of aggregation, see :doc:`the topic guide on @@ -2884,13 +2901,13 @@ not. This tries to perform the query in the simplest and fastest way possible. To check whether a queryset contains a specific item:: if some_queryset.contains(obj): - print('Entry contained in queryset') + print("Entry contained in queryset") This will be faster than the following which requires evaluating and iterating through the entire queryset:: if obj in some_queryset: - print('Entry contained in queryset') + print("Entry contained in queryset") Like :meth:`exists`, if ``some_queryset`` has not yet been evaluated, but you know that it will be at some point, then using ``some_queryset.contains(obj)`` @@ -2927,7 +2944,9 @@ here we update the ``comments_on`` and ``headline`` fields: .. code-block:: pycon - >>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False, headline='This is old') + >>> Entry.objects.filter(pub_date__year=2010).update( + ... comments_on=False, headline="This is old" + ... ) The ``update()`` method is applied instantly, and the only restriction on the :class:`.QuerySet` that is updated is that it can only update columns in the @@ -2935,7 +2954,7 @@ model's main table, not on related models. You can't do this, for example: .. code-block:: pycon - >>> Entry.objects.update(blog__name='foo') # Won't work! + >>> Entry.objects.update(blog__name="foo") # Won't work! Filtering based on related fields is still possible, though: @@ -2953,7 +2972,7 @@ The ``update()`` method returns the number of affected rows: >>> Entry.objects.filter(id=64).update(comments_on=True) 1 - >>> Entry.objects.filter(slug='nonexistent-slug').update(comments_on=True) + >>> Entry.objects.filter(slug="nonexistent-slug").update(comments_on=True) 0 >>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False) @@ -2999,7 +3018,7 @@ Chaining ``order_by()`` with ``update()`` is supported only on MariaDB and MySQL, and is ignored for different databases. This is useful for updating a unique field in the order that is specified without conflicts. For example:: - Entry.objects.order_by('-number').update(number=F('number') + 1) + Entry.objects.order_by("-number").update(number=F("number") + 1) .. note:: @@ -3100,7 +3119,7 @@ For example, when using PostgreSQL: .. code-block:: pycon - >>> print(Blog.objects.filter(title='My Blog').explain()) + >>> print(Blog.objects.filter(title="My Blog").explain()) Seq Scan on blog (cost=0.00..35.50 rows=10 width=12) Filter: (title = 'My Blog'::bpchar) @@ -3121,7 +3140,7 @@ Pass these flags as keyword arguments. For example, when using PostgreSQL: .. code-block:: pycon - >>> print(Blog.objects.filter(title='My Blog').explain(verbose=True, analyze=True)) + >>> print(Blog.objects.filter(title="My Blog").explain(verbose=True, analyze=True)) Seq Scan on public.blog (cost=0.00..35.50 rows=10 width=12) (actual time=0.004..0.004 rows=10 loops=1) Output: id, title Filter: (blog.title = 'My Blog'::bpchar) @@ -3195,7 +3214,7 @@ details). Example:: - Blog.objects.get(name__iexact='beatles blog') + Blog.objects.get(name__iexact="beatles blog") Blog.objects.get(name__iexact=None) SQL equivalents: @@ -3223,7 +3242,7 @@ Case-sensitive containment test. Example:: - Entry.objects.get(headline__contains='Lennon') + Entry.objects.get(headline__contains="Lennon") SQL equivalent: @@ -3250,7 +3269,7 @@ Case-insensitive containment test. Example:: - Entry.objects.get(headline__icontains='Lennon') + Entry.objects.get(headline__icontains="Lennon") SQL equivalent: @@ -3274,7 +3293,7 @@ case, but strings (being iterables) are accepted. Examples:: Entry.objects.filter(id__in=[1, 3, 4]) - Entry.objects.filter(headline__in='abc') + Entry.objects.filter(headline__in="abc") SQL equivalents: @@ -3286,7 +3305,7 @@ SQL equivalents: You can also use a queryset to dynamically evaluate the list of values instead of providing a list of literal values:: - inner_qs = Blog.objects.filter(name__contains='Cheddar') + inner_qs = Blog.objects.filter(name__contains="Cheddar") entries = Entry.objects.filter(blog__in=inner_qs) This queryset will be evaluated as subselect statement: @@ -3300,14 +3319,14 @@ as the value to an ``__in`` lookup, you need to ensure you are only extracting one field in the result. For example, this will work (filtering on the blog names):: - inner_qs = Blog.objects.filter(name__contains='Ch').values('name') + inner_qs = Blog.objects.filter(name__contains="Ch").values("name") entries = Entry.objects.filter(blog__name__in=inner_qs) This example will raise an exception, since the inner query is trying to extract two field values, where only one is expected:: # Bad code! Will raise a TypeError. - inner_qs = Blog.objects.filter(name__contains='Ch').values('name', 'id') + inner_qs = Blog.objects.filter(name__contains="Ch").values("name", "id") entries = Entry.objects.filter(blog__name__in=inner_qs) .. _nested-queries-performance: @@ -3321,8 +3340,7 @@ extract two field values, where only one is expected:: and then pass that into the second query. That is, execute two queries instead of one:: - values = Blog.objects.filter( - name__contains='Cheddar').values_list('pk', flat=True) + values = Blog.objects.filter(name__contains="Cheddar").values_list("pk", flat=True) entries = Entry.objects.filter(blog__in=list(values)) Note the ``list()`` call around the Blog ``QuerySet`` to force execution of @@ -3376,7 +3394,7 @@ Case-sensitive starts-with. Example:: - Entry.objects.filter(headline__startswith='Lennon') + Entry.objects.filter(headline__startswith="Lennon") SQL equivalent: @@ -3396,7 +3414,7 @@ Case-insensitive starts-with. Example:: - Entry.objects.filter(headline__istartswith='Lennon') + Entry.objects.filter(headline__istartswith="Lennon") SQL equivalent: @@ -3418,7 +3436,7 @@ Case-sensitive ends-with. Example:: - Entry.objects.filter(headline__endswith='Lennon') + Entry.objects.filter(headline__endswith="Lennon") SQL equivalent: @@ -3441,7 +3459,7 @@ Case-insensitive ends-with. Example:: - Entry.objects.filter(headline__iendswith='Lennon') + Entry.objects.filter(headline__iendswith="Lennon") SQL equivalent: @@ -3464,6 +3482,7 @@ Range test (inclusive). Example:: import datetime + start_date = datetime.date(2005, 1, 1) end_date = datetime.date(2005, 3, 31) Entry.objects.filter(pub_date__range=(start_date, end_date)) @@ -3841,7 +3860,7 @@ the regular expression syntax is therefore that of Python's ``re`` module. Example:: - Entry.objects.get(title__regex=r'^(An?|The) +') + Entry.objects.get(title__regex=r"^(An?|The) +") SQL equivalents: @@ -3867,7 +3886,7 @@ Case-insensitive regular expression match. Example:: - Entry.objects.get(title__iregex=r'^(an?|the) +') + Entry.objects.get(title__iregex=r"^(an?|the) +") SQL equivalents: @@ -4150,7 +4169,7 @@ lookups or :class:`Prefetch` objects you want to prefetch for. For example: >>> from django.db.models import prefetch_related_objects >>> restaurants = fetch_top_restaurants_from_cache() # A list of Restaurants - >>> prefetch_related_objects(restaurants, 'pizzas__toppings') + >>> prefetch_related_objects(restaurants, "pizzas__toppings") When using multiple databases with ``prefetch_related_objects``, the prefetch query will use the database associated with the model instance. This can be @@ -4181,10 +4200,11 @@ For example, to find restaurants that have vegetarian pizzas with >>> from django.db.models import FilteredRelation, Q >>> Restaurant.objects.annotate( - ... pizzas_vegetarian=FilteredRelation( - ... 'pizzas', condition=Q(pizzas__vegetarian=True), - ... ), - ... ).filter(pizzas_vegetarian__name__icontains='mozzarella') + ... pizzas_vegetarian=FilteredRelation( + ... "pizzas", + ... condition=Q(pizzas__vegetarian=True), + ... ), + ... ).filter(pizzas_vegetarian__name__icontains="mozzarella") If there are a large number of pizzas, this queryset performs better than: @@ -4192,7 +4212,7 @@ If there are a large number of pizzas, this queryset performs better than: >>> Restaurant.objects.filter( ... pizzas__vegetarian=True, - ... pizzas__name__icontains='mozzarella', + ... pizzas__name__icontains="mozzarella", ... ) because the filtering in the ``WHERE`` clause of the first queryset will only diff --git a/docs/ref/models/relations.txt b/docs/ref/models/relations.txt index 495c3164ee..5c3a4a7ae5 100644 --- a/docs/ref/models/relations.txt +++ b/docs/ref/models/relations.txt @@ -14,10 +14,12 @@ Related objects reference from django.db import models + class Blog(models.Model): # ... pass + class Entry(models.Model): blog = models.ForeignKey(Blog, on_delete=models.CASCADE, null=True) @@ -31,6 +33,7 @@ Related objects reference # ... pass + class Pizza(models.Model): toppings = models.ManyToManyField(Topping) @@ -50,7 +53,7 @@ Related objects reference >>> b = Blog.objects.get(id=1) >>> e = Entry.objects.get(id=234) - >>> b.entry_set.add(e) # Associates Entry e with Blog b. + >>> b.entry_set.add(e) # Associates Entry e with Blog b. In the example above, in the case of a :class:`~django.db.models.ForeignKey` relationship, @@ -97,9 +100,7 @@ Related objects reference >>> b = Blog.objects.get(id=1) >>> e = b.entry_set.create( - ... headline='Hello', - ... body_text='Hi', - ... pub_date=datetime.date(2005, 1, 1) + ... headline="Hello", body_text="Hi", pub_date=datetime.date(2005, 1, 1) ... ) # No need to call e.save() at this point -- it's already been saved. @@ -109,12 +110,7 @@ Related objects reference .. code-block:: pycon >>> b = Blog.objects.get(id=1) - >>> e = Entry( - ... blog=b, - ... headline='Hello', - ... body_text='Hi', - ... pub_date=datetime.date(2005, 1, 1) - ... ) + >>> e = Entry(blog=b, headline="Hello", body_text="Hi", pub_date=datetime.date(2005, 1, 1)) >>> e.save(force_insert=True) Note that there's no need to specify the keyword argument of the model @@ -142,7 +138,7 @@ Related objects reference >>> b = Blog.objects.get(id=1) >>> e = Entry.objects.get(id=234) - >>> b.entry_set.remove(e) # Disassociates Entry e from Blog b. + >>> b.entry_set.remove(e) # Disassociates Entry e from Blog b. Similar to :meth:`add()`, ``e.save()`` is called in the example above to perform the update. Using ``remove()`` with a many-to-many |
