bun*_*ero 16 django manytomanyfield
鉴于这两个模型:
class Item(models.Model):
timestamp = models.DateTimeField()
class Source(models.Model):
items = models.ManyToManyField(Item, related_name="sources")
Run Code Online (Sandbox Code Playgroud)
我可以在给定时间之前找到所有Source的项目:
source.items.filter(timestamp__lte=some_datetime)
Run Code Online (Sandbox Code Playgroud)
如何有效删除与该查询匹配的所有项目?我想我可以尝试这样的事情:
items_to_remove = list(source.items.filter(timestamp__lte=some_datetime))
source.items.remove(*items_to_remove)
Run Code Online (Sandbox Code Playgroud)
但那似乎很糟糕.
请注意,我不想删除这些项目,因为它们也可能属于其他来源.我只想删除他们与特定来源的关系.
Yuj*_*ita 26
我认为你没钱,除了你不需要转换成一个列表.
source.items.remove(*source.items.filter(*args))
Run Code Online (Sandbox Code Playgroud)
该remove/ add方法如下所示
remove(self, *objs)
add(self, *objs)
Run Code Online (Sandbox Code Playgroud)
并且文档使用以形式添加多个示例,[p1, p2, p3]所以我也会下注remove,因为参数是相同的.
>>> a2.publications.add(p1, p2, p3)
Run Code Online (Sandbox Code Playgroud)
进一步挖掘,删除函数*objs逐个迭代,检查它是否是有效模型,否则使用值作为PK,然后用a删除项目pk__in,所以我会说是,最好的方法是首先查询m2m表以查找要删除的对象,然后将这些对象传入m2m管理器.
# django.db.models.related.py
def _remove_items(self, source_field_name, target_field_name, *objs):
# source_col_name: the PK colname in join_table for the source object
# target_col_name: the PK colname in join_table for the target object
# *objs - objects to remove
# If there aren't any objects, there is nothing to do.
if objs:
# Check that all the objects are of the right type
old_ids = set()
for obj in objs:
if isinstance(obj, self.model):
old_ids.add(obj.pk)
else:
old_ids.add(obj)
if self.reverse or source_field_name == self.source_field_name:
# Don't send the signal when we are deleting the
# duplicate data row for symmetrical reverse entries.
signals.m2m_changed.send(sender=rel.through, action="pre_remove",
instance=self.instance, reverse=self.reverse,
model=self.model, pk_set=old_ids)
# Remove the specified objects from the join table
db = router.db_for_write(self.through.__class__, instance=self.instance)
self.through._default_manager.using(db).filter(**{
source_field_name: self._pk_val,
'%s__in' % target_field_name: old_ids
}).delete()
if self.reverse or source_field_name == self.source_field_name:
# Don't send the signal when we are deleting the
# duplicate data row for symmetrical reverse entries.
signals.m2m_changed.send(sender=rel.through, action="post_remove",
instance=self.instance, reverse=self.reverse,
model=self.model, pk_set=old_ids)
Run Code Online (Sandbox Code Playgroud)
小智 5
根据当前的文档,有一个through属性可以让您访问管理多对多关系的表,就像这样Model.m2mfield.through.objects.all()
所以就你的例子而言:
source.items.through.objects \
.filter(item__timestamp__lte=some_datetime) \
.delete()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9437 次 |
| 最近记录: |