1

我有一堂课叫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 多个查询,并需要一秒钟多的时间来处理。必须有更好的方法,你能告诉我路径吗?

4

1 回答 1

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实际上,您不需要实例本身,只需要 ids 即可获得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 应该将其作为带有子选择的单个查询来执行。

于 2013-11-06T19:26:27.773 回答