Django left the m2m field

Here is my model:

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()

I want to get a list of items, and I want to know if the current user voted for each item. How to change your query object so that it generates sql similar to:

SELECT ...
FROM items
LEFT OUTER JOIN item_votes ON (item_votes.user_id = ? AND
                               item_votes.item_id = items.id)
+3
source share
2 answers

You cannot execute simple django requests. This is a many, many ship relationship, you can even refine it by doing something like this:

class Item(models.Model):
    votes = models.ManyToManyField(User, through='ItemVote', related='votedItems')

In a Many-to-Many relationship, we can talk about related sets (because there are several objects). While django can filter on related sets, something like:

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 - ).

- 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

ItemVote:

items = ItemVote.objects.filter(user=user)

Django:

{% for i in items %}
item: {{ i.item }}
voted: {{ i.voted }}
{% endfor %}
0

Source: https://habr.com/ru/post/1745684/


All Articles