我有一个名为ToggleProperty
的班级。我用它来存储有关用户是否在对象上切换某些属性的信息。属性的示例是“like”,“bookmark”和“follow”。
class ToggleProperty(models.Model):
# "like", "bookmark", "follow" etc
property_type = CharField()
# The user who toggled the property
user = ForeignKey(User)
# The object upon which the user is toggling the property, e.g. "user likes image"
object_id = models.TextField()
content_type = models.ForeignKey(ContentType)
content_object = generic.GenericForeignKey('content_type', 'object_id')
现在,我想获得一个其他用户所遵循的用户列表,让我们称他为Tom。
我不能只查询ToggleProperty
,因为那会给我ToggleProperties,而不是用户!
所以我这样做:
# First get the ContentType for user, we'll need it
user_ct = ContentType.objects.get_for_model(User)
# Now get the users that Tom follows
followed_by_tom = [
user_ct.get_object_for_this_type(id = x.object_id) for x in
ToggleProperty.objects.filter(
property_type = "follow",
user = tom,
content_type = ContentType.objects.get_for_model(User))
]
问题在于它在我的视图中命中数据库,我不喜欢它。
如果这不够丑陋,请听我说。我实际上对Tom所关注的用户上传的图像感兴趣,所以我可以通过他所关注的人向Tom展示所有图像。
所以对于上面的代码,我添加了这个:
images = Image.objects.filter(user__in = followed_by_tom)
这最终会执行超过400个查询,并且需要花费一秒钟来处理。必须有更好的方法,请你告诉我路径?
答案 0 :(得分:2)
这篇文章:
followed_by_tom = [
user_ct.get_object_for_this_type(id = x.object_id) for x in
ToggleProperty.objects.filter(
property_type = "follow",
user = tom,
content_type = ContentType.objects.get_for_model(User))
]
获取在User
个查询中可以在单个查询中完成的所有N
个实例。实际上,您不需要实例本身只需要id来获取Images
IN
查询。因此,您可以通过以下方式删除循环中的额外查询:
followed_by_tom = ToggleProperty.objects.filter(
property_type="follow",
user=tom,
content_type=ContentType.objects.get_for_model(User)
).values_list('object_id', flat=True)
images = Image.objects.filter(user__in=followed_by_tom)
由于永远不会评估followed_by_tom
,因此ORM应将其作为带有子选择的单个查询执行。