【发布时间】:2011-06-01 20:54:28
【问题描述】:
这里有两个示例 Django 模型。特别注意 has_pet 方法。
class Person(models.Model):
name = models.CharField(max_length=255)
def has_pet(self):
return bool(self.pets.all().only('id'))
class Pet(models.Model):
name = models.CharField(max_length=255)
owner = models.ForeignKey(Person, blank=True, null=True, related_name="pets")
这里的问题是 has_pet 方法总是生成一个查询。如果你做这样的事情。
p = Person.objects.get(id=1)
if p.has_pet():
...
那么你实际上会做一个额外的查询来检查一个人是否有宠物。如果您必须检查多个人,那将是一个大问题。如果在这样的模板中使用,它也会生成查询。
{% for person in persons %}
{% if person.has_pet %}
{{ person.name }} owns a pet
{% else %}
{{ person.name }} is petless
{% endif %}
{% endfor %}
这个例子实际上会在渲染模板时对persons查询集中的每个人执行一个额外的查询。
有没有办法只用一个查询,或者至少每人只做不到一个额外的查询?也许还有另一种设计方法可以完全避免这个问题。
我想为 Person 添加一个 BooleanField,并在保存或删除宠物时更新该字段。这真的是正确的方法吗?
另外,我已经正确设置了 memcached,因此只有在结果尚未缓存时才会发生这些查询。我希望首先删除查询以进行更大的优化。
【问题讨论】:
-
我认为您的建议是最好的方法:一个跟踪用户是否有宠物的布尔字段。 Pet 是数据库中的一个单独的表,因此您总是需要对其执行某种查询来查看 Person 是否有 Pet
-
虽然,现在我想起来了,如果你查询 Pet 表中的所有条目,你不应该对每个人都执行后续查询。即如果 Pet.objects.all(owner.id=id).exists() 不应该导致数据库上的另一个查询
标签: python django django-models django-queryset