进行查询

Once you've created your data models, Djangoautomatically gives you a database-abstraction API that lets you create,retrieve, update and delete objects. This document explains how to use thisAPI. Refer to the data model reference for fulldetails of all the various model lookup options.

Throughout this guide (and in the reference), we'll refer to the followingmodels, which comprise a Weblog application:

  1. from django.db import models
  2.  
  3. class Blog(models.Model):
  4. name = models.CharField(max_length=100)
  5. tagline = models.TextField()
  6.  
  7. def __str__(self):
  8. return self.name
  9.  
  10. class Author(models.Model):
  11. name = models.CharField(max_length=200)
  12. email = models.EmailField()
  13.  
  14. def __str__(self):
  15. return self.name
  16.  
  17. class Entry(models.Model):
  18. blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
  19. headline = models.CharField(max_length=255)
  20. body_text = models.TextField()
  21. pub_date = models.DateField()
  22. mod_date = models.DateField()
  23. authors = models.ManyToManyField(Author)
  24. n_comments = models.IntegerField()
  25. n_pingbacks = models.IntegerField()
  26. rating = models.IntegerField()
  27.  
  28. def __str__(self):
  29. return self.headline

Creating objects

To represent database-table data in Python objects, Django uses an intuitivesystem: A model class represents a database table, and an instance of thatclass represents a particular record in the database table.

To create an object, instantiate it using keyword arguments to the model class,then call save() to save it to the database.

Assuming models live in a file mysite/blog/models.py, here's an example:

  1. >>> from blog.models import Blog
  2. >>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
  3. >>> b.save()

This performs an INSERT SQL statement behind the scenes. Django doesn't hitthe database until you explicitly call save().

The save() method has no return value.

参见

save() takes a number of advanced options notdescribed here. See the documentation forsave() for complete details.

To create and save an object in a single step, use thecreate() method.

Saving changes to objects

To save changes to an object that's already in the database, usesave().

Given a Blog instance b5 that has already been saved to the database,this example changes its name and updates its record in the database:

  1. >>> b5.name = 'New name'
  2. >>> b5.save()

This performs an UPDATE SQL statement behind the scenes. Django doesn't hitthe database until you explicitly call save().

Saving ForeignKey and ManyToManyField fields

Updating a ForeignKey field works exactly the sameway as saving a normal field — simply assign an object of the right type tothe field in question. This example updates the blog attribute of anEntry instance entry, assuming appropriate instances of Entry andBlog are already saved to the database (so we can retrieve them below):

  1. >>> from blog.models import Blog, Entry
  2. >>> entry = Entry.objects.get(pk=1)
  3. >>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
  4. >>> entry.blog = cheese_blog
  5. >>> entry.save()

Updating a ManyToManyField works a littledifferently — use theadd() method on the fieldto add a record to the relation. This example adds the Author instancejoe to the entry object:

  1. >>> from blog.models import Author
  2. >>> joe = Author.objects.create(name="Joe")
  3. >>> entry.authors.add(joe)

To add multiple records to a ManyToManyField in onego, include multiple arguments in the call toadd(), like this:

  1. >>> john = Author.objects.create(name="John")
  2. >>> paul = Author.objects.create(name="Paul")
  3. >>> george = Author.objects.create(name="George")
  4. >>> ringo = Author.objects.create(name="Ringo")
  5. >>> entry.authors.add(john, paul, george, ringo)

Django will complain if you try to assign or add an object of the wrong type.

Retrieving objects

To retrieve objects from your database, construct aQuerySet via aManager on your model class.

A QuerySet represents a collection of objectsfrom your database. It can have zero, one or many filters. Filters narrowdown the query results based on the given parameters. In SQL terms, aQuerySet equates to a SELECT statement,and a filter is a limiting clause such as WHERE or LIMIT.

You get a QuerySet by using your model'sManager. Each model has at least oneManager, and it's calledobjects by default. Access it directly via themodel class, like so:

  1. >>> Blog.objects
  2. <django.db.models.manager.Manager object at ...>
  3. >>> b = Blog(name='Foo', tagline='Bar')
  4. >>> b.objects
  5. Traceback:
  6. ...
  7. AttributeError: "Manager isn't accessible via Blog instances."

注解

Managers are accessible only via model classes, rather than from modelinstances, to enforce a separation between "table-level" operations and"record-level" operations.

The Manager is the main source of QuerySets fora model. For example, Blog.objects.all() returns aQuerySet that contains all Blog objects inthe database.

Retrieving all objects

The simplest way to retrieve objects from a table is to get all of them. To dothis, use the all() method on aManager:

  1. >>> all_entries = Entry.objects.all()

The all() method returns aQuerySet of all the objects in the database.

Retrieving specific objects with filters

The QuerySet returned byall() describes all objects in thedatabase table. Usually, though, you'll need to select only a subset of thecomplete set of objects.

To create such a subset, you refine the initialQuerySet, adding filter conditions. The twomost common ways to refine a QuerySet are:

  • filter(**kwargs)
  • Returns a new QuerySet containing objectsthat match the given lookup parameters.
  • exclude(**kwargs)
  • Returns a new QuerySet containing objectsthat do not match the given lookup parameters.
    The lookup parameters (**kwargs in the above function definitions) shouldbe in the format described in Field lookups below.

For example, to get a QuerySet of blog entriesfrom the year 2006, use filter() likeso:

  1. Entry.objects.filter(pub_date__year=2006)

With the default manager class, it is the same as:

  1. Entry.objects.all().filter(pub_date__year=2006)

Chaining filters

The result of refining a QuerySet is itself aQuerySet, so it's possible to chainrefinements together. For example:

  1. >>> Entry.objects.filter(
  2. ... headline__startswith='What'
  3. ... ).exclude(
  4. ... pub_date__gte=datetime.date.today()
  5. ... ).filter(
  6. ... pub_date__gte=datetime.date(2005, 1, 30)
  7. ... )

This takes the initial QuerySet of all entriesin the database, adds a filter, then an exclusion, then another filter. Thefinal result is a QuerySet containing allentries with a headline that starts with "What", that were published betweenJanuary 30, 2005, and the current day.

Filtered QuerySets are unique

Each time you refine a QuerySet, you get abrand-new QuerySet that is in no way bound tothe previous QuerySet. Each refinement createsa separate and distinct QuerySet that can bestored, used and reused.

举例:

  1. >>> q1 = Entry.objects.filter(headline__startswith="What")
  2. >>> q2 = q1.exclude(pub_date__gte=datetime.date.today())
  3. >>> q3 = q1.filter(pub_date__gte=datetime.date.today())

These three QuerySets are separate. The first is a baseQuerySet containing all entries that contain aheadline starting with "What". The second is a subset of the first, with anadditional criteria that excludes records whose pub_date is today or in thefuture. The third is a subset of the first, with an additional criteria thatselects only the records whose pub_date is today or in the future. Theinitial QuerySet (q1) is unaffected by therefinement process.

QuerySets are lazy

QuerySets are lazy — the act of creating aQuerySet doesn't involve any databaseactivity. You can stack filters together all day long, and Django won'tactually run the query until the QuerySet isevaluated. Take a look at this example:

  1. >>> q = Entry.objects.filter(headline__startswith="What")
  2. >>> q = q.filter(pub_date__lte=datetime.date.today())
  3. >>> q = q.exclude(body_text__icontains="food")
  4. >>> print(q)

Though this looks like three database hits, in fact it hits the database onlyonce, at the last line (print(q)). In general, the results of aQuerySet aren't fetched from the databaseuntil you "ask" for them. When you do, theQuerySet is evaluated by accessing thedatabase. For more details on exactly when evaluation takes place, seeWhen QuerySets are evaluated.

Retrieving a single object with get()

filter() will always give you aQuerySet, even if only a single object matchesthe query - in this case, it will be aQuerySet containing a single element.

If you know there is only one object that matches your query, you can use theget() method on aManager which returns the object directly:

  1. >>> one_entry = Entry.objects.get(pk=1)

You can use any query expression withget(), just like withfilter() - again, see Field lookupsbelow.

Note that there is a difference between usingget(), and usingfilter() with a slice of [0]. Ifthere are no results that match the query,get() will raise a DoesNotExistexception. This exception is an attribute of the model class that the query isbeing performed on - so in the code above, if there is no Entry object witha primary key of 1, Django will raise Entry.DoesNotExist.

Similarly, Django will complain if more than one item matches theget() query. In this case, it will raiseMultipleObjectsReturned, which again is anattribute of the model class itself.

Other QuerySet methods

Most of the time you'll use all(),get(),filter() andexclude() when you need to look upobjects from the database. However, that's far from all there is; see theQuerySet API Reference for a complete list of all thevarious QuerySet methods.

Limiting QuerySets

Use a subset of Python's array-slicing syntax to limit yourQuerySet to a certain number of results. Thisis the equivalent of SQL's LIMIT and OFFSET clauses.

For example, this returns the first 5 objects (LIMIT 5):

  1. >>> Entry.objects.all()[:5]

This returns the sixth through tenth objects (OFFSET 5 LIMIT 5):

  1. >>> Entry.objects.all()[5:10]

Negative indexing (i.e. Entry.objects.all()[-1]) is not supported.

Generally, slicing a QuerySet returns a newQuerySet — it doesn't evaluate the query. Anexception is if you use the "step" parameter of Python slice syntax. Forexample, this would actually execute the query in order to return a list ofevery second object of the first 10:

  1. >>> Entry.objects.all()[:10:2]

Further filtering or ordering of a sliced queryset is prohibited due to theambiguous nature of how that might work.

To retrieve a single object rather than a list(e.g. SELECT foo FROM bar LIMIT 1), use a simple index instead of aslice. For example, this returns the first Entry in the database, afterordering entries alphabetically by headline:

  1. >>> Entry.objects.order_by('headline')[0]

This is roughly equivalent to:

  1. >>> Entry.objects.order_by('headline')[0:1].get()

Note, however, that the first of these will raise IndexError while thesecond will raise DoesNotExist if no objects match the given criteria. Seeget() for more details.

Field lookups

Field lookups are how you specify the meat of an SQL WHERE clause. They'respecified as keyword arguments to the QuerySetmethods filter(),exclude() andget().

Basic lookups keyword arguments take the form field__lookuptype=value.(That's a double-underscore). For example:

  1. >>> Entry.objects.filter(pub_date__lte='2006-01-01')

translates (roughly) into the following SQL:

  1. SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';

How this is possible

Python has the ability to define functions that accept arbitrary name-valuearguments whose names and values are evaluated at runtime. For moreinformation, see Keyword Arguments in the official Python tutorial.

The field specified in a lookup has to be the name of a model field. There'sone exception though, in case of a ForeignKey youcan specify the field name suffixed with _id. In this case, the valueparameter is expected to contain the raw value of the foreign model's primarykey. For example:

  1. >>> Entry.objects.filter(blog_id=4)

If you pass an invalid keyword argument, a lookup function will raiseTypeError.

The database API supports about two dozen lookup types; a complete referencecan be found in the field lookup reference. To give youa taste of what's available, here's some of the more common lookups you'llprobably use:

  • exact
  • An "exact" match. For example:
  1. >>> Entry.objects.get(headline__exact="Cat bites dog")

Would generate SQL along these lines:

  1. SELECT ... WHERE headline = 'Cat bites dog';

If you don't provide a lookup type — that is, if your keyword argumentdoesn't contain a double underscore — the lookup type is assumed to beexact.

For example, the following two statements are equivalent:

  1. >>> Blog.objects.get(id__exact=14) # Explicit form
  2. >>> Blog.objects.get(id=14) # __exact is implied

This is for convenience, because exact lookups are the common case.

  • iexact
  • A case-insensitive match. So, the query:
  1. >>> Blog.objects.get(name__iexact="beatles blog")

Would match a Blog titled "Beatles Blog", "beatles blog", oreven "BeAtlES blOG".

  • contains
  • Case-sensitive containment test. For example:
  1. Entry.objects.get(headline__contains='Lennon')

Roughly translates to this SQL:

  1. SELECT ... WHERE headline LIKE '%Lennon%';

Note this will match the headline 'Today Lennon honored' but not'today lennon honored'.

There's also a case-insensitive version, icontains.

Lookups that span relationships

Django offers a powerful and intuitive way to "follow" relationships inlookups, taking care of the SQL JOINs for you automatically, behind thescenes. To span a relationship, just use the field name of related fieldsacross models, separated by double underscores, until you get to the field youwant.

This example retrieves all Entry objects with a Blog whose nameis 'Beatles Blog':

  1. >>> Entry.objects.filter(blog__name='Beatles Blog')

This spanning can be as deep as you'd like.

It works backwards, too. To refer to a "reverse" relationship, just use thelowercase name of the model.

This example retrieves all Blog objects which have at least one Entrywhose headline contains 'Lennon':

  1. >>> Blog.objects.filter(entry__headline__contains='Lennon')

If you are filtering across multiple relationships and one of the intermediatemodels doesn't have a value that meets the filter condition, Django will treatit as if there is an empty (all values are NULL), but valid, object there.All this means is that no error will be raised. For example, in this filter:

  1. Blog.objects.filter(entry__authors__name='Lennon')

(if there was a related Author model), if there was no authorassociated with an entry, it would be treated as if there was also no nameattached, rather than raising an error because of the missing author.Usually this is exactly what you want to have happen. The only case where itmight be confusing is if you are using isnull. Thus:

  1. Blog.objects.filter(entry__authors__name__isnull=True)

will return Blog objects that have an empty name on the author andalso those which have an empty author on the entry. If you don't wantthose latter objects, you could write:

  1. Blog.objects.filter(entry__authors__isnull=False, entry__authors__name__isnull=True)

Spanning multi-valued relationships

When you are filtering an object based on aManyToManyField or a reverseForeignKey, there are two different sorts of filteryou may be interested in. Consider the Blog/Entry relationship(Blog to Entry is a one-to-many relation). We might be interested infinding blogs that have an entry which has both "Lennon" in the headline andwas published in 2008. Or we might want to find blogs that have an entry with"Lennon" in the headline as well as an entry that was publishedin 2008. Since there are multiple entries associated with a single Blog,both of these queries are possible and make sense in some situations.

The same type of situation arises with aManyToManyField. For example, if an Entry has aManyToManyField called tags, we might want tofind entries linked to tags called "music" and "bands" or we might want anentry that contains a tag with a name of "music" and a status of "public".

To handle both of these situations, Django has a consistent way of processingfilter() calls. Everything inside asingle filter() call is appliedsimultaneously to filter out items matching all those requirements. Successivefilter() calls further restrict the setof objects, but for multi-valued relations, they apply to any object linked tothe primary model, not necessarily those objects that were selected by anearlier filter() call.

That may sound a bit confusing, so hopefully an example will clarify. Toselect all blogs that contain entries with both "Lennon" in the headlineand that were published in 2008 (the same entry satisfying both conditions),we would write:

  1. Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)

To select all blogs that contain an entry with "Lennon" in the headlineas well as an entry that was published in 2008, we would write:

  1. Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)

Suppose there is only one blog that had both entries containing "Lennon" andentries from 2008, but that none of the entries from 2008 contained "Lennon".The first query would not return any blogs, but the second query would returnthat one blog.

In the second example, the first filter restricts the queryset to all thoseblogs linked to entries with "Lennon" in the headline. The second filterrestricts the set of blogs further to those that are also linked to entriesthat were published in 2008. The entries selected by the second filter may ormay not be the same as the entries in the first filter. We are filtering theBlog items with each filter statement, not the Entry items.

注解

The behavior of filter() for queriesthat span multi-value relationships, as described above, is not implementedequivalently for exclude(). Instead,the conditions in a single exclude()call will not necessarily refer to the same item.

For example, the following query would exclude blogs that contain both_entries with "Lennon" in the headline _and entries published in 2008:

  1. Blog.objects.exclude(
  2. entry__headline__contains='Lennon',
  3. entry__pub_date__year=2008,
  4. )

However, unlike the behavior when usingfilter(), this will not limit blogsbased on entries that satisfy both conditions. In order to do that, i.e.to select all blogs that do not contain entries published with _"Lennon"_that were published in 2008, you need to make two queries:

  1. Blog.objects.exclude(
  2. entry__in=Entry.objects.filter(
  3. headline__contains='Lennon',
  4. pub_date__year=2008,
  5. ),
  6. )

Filters can reference fields on the model

In the examples given so far, we have constructed filters that comparethe value of a model field with a constant. But what if you want to comparethe value of a model field with another field on the same model?

Django provides F expressions to allow suchcomparisons. Instances of F() act as a reference to a model field within aquery. These references can then be used in query filters to compare the valuesof two different fields on the same model instance.

For example, to find a list of all blog entries that have had more commentsthan pingbacks, we construct an F() object to reference the pingback count,and use that F() object in the query:

  1. >>> from django.db.models import F
  2. >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))

Django supports the use of addition, subtraction, multiplication,division, modulo, and power arithmetic with F() objects, both with constantsand with other F() objects. To find all the blog entries with more thantwice as many comments as pingbacks, we modify the query:

  1. >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)

To find all the entries where the rating of the entry is less than thesum of the pingback count and comment count, we would issue thequery:

  1. >>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))

You can also use the double underscore notation to span relationships inan F() object. An F() object with a double underscore will introduceany joins needed to access the related object. For example, to retrieve allthe entries where the author's name is the same as the blog name, we couldissue the query:

  1. >>> Entry.objects.filter(authors__name=F('blog__name'))

For date and date/time fields, you can add or subtract atimedelta object. The following would return all entriesthat were modified more than 3 days after they were published:

  1. >>> from datetime import timedelta
  2. >>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))

The F() objects support bitwise operations by .bitand(), .bitor(),.bitrightshift(), and .bitleftshift(). For example:

  1. >>> F('somefield').bitand(16)

The pk lookup shortcut

For convenience, Django provides a pk lookup shortcut, which stands for"primary key".

In the example Blog model, the primary key is the id field, so thesethree statements are equivalent:

  1. >>> Blog.objects.get(id__exact=14) # Explicit form
  2. >>> Blog.objects.get(id=14) # __exact is implied
  3. >>> Blog.objects.get(pk=14) # pk implies id__exact

The use of pk isn't limited to __exact queries — any query termcan be combined with pk to perform a query on the primary key of a model:

  1. # Get blogs entries with id 1, 4 and 7
  2. >>> Blog.objects.filter(pk__in=[1,4,7])
  3.  
  4. # Get all blog entries with id > 14
  5. >>> Blog.objects.filter(pk__gt=14)

pk lookups also work across joins. For example, these three statements areequivalent:

  1. >>> Entry.objects.filter(blog__id__exact=3) # Explicit form
  2. >>> Entry.objects.filter(blog__id=3) # __exact is implied
  3. >>> Entry.objects.filter(blog__pk=3) # __pk implies __id__exact

Escaping percent signs and underscores in LIKE statements

The field lookups that equate to LIKE SQL statements (iexact,contains, icontains, startswith, istartswith, endswithand iendswith) will automatically escape the two special characters used inLIKE statements — the percent sign and the underscore. (In a LIKEstatement, the percent sign signifies a multiple-character wildcard and theunderscore signifies a single-character wildcard.)

This means things should work intuitively, so the abstraction doesn't leak.For example, to retrieve all the entries that contain a percent sign, just usethe percent sign as any other character:

  1. >>> Entry.objects.filter(headline__contains='%')

Django takes care of the quoting for you; the resulting SQL will look somethinglike this:

  1. SELECT ... WHERE headline LIKE '%\%%';

Same goes for underscores. Both percentage signs and underscores are handledfor you transparently.

Caching and QuerySets

Each QuerySet contains a cache to minimizedatabase access. Understanding how it works will allow you to write the mostefficient code.

In a newly created QuerySet, the cache isempty. The first time a QuerySet is evaluated— and, hence, a database query happens — Django saves the query results inthe QuerySet’s cache and returns the resultsthat have been explicitly requested (e.g., the next element, if theQuerySet is being iterated over). Subsequentevaluations of the QuerySet reuse the cachedresults.

Keep this caching behavior in mind, because it may bite you if you don't useyour QuerySets correctly. For example, thefollowing will create two QuerySets, evaluatethem, and throw them away:

  1. >>> print([e.headline for e in Entry.objects.all()])
  2. >>> print([e.pub_date for e in Entry.objects.all()])

That means the same database query will be executed twice, effectively doublingyour database load. Also, there's a possibility the two lists may not includethe same database records, because an Entry may have been added or deletedin the split second between the two requests.

To avoid this problem, simply save theQuerySet and reuse it:

  1. >>> queryset = Entry.objects.all()
  2. >>> print([p.headline for p in queryset]) # Evaluate the query set.
  3. >>> print([p.pub_date for p in queryset]) # Re-use the cache from the evaluation.

When QuerySets are not cached

Querysets do not always cache their results. When evaluating only part ofthe queryset, the cache is checked, but if it is not populated then the itemsreturned by the subsequent query are not cached. Specifically, this means thatlimiting the queryset using an array slice or anindex will not populate the cache.

For example, repeatedly getting a certain index in a queryset object will querythe database each time:

  1. >>> queryset = Entry.objects.all()
  2. >>> print(queryset[5]) # Queries the database
  3. >>> print(queryset[5]) # Queries the database again

However, if the entire queryset has already been evaluated, the cache will bechecked instead:

  1. >>> queryset = Entry.objects.all()
  2. >>> [entry for entry in queryset] # Queries the database
  3. >>> print(queryset[5]) # Uses cache
  4. >>> print(queryset[5]) # Uses cache

Here are some examples of other actions that will result in the entire querysetbeing evaluated and therefore populate the cache:

  1. >>> [entry for entry in queryset]
  2. >>> bool(queryset)
  3. >>> entry in queryset
  4. >>> list(queryset)

注解

Simply printing the queryset will not populate the cache. This is becausethe call to repr() only returns a slice of the entire queryset.

Complex lookups with Q objects

Keyword argument queries — in filter(),etc. — are "AND"ed together. If you need to execute more complex queries (forexample, queries with OR statements), you can use Q objects.

A Q object (django.db.models.Q) is an objectused to encapsulate a collection of keyword arguments. These keyword argumentsare specified as in "Field lookups" above.

For example, this Q object encapsulates a single LIKE query:

  1. from django.db.models import Q
  2. Q(question__startswith='What')

Q objects can be combined using the & and | operators. When anoperator is used on two Q objects, it yields a new Q object.

For example, this statement yields a single Q object that represents the"OR" of two "question__startswith" queries:

  1. Q(question__startswith='Who') | Q(question__startswith='What')

This is equivalent to the following SQL WHERE clause:

  1. WHERE question LIKE 'Who%' OR question LIKE 'What%'

You can compose statements of arbitrary complexity by combining Q objectswith the & and | operators and use parenthetical grouping. Also, Qobjects can be negated using the ~ operator, allowing for combined lookupsthat combine both a normal query and a negated (NOT) query:

  1. Q(question__startswith='Who') | ~Q(pub_date__year=2005)

Each lookup function that takes keyword-arguments(e.g. filter(),exclude(),get()) can also be passed one or moreQ objects as positional (not-named) arguments. If you provide multipleQ object arguments to a lookup function, the arguments will be "AND"edtogether. For example:

  1. Poll.objects.get(
  2. Q(question__startswith='Who'),
  3. Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
  4. )

… roughly translates into the SQL:

  1. SELECT * from polls WHERE question LIKE 'Who%'
  2. AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

Lookup functions can mix the use of Q objects and keyword arguments. Allarguments provided to a lookup function (be they keyword arguments or Qobjects) are "AND"ed together. However, if a Q object is provided, it mustprecede the definition of any keyword arguments. For example:

  1. Poll.objects.get(
  2. Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
  3. question__startswith='Who',
  4. )

… would be a valid query, equivalent to the previous example; but:

  1. # INVALID QUERY
  2. Poll.objects.get(
  3. question__startswith='Who',
  4. Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
  5. )

… would not be valid.

参见

The OR lookups examples in Django'sunit tests show some possible uses of Q.

Comparing objects

To compare two model instances, just use the standard Python comparison operator,the double equals sign: ==. Behind the scenes, that compares the primarykey values of two models.

Using the Entry example above, the following two statements are equivalent:

  1. >>> some_entry == other_entry
  2. >>> some_entry.id == other_entry.id

If a model's primary key isn't called id, no problem. Comparisons willalways use the primary key, whatever it's called. For example, if a model'sprimary key field is called name, these two statements are equivalent:

  1. >>> some_obj == other_obj
  2. >>> some_obj.name == other_obj.name

Deleting objects

The delete method, conveniently, is nameddelete(). This method immediately deletes theobject and returns the number of objects deleted and a dictionary withthe number of deletions per object type. Example:

  1. >>> e.delete()
  2. (1, {'weblog.Entry': 1})

You can also delete objects in bulk. EveryQuerySet has adelete() method, which deletes allmembers of that QuerySet.

For example, this deletes all Entry objects with a pub_date year of2005:

  1. >>> Entry.objects.filter(pub_date__year=2005).delete()
  2. (5, {'webapp.Entry': 5})

Keep in mind that this will, whenever possible, be executed purely in SQL, andso the delete() methods of individual object instances will not necessarilybe called during the process. If you've provided a custom delete() methodon a model class and want to ensure that it is called, you will need to"manually" delete instances of that model (e.g., by iterating over aQuerySet and calling delete() on eachobject individually) rather than using the bulkdelete() method of aQuerySet.

When Django deletes an object, by default it emulates the behavior of the SQLconstraint ON DELETE CASCADE — in other words, any objects which hadforeign keys pointing at the object to be deleted will be deleted along withit. For example:

  1. b = Blog.objects.get(pk=1)
  2. # This will delete the Blog and all of its Entry objects.
  3. b.delete()

This cascade behavior is customizable via theon_delete argument to theForeignKey.

Note that delete() is the onlyQuerySet method that is not exposed on aManager itself. This is a safety mechanism toprevent you from accidentally requesting Entry.objects.delete(), anddeleting all the entries. If you do want to delete all the objects, thenyou have to explicitly request a complete query set:

  1. Entry.objects.all().delete()

Copying model instances

Although there is no built-in method for copying model instances, it ispossible to easily create new instance with all fields' values copied. In thesimplest case, you can just set pk to None. Using our blog example:

  1. blog = Blog(name='My blog', tagline='Blogging is easy')
  2. blog.save() # blog.pk == 1
  3.  
  4. blog.pk = None
  5. blog.save() # blog.pk == 2

Things get more complicated if you use inheritance. Consider a subclass ofBlog:

  1. class ThemeBlog(Blog):
  2. theme = models.CharField(max_length=200)
  3.  
  4. django_blog = ThemeBlog(name='Django', tagline='Django is easy', theme='python')
  5. django_blog.save() # django_blog.pk == 3

Due to how inheritance works, you have to set both pk and id to None:

  1. django_blog.pk = None
  2. django_blog.id = None
  3. django_blog.save() # django_blog.pk == 4

This process doesn't copy relations that aren't part of the model's databasetable. For example, Entry has a ManyToManyField to Author. Afterduplicating an entry, you must set the many-to-many relations for the newentry:

  1. entry = Entry.objects.all()[0] # some previous entry
  2. old_authors = entry.authors.all()
  3. entry.pk = None
  4. entry.save()
  5. entry.authors.set(old_authors)

For a OneToOneField, you must duplicate the related object and assign itto the new object's field to avoid violating the one-to-one unique constraint.For example, assuming entry is already duplicated as above:

  1. detail = EntryDetail.objects.all()[0]
  2. detail.pk = None
  3. detail.entry = entry
  4. detail.save()

Updating multiple objects at once

Sometimes you want to set a field to a particular value for all the objects ina QuerySet. You can do this with theupdate() method. For example:

  1. # Update all the headlines with pub_date in 2007.
  2. Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

You can only set non-relation fields and ForeignKeyfields using this method. To update a non-relation field, provide the new valueas a constant. To update ForeignKey fields, set thenew value to be the new model instance you want to point to. For example:

  1. >>> b = Blog.objects.get(pk=1)
  2.  
  3. # Change every Entry so that it belongs to this Blog.
  4. >>> Entry.objects.all().update(blog=b)

The update() method is applied instantly and returns the number of rowsmatched by the query (which may not be equal to the number of rows updated ifsome rows already have the new value). The only restriction on theQuerySet being updated is that it can onlyaccess one database table: the model's main table. You can filter based onrelated fields, but you can only update columns in the model's maintable. Example:

  1. >>> b = Blog.objects.get(pk=1)
  2.  
  3. # Update all the headlines belonging to this Blog.
  4. >>> Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same')

Be aware that the update() method is converted directly to an SQLstatement. It is a bulk operation for direct updates. It doesn't run anysave() methods on your models, or emit thepre_save or post_save signals (which are a consequence of callingsave()), or honor theauto_now field option.If you want to save every item in a QuerySetand make sure that the save() method is called oneach instance, you don't need any special function to handle that. Just loopover them and call save():

  1. for item in my_queryset:
  2. item.save()

Calls to update can also use F expressions toupdate one field based on the value of another field in the model. This isespecially useful for incrementing counters based upon their current value. Forexample, to increment the pingback count for every entry in the blog:

  1. >>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)

However, unlike F() objects in filter and exclude clauses, you can'tintroduce joins when you use F() objects in an update — you can onlyreference fields local to the model being updated. If you attempt to introducea join with an F() object, a FieldError will be raised:

  1. # This will raise a FieldError
  2. >>> Entry.objects.update(headline=F('blog__name'))

When you define a relationship in a model (i.e., aForeignKey,OneToOneField, orManyToManyField), instances of that model will havea convenient API to access the related object(s).

Using the models at the top of this page, for example, an Entry object ecan get its associated Blog object by accessing the blog attribute:e.blog.

(Behind the scenes, this functionality is implemented by Python descriptors.This shouldn't really matter to you, but we point it out here for the curious.)

Django also creates API accessors for the "other" side of the relationship —the link from the related model to the model that defines the relationship.For example, a Blog object b has access to a list of all relatedEntry objects via the entry_set attribute: b.entry_set.all().

All examples in this section use the sample Blog, Author and Entrymodels defined at the top of this page.

One-to-many relationships

Forward

If a model has a ForeignKey, instances of that modelwill have access to the related (foreign) object via a simple attribute of themodel.

举例:

  1. >>> e = Entry.objects.get(id=2)
  2. >>> e.blog # Returns the related Blog object.

You can get and set via a foreign-key attribute. As you may expect, changes tothe foreign key aren't saved to the database until you callsave(). Example:

  1. >>> e = Entry.objects.get(id=2)
  2. >>> e.blog = some_blog
  3. >>> e.save()

If a ForeignKey field has null=True set (i.e.,it allows NULL values), you can assign None to remove the relation.Example:

  1. >>> e = Entry.objects.get(id=2)
  2. >>> e.blog = None
  3. >>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;"

Forward access to one-to-many relationships is cached the first time therelated object is accessed. Subsequent accesses to the foreign key on the sameobject instance are cached. Example:

  1. >>> e = Entry.objects.get(id=2)
  2. >>> print(e.blog) # Hits the database to retrieve the associated Blog.
  3. >>> print(e.blog) # Doesn't hit the database; uses cached version.

Note that the select_related()QuerySet method recursively prepopulates thecache of all one-to-many relationships ahead of time. Example:

  1. >>> e = Entry.objects.select_related().get(id=2)
  2. >>> print(e.blog) # Doesn't hit the database; uses cached version.
  3. >>> print(e.blog) # Doesn't hit the database; uses cached version.

Following relationships "backward"

If a model has a ForeignKey, instances of theforeign-key model will have access to a Manager thatreturns all instances of the first model. By default, thisManager is named FOO_set, where FOO is thesource model name, lowercased. This Manager returnsQuerySets, which can be filtered and manipulated as described in the"Retrieving objects" section above.

举例:

  1. >>> b = Blog.objects.get(id=1)
  2. >>> b.entry_set.all() # Returns all Entry objects related to Blog.
  3.  
  4. # b.entry_set is a Manager that returns QuerySets.
  5. >>> b.entry_set.filter(headline__contains='Lennon')
  6. >>> b.entry_set.count()

You can override the FOO_set name by setting therelated_name parameter in theForeignKey definition. For example, if the Entrymodel was altered to blog = ForeignKey(Blog, on_delete=models.CASCADE,
related_name='entries')
, the above example code would look like this:

  1. >>> b = Blog.objects.get(id=1)
  2. >>> b.entries.all() # Returns all Entry objects related to Blog.
  3.  
  4. # b.entries is a Manager that returns QuerySets.
  5. >>> b.entries.filter(headline__contains='Lennon')
  6. >>> b.entries.count()

Using a custom reverse manager

By default the RelatedManager usedfor reverse relations is a subclass of the default managerfor that model. If you would like to specify a different manager for a givenquery you can use the following syntax:

  1. from django.db import models
  2.  
  3. class Entry(models.Model):
  4. #...
  5. objects = models.Manager() # Default Manager
  6. entries = EntryManager() # Custom Manager
  7.  
  8. b = Blog.objects.get(id=1)
  9. b.entry_set(manager='entries').all()

If EntryManager performed default filtering in its get_queryset()method, that filtering would apply to the all() call.

Of course, specifying a custom reverse manager also enables you to call itscustom methods:

  1. b.entry_set(manager='entries').is_published()

In addition to the QuerySet methods defined in"Retrieving objects" above, the ForeignKeyManager has additional methods used to handle theset of related objects. A synopsis of each is below, and complete details canbe found in the related objects reference.

  • add(obj1, obj2, …)
  • 将特定的模型对象加入关联对象集合。
  • create(**kwargs)
  • Creates a new object, saves it and puts it in the related object set.Returns the newly created object.
  • remove(obj1, obj2, …)
  • Removes the specified model objects from the related object set.
  • clear()
  • Removes all objects from the related object set.
  • set(objs)
  • Replace the set of related objects.
    To assign the members of a related set, use the set() method with aniterable of object instances. For example, if e1 and e2 are Entryinstances:
  1. b = Blog.objects.get(id=1)
  2. b.entry_set.set([e1, e2])

If the clear() method is available, any pre-existing objects will beremoved from the entry_set before all objects in the iterable (in thiscase, a list) are added to the set. If the clear() method is _not_available, all objects in the iterable will be added without removing anyexisting elements.

Each "reverse" operation described in this section has an immediate effect onthe database. Every addition, creation and deletion is immediately andautomatically saved to the database.

Many-to-many relationships

Both ends of a many-to-many relationship get automatic API access to the otherend. The API works similar to a "backward" one-to-many relationship, above.

One difference is in the attribute naming: The model that defines theManyToManyField uses the attribute name of thatfield itself, whereas the "reverse" model uses the lowercased model name of theoriginal model, plus '_set' (just like reverse one-to-many relationships).

An example makes this easier to understand:

  1. e = Entry.objects.get(id=3)
  2. e.authors.all() # Returns all Author objects for this Entry.
  3. e.authors.count()
  4. e.authors.filter(name__contains='John')
  5.  
  6. a = Author.objects.get(id=5)
  7. a.entry_set.all() # Returns all Entry objects for this Author.

Like ForeignKey,ManyToManyField can specifyrelated_name. In the above example,if the ManyToManyField in Entry had specifiedrelated_name='entries', then each Author instance would have anentries attribute instead of entry_set.

Another difference from one-to-many relationships is that in addition to modelinstances, the add(), set(), and remove() methods on many-to-manyrelationships accept primary key values. For example, if e1 and e2 areEntry instances, then these set() calls work identically:

  1. a = Author.objects.get(id=5)
  2. a.entry_set.set([e1, e2])
  3. a.entry_set.set([e1.pk, e2.pk])

One-to-one relationships

One-to-one relationships are very similar to many-to-one relationships. If youdefine a OneToOneField on your model, instances ofthat model will have access to the related object via a simple attribute of themodel.

例如:

  1. class EntryDetail(models.Model):
  2. entry = models.OneToOneField(Entry, on_delete=models.CASCADE)
  3. details = models.TextField()
  4.  
  5. ed = EntryDetail.objects.get(id=2)
  6. ed.entry # Returns the related Entry object.

The difference comes in "reverse" queries. The related model in a one-to-onerelationship also has access to a Manager object, butthat Manager represents a single object, rather thana collection of objects:

  1. e = Entry.objects.get(id=2)
  2. e.entrydetail # returns the related EntryDetail object

If no object has been assigned to this relationship, Django will raisea DoesNotExist exception.

Instances can be assigned to the reverse relationship in the same way asyou would assign the forward relationship:

  1. e.entrydetail = ed

How are the backward relationships possible?

Other object-relational mappers require you to define relationships on bothsides. The Django developers believe this is a violation of the DRY (Don'tRepeat Yourself) principle, so Django only requires you to define therelationship on one end.

But how is this possible, given that a model class doesn't know which othermodel classes are related to it until those other model classes are loaded?

The answer lies in the app registry. When Djangostarts, it imports each application listed in INSTALLED_APPS, andthen the models module inside each application. Whenever a new model classis created, Django adds backward-relationships to any related models. If therelated models haven't been imported yet, Django keeps tracks of therelationships and adds them when the related models eventually are imported.

For this reason, it's particularly important that all the models you're usingbe defined in applications listed in INSTALLED_APPS. Otherwise,backwards relations may not work properly.

Queries involving related objects follow the same rules as queries involvingnormal value fields. When specifying the value for a query to match, you mayuse either an object instance itself, or the primary key value for the object.

For example, if you have a Blog object b with id=5, the followingthree queries would be identical:

  1. Entry.objects.filter(blog=b) # Query using object instance
  2. Entry.objects.filter(blog=b.id) # Query using id from instance
  3. Entry.objects.filter(blog=5) # Query using id directly

Falling back to raw SQL

If you find yourself needing to write an SQL query that is too complex forDjango's database-mapper to handle, you can fall back on writing SQL by hand.Django has a couple of options for writing raw SQL queries; seePerforming raw SQL queries.

Finally, it's important to note that the Django database layer is merely aninterface to your database. You can access your database via other tools,programming languages or database frameworks; there's nothing Django-specificabout your database.