如何验证对象是否存在于manymanmany中

Hen*_*mos 16 django many-to-many

楷模

class Beer(models.Model):
    pass

class Salas(models.Model):
    name =  models.CharField(max_length=20)
    beers =     models.ManyToManyField('Beer', blank=True)
Run Code Online (Sandbox Code Playgroud)

视图

beer = Beer.objects.get(user=user)
id_sala = request.GET['id_sala']
sala = get_object_or_404(Salas, id=id_sala)


if beer.salas_set.filter(nombre=sala):
# if beer.objects.filter(sitios__id=beer).exists():
    sala.beers.remove(beer)

else:
    sala.beers.add(beer)
Run Code Online (Sandbox Code Playgroud)

我想看看啤酒与sala之间是否存在关系,如何制作?

Jak*_*ňák 37

我建议你使用:

if beer.salas_set.filter(pk=sala.pk).exists():
    # do stuff
Run Code Online (Sandbox Code Playgroud)

如果使用sala in beer.salas_set.all(),它会从关系表中选择所有记录并循环遍历它们,以查找给定对象是否存在.但是,beer.salas_set.filter(pk=sala.pk).exists()只从数据库中选择零行或一行并立即给出结果(不循环).

  • 三年后,当我刚开始使用Django时,我对自己的回答感到ham愧。我强烈推荐您的。谢谢! (4认同)
  • @sebhaase 好吧,因为 `in` 将强制 django 评估查询集以产生布尔值。也就是说,查询集是延迟计算的,如果它是一个 10000 个对象的查询集,它会非常慢。另一方面,“.filter().exists()”将在数据库中执行额外的查询,但它只是一个。 (2认同)

Pat*_*sut 13

使用您的解决方案可能会出现问题,因为salas的名称并不是唯一的.因此,如果您按照sala的名称过滤,希望找到一个且只有一个sala,那可能不会发生.

我建议你这样做:

if sala in beer.salas_set.all():
    #do stuff:
else:
    # do other stuff
Run Code Online (Sandbox Code Playgroud)

这样,beer.salas_set.all()将返回一个QuerySet,您可以在其中使用'in'关键字检查特定对象是否存在.

  • 对于未来的访问者:Django Docs https://docs.djangoproject.com/en/dev/ref/models/querysets/#exists中介绍了该主题.支持`in`运算符,但`exists()`更快根据文档. (7认同)

小智 5

Django 4.0 向 QuerySets 添加了一个新的 contains() 方法,这非常适合此用例。

if beer.salas_set.contains(sala):
    # do stuff
Run Code Online (Sandbox Code Playgroud)