在Django中获取相关对象的特定字段

17

假设我在 Django 中有这样的模型:

class User(models.Model):
    name=models.CharField(...)
    email=models.EmailField(...)
    photo=...
    <other fields>

class Comment(models.Model):
    user=models.ForeignKey(User, ...)

我有一个函数,它接收 Comment 对象,并且只需要姓名和电子邮件字段来发送电子邮件(这只是一个示例,很明显)

def sendEmail(comment):
    name, email=comment.user.name, comment.user.email
在上面提供的实现中,Django 将获取相关对象 User 的所有字段(大致相当于 select * from users where id=comment.user_id)。 使用 values_list,可以仅获取所需字段: Users.objects.filter(id=comment.user_id).values_list('name', 'email') 但是 values_list 仅适用于 QuerySet 对象,而不适用于模型实例。 我的问题是:是否有任何方法仅使用“comment”对象来执行相同的操作? 它必须与 select name, email from users where id=comment.user_id 的复杂度相等(我不想在不需要时传输存储在某些字段中的大量数据)。

1
简而言之,您希望ForeignKey能够部分获取相关对象,而无需显式查询集吗? - dhke
@dhke,是的,完全正确。 - fantom
坦白地说:Comment是一个属性,它返回上述查询的结果。我想到的其他解决方案都需要使用自定义的ForwardManyToOneDescriptor,这就有点过度了。 - dhke
4个回答

15

如果您想在评论中获得一些额外的用户数据,而不必检索整个User对象,则我认为最好在检索评论时获取附加数据:

Comment.objects.filter(user=user).values_list('user__name', 'user__email')

显然,您可以获取其他有用的评论字段。

或者:

Comment.objects.filter(user=user).annotate(author_name=F('user__name'),\ 
                                           author_email=F('user__email'))

这仍然使用QuerySet API,但两种方法都允许您跨越关系以获取额外的数据而不需要额外的查询。


1
Users.objects.filter(id=comment.user_id).values_list('name', 'email').get()

应该可以了


1
queryset = ModelName.objects.filter().only('realed_obj__field1', 'related_obj__field2')

0
必须在复杂性上等于 select name, email from users where id=comment.user_id

真正等效于此查询的是您已经拥有的:

Users.objects.filter(id=comment.user_id).values_list('name', 'email')

“values_list”只适用于“QuerySet”对象,而不适用于模型实例。
这是绝对正确的。但你需要考虑的是,一旦你拥有了这个查询集合,你就可以获取第一个元素,因为只有一个用户ID,那么就只会有一个用户。
name, email = Users.objects.filter(id=comment.user_id).values_list('name', 'email').first()

1
同时使用first和元组展开是一个不好的主意...如果没有匹配项,那么你会得到一个错误,因为它无法将None分成两个部分。 - Shadow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接