Django------(Related objects)相关对象查询
When you define a relationship in a model(i.e.,a ForeignKey,OneToOneField,ManyToManyField),instance of that models will have a convenient API to access the related objects.
Django 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 related Entry objects via the entry_set attribute: b.entry_set.all().
All examples in this section use the sample Blog, Author and Entry models defined at the previous Blog.
One-to-many relationships:
Faward:
>>> e = Entry.objects.get(pk=2) >>> e.blog # Return the related Blog object.
Changes to the foreignkey are not saved to the database until you call save().
>>> e = Entry.objects.get(pk=6) >>> e.blog = some_blog >>> e.save()
If a foreign key field has null=True set, you can assign None to it:
>>> e = Entry.objects.get(id=2) >>> e.blog = None >>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;"
>>> e = Entry.objects.get(id=2) >>> print e.blog # Hits the database to retrieve the associated Blog. >>> print e.blog # Doesn't hit the database; uses cached version.
>>> e = Entry.objects.select_related().get(id=2) >>> print e.blog # Doesn't hit the database; uses cached version. >>> print e.blog # Doesn't hit the database; uses cached version.
backward:
>>> b = Blog.objects.get(id=1) >>> b.entry_set.all() # Returns all Entry objects related to Blog. # b.entry_set is a Manager that returns QuerySets. >>> b.entry_set.filter(headline__contains='Lennon') >>> b.entry_set.count()
You can override the FOO_set name by setting the related_name parameter in the ForeignKey() definition. For example, if the Entry model was altered to blog=models.ForeignKey(Blog, related_name='entries'),the code would look like this:
>>> b = Blog.objects.get(id=1) >>> b.entries.all() >>> b.entries.filter(headline__contains='Lennon') >>> b.entries.count()
You cannot access a reverse ForeignKey Manager from the class; it must be accessed from an instance:
>>> Blog.entry_set Traceback: ... AttributeError: "Manager must be accessed via instance".
add(.......) >>> b = Blog.objects.get(id=1) >>> e = Entry.objects.get(id=234) >>> b.entry_set.add(e) # Associates Entry e with Blog b.
>>> b = Blog.objects.get(id=1) >>> e = b.entry_set.create( ... 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.
>>> b = Blog.objects.get(id=1) >>> e = Entry.objects.get(id=234) >>> b.entry_set.remove(e) # Disassociates Entry e from Blog b. In order to prevent database inconsistency, this method only exists on ForeignKey objects where null=True. I
>>> b = Blog.objects.get(id=1)
>>> b.entry_set.clear()
Just like remove(), clear() is only available on ForeignKeys where null=True.
Many-to-many relationships:
e = Entry.objects.get(id=3) e.authors.all() # Returns all Author objects for this Entry. e.authors.count() e.authors.filter(name__contains='John') a = Author.objects.get(id=5) a.entry_set.all() # Returns all Entry objects for this Author.
One-to-one relationships:
class EntryDetail(models.Model): entry = models.OneToOneField(Entry) details = models.TextField() ed = EntryDetail.objects.get(id=2) ed.entry # Returns the related Entry object.
e = Entry.objects.get(id=2) e.entrydetail # returns the related EntryDetail object
e.entrydetail = ed
反向关系怎么成为可能?
其他的对象关系映射都要求在两边都定义关系,但是Django的开发者认为这违反的DRY的原则,所以django只要求在一方定义关系,但是怎么让它成为可能呢,主要是在INSTALL_APP里。
If you have a Blog object b with id=5, the following three queries would be identical(相同的):
Entry.objects.filter(blog=b) # Query using object instance Entry.objects.filter(blog=b.id) # Query using id from instance Entry.objects.filter(blog=5) # Query using id directly