【问题标题】:Django query that excludes results if id from one table is in another如果一个表中的 id 在另一个表中,则排除结果的 Django 查询
【发布时间】:2016-03-27 19:42:42
【问题描述】:

我正在尝试创建一个 Django 查询,其中结果是 Item 表中的所有条目,其中给定用户的 Seen 表中的表项没有条目。

我的 Django 模型如下所示:

from django.db import models
from django.contrib.auth.models import User

# The keywords that can be associated with an item (e.g. Animals, Scenery, Buildings, Art, ...)
class Keyword(models.Model):
    name = models.CharField(max_length=30)

    # This needed to show the name and not the text 'keyword object' on the Admin page
    def __str__(self):
        return format(self.name)

# Items. E.g. Vines, YouTube, Vimeo, Photo...
class Item(models.Model):

    ITEM_TYPES = (
        ('V', 'Vine'),
        ('Y', 'YouTube'),
        ('P', 'Photo'),         # Photo is stored by us on a CDN somewhere
        ('F', 'Flickr'),
        ('I', 'Instagram'),
        ('D', 'DeviantArt'),
        ('5', '500px'),
    )
    owner           = models.ForeignKey(User, on_delete=models.CASCADE)     # Id of user who owns the item
    url             = models.CharField(max_length=250, default='')          # URL of where item resides (e.g. Vine or YouTube url)
    item_type       = models.CharField(max_length=1, choices=ITEM_TYPES)    # Type of item (e.g. Vine|YoutTube|Instagram|etc.)
    keywords        = models.ManyToManyField(Keyword, related_name='keywords')
                                                                            # E.g. Art, Travel, Food, etc.
    credits_applied = models.IntegerField(default=10, help_text='Total number of credits applied to this item including any given by VeeU admin')
                                                                            # Records the total number of credits applied to the Item
    credits_left    = models.IntegerField(default=10, help_text='The number of credits still remaining to show the item')
                                                                            # Number of credits left (goes down each time item is viewed
    credits_gifted  = models.IntegerField(default=0, help_text='The number of credits this item has been gifted by other users')
                                                                            # Number of credits users have gifted to this item
    date_added      = models.DateTimeField(auto_now_add=True)               # When item was added
    active          = models.BooleanField(default=True, help_text='If you mark this item inactive please say why in the comment field. E.g. "Inapproriate content"')
                                                                            # True if item is available for showing
    comment         = models.CharField(max_length=100, blank=True)          # Comment to be applied if item is inactive to say why

    # Add defs here for model related functions

    # This to allow url to be a clickable link
    def item_url(self):
        return u'<a href="%s">%s</a>' % (self.url, self.url)
    item_url.allow_tags = True

    def __str__(self):
        return '%s: %s' % (self.owner, self.url)

# Record of which items have been viewed, when, and whether they were liked or not
class Seen(models.Model):
    item_id         = models.ForeignKey(Item, on_delete=models.CASCADE)     # id of the item that has been seen
    user_id         = models.ForeignKey(User, on_delete=models.CASCADE)     # id of user who viewed it
    date_seen       = models.DateTimeField(auto_now_add=True)               # When item was viewed
    liked           = models.BooleanField(help_text='If the item was liked this is set to true')
                                                                            # Flag True if item was liked

    # Add defs here for model related functions

我认为我需要使用的查询如下所示:

Item.objects.exclude(
    seen=Seen.objects.filter(
        user_id=23,
        item_id=<id of item from Item table>,
    ),
)

我不知道要替换什么,以便将 Item 表中的每个项目与 Seen 表中相同项目 ID 的条目进行比较。

【问题讨论】:

    标签: python django


    【解决方案1】:

    通过访问视图中的request 对象,您可以从Seen 表中获取当前用户的item_ids 列表,并使用Django 的in 运算符进行过滤。

    unseen_items = Item.objects.exclude(
        pk__in=Seen.objects.filter(user_id=request.user).values_list(
            'item_id', flat=True
        )
    )
    

    有关in 的信息请参阅here,有关values_list 的信息请参阅here

    【讨论】:

      猜你喜欢
      • 2014-02-21
      • 1970-01-01
      • 2015-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多