RelatedManager
P“关系管理器”是一个用于处理“一对多”和“多对多”关联关系的管理器。在以下两种情况用到:
“另一边”的关联关系 ForeignKey
。即:
from django.db import models
class Reporter(models.Model):
# ...
pass
class Article(models.Model):
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
在上面的例子中,以下方法会在管理器 reporter.article_set
中可用。
双边关系 ManyToManyField
class Topping(models.Model):
# ...
pass
class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)
在这个例子中,下文列出的方法在 topping.pizza_set
和 pizza.toppings
中均可用。
add
(*objs, bulk=True, through_defaults=None)P将特定的模型对象加入关联对象集合。
举例:
>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.add(e) # Associates Entry e with Blog b.
上述例子中,由于有 ForeignKey
关联关系,才可以使用 QuerySet.update()
更新数据。这要求对象事先已经被保存在数据库内了。
你可以使用 bulk=False
参数让关系管理器通过调用 e.save()
来执行更新操作。
Using add()
with a many-to-many relationship, however, will not
call any save()
methods (the bulk
argument doesn't exist), but
rather create the relationships using QuerySet.bulk_create()
. If you need to execute
some custom logic when a relationship is created, listen to the
m2m_changed
signal, which will
trigger pre_add
and post_add
actions.
Using add()
on a relation that already exists won't duplicate the
relation, but it will still trigger signals.
add()
also accepts the field the relation points to as an argument.
The above example can be rewritten as b.entry_set.add(234)
.
Use the through_defaults
argument to specify values for the new
intermediate model instance(s), if
needed.
The through_defaults
argument was added.
create
(through_defaults=None, **kwargs)P创建一个新对象,保存至数据库,并将其放入关联对象集合内。返回刚创建的对象:
>>> 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(
... blog=b,
... headline='Hello',
... body_text='Hi',
... pub_date=datetime.date(2005, 1, 1)
... )
>>> e.save(force_insert=True)
无需指定定义了模型间关系的关键字参数。在上述例子中,我们并未向 create()
传递参数 blog
。Django 知道要将新 Entry
对象的 blog
字段设置为 b
。
Use the through_defaults
argument to specify values for the new
intermediate model instance, if
needed.
The through_defaults
argument was added.
remove
(*objs, bulk=True)P从关系集合中移除特定的对象:
>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.
Similar to add()
, e.save()
is called in the example above
to perform the update. Using remove()
with a many-to-many
relationship, however, will delete the relationships using
QuerySet.delete()
which
means no model save()
methods are called; listen to the
m2m_changed
signal if you wish to
execute custom code when a relationship is deleted.
Similarly to add()
, remove()
also accepts the field the
relation points to as an argument. The above example can be rewritten
as b.entry_set.remove(234)
.
For ForeignKey
objects, this method only
exists if null=True
. If the related field can't be set to None
(NULL
), then an object can't be removed from a relation without
being added to another. In the above example, removing e
from
b.entry_set()
is equivalent to doing e.blog = None
, and because
the blog
ForeignKey
doesn't have
null=True
, this is invalid.
For ForeignKey
objects, this method accepts
a bulk
argument to control how to perform the operation.
If True
(the default), QuerySet.update()
is used.
If bulk=False
, the save()
method of each individual model
instance is called instead. This triggers the
pre_save
and
post_save
signals and comes at the
expense of performance.
For many-to-many relationships, the bulk
keyword argument doesn't
exist.
clear
(bulk=True)P清空关系集合:
>>> b = Blog.objects.get(id=1)
>>> b.entry_set.clear()
Note this doesn't delete the related objects -- it just disassociates them.
Just like remove()
, clear()
is only available on
ForeignKey
s where null=True
and it also
accepts the bulk
keyword argument.
For many-to-many relationships, the bulk
keyword argument doesn't
exist.
set
(objs, bulk=True, clear=False, through_defaults=None)PReplace the set of related objects:
>>> new_list = [obj1, obj2, obj3]
>>> e.related_set.set(new_list)
This method accepts a clear
argument to control how to perform the
operation. If False
(the default), the elements missing from the
new set are removed using remove()
and only the new ones are added.
If clear=True
, the clear()
method is called instead and the
whole set is added at once.
For ForeignKey
objects, the bulk
argument is passed on to add()
and remove()
.
For many-to-many relationships, the bulk
keyword argument doesn't
exist.
Note that since set()
is a compound operation, it is subject to
race conditions. For instance, new objects may be added to the database
in between the call to clear()
and the call to add()
.
Similarly to add()
, set()
also accepts the field the
relation points to as an argument. The above example can be rewritten
as e.related_set.set([obj1.pk, obj2.pk, obj3.pk])
.
Use the through_defaults
argument to specify values for the new
intermediate model instance(s), if
needed.
The through_defaults
argument was added.
注解
Note that add()
, create()
, remove()
, clear()
, and
set()
all apply database changes immediately for all types of
related fields. In other words, there is no need to call save()
on either end of the relationship.
If you use prefetch_related()
,
the add()
, remove()
, clear()
, and set()
methods clear
the prefetched cache.