这是我的模特:
class User(models.Model):
pass
class Item(models.Model):
pass
class ItemVote(models.Model):
user = models.ForeignKey(User)
item = models.ForeignKey(Item)
vote = models.BooleanField()
我想检索一个Items列表,我想知道当前用户是否已为每个Item投票。如何更改我的查询对象,以便生成类似于:
的sqlSELECT ...
FROM items
LEFT OUTER JOIN item_votes ON (item_votes.user_id = ? AND
item_votes.item_id = items.id)
答案 0 :(得分:1)
你不能在简单的django查询中。这是一个多对多的关系,您甚至可以通过这样的方式更明确地指定它:
class Item(models.Model):
votes = models.ManyToManyField(User, through='ItemVote', related='votedItems')
在多对多关系中,我们可以说相关集(因为有多个对象)。虽然django可以过滤相关集,例如:
Item.objects.filter(votes=request.user)
这将返回用户投票的所有项目。但是,当您在这些对象中列出.votes属性时,您将获得已投票赞成该项目的所有用户。过滤用于原始对象,从不用于相关集。
以纯粹的django方式,您可以将我以前的Item类扩展为:
class Item(models.Model):
votes = models.ManyToManyField(User, through='ItemVote', related='votedItems')
def markVoted(self, user):
self.voted = user in self.votes
然后为每个对象调用此方法。但是,这将为每个对象的集合创建一个额外的查询(并且不会,select_related不适用于多对多关系)。
解决此问题的唯一方法是使用extra method向查询集添加一些SQL,如下所示:
Item.objects.extra('voted' : 'SELECT COUNT(*) FROM app_itemvote WHERE app_itemvote.item_id = app_item.id AND app_itemvote.user_id=%d'%request.user.pk)
答案 1 :(得分:0)
返回ItemVote项目:
items = ItemVote.objects.filter(user=user)
在Django模板中使用:
{% for i in items %}
item: {{ i.item }}
voted: {{ i.voted }}
{% endfor %}