【问题标题】:How do I display only distinct objects in a queryset that have values in them?如何在查询集中仅显示具有值的不同对象?
【发布时间】:2012-11-04 20:07:31
【问题描述】:

我的数据库中保存了多个对象,但我只想在我的查询集中显示唯一的项目,并且如果它们实际上保存了一个项目。

models.py

class Everything(models.Model):
    profile = models.ForeignKey(User)
    playlist = models.CharField('Playlist', max_length = 2000, null=True, blank=True)
    platform = models.CharField('Platform', max_length = 2000, null=True, blank=True)
    video = models.CharField('VideoID', max_length = 2000, null=True, blank=True)
    def __unicode__(self):
        return u'%s %s %s %s' % (self.profile, self.playlist, self.platform, self.video)

views.py

playlist2 = Everything.objects.filter(profile=request.user)

模板

<select name ="playlist2">
{% for item in playlist2 %}
  <option value="{{item.playlist}}">{{item.playlist}}</option>
{% endfor %}
</select>

不必有播放列表,因为 null=True 和 blank=True。播放列表中的某些项目也可能重复。如何仅显示其中包含值的不同项目?

【问题讨论】:

    标签: python django templates view model


    【解决方案1】:

    您可以使用 excludedistinct 查询集函数 (docs)。

    但是,在您的情况下,这并不简单,因为您的 CharField 定义允许 NULL (null=True) 和空字符串 (blank=True) 值。这意味着您必须测试两个条件,为此您必须使用 Q (docs) 对象:

     everything = Everything.objects.exclude(Q(playlist=None) | Q(playlist='')).distinct()
    

    这正是 Django 文档不建议将 null=True 用于字符串模型字段 (docs) 的原因。摘录如下:

    避免在基于字符串的字段(例如 CharField 和 TextField 除非你有充分的理由。如果基于字符串的字段 有 null=True,这意味着它有两个可能的“无数据”值: NULL 和空字符串。在大多数情况下,有两个是多余的 “无数据”的可能值; Django 约定是使用空的 字符串,不为 NULL。

    如果您遵循这种转换,那么您的过滤器查找会变得更加简单:

     everything = Everything.objects.exclude(playlist=None).distinct()
    

    【讨论】:

    • 我有 2 个对象,它们在模型中具有不同的“视频”属性值,但具有相同的“播放列表”属性(命名为收藏夹)。如何只让收藏夹显示一次?使用上述解决方案,Favorites 仍然会出现两次,因为它们是不同的对象(它们对另一个属性具有不同的值)。提前致谢!
    • 为此,获取Everything 对象没有任何意义,因为此时您不是根据条件过滤它们,而是根据聚合条件过滤它们。要获得唯一的播放列表值,您可以执行Everything.objects.filter(...).exclude(...).values('playlist').distinct()
    【解决方案2】:

    您可以过滤掉所有的 null 和空白对象。

    playlist2 = Everything.objects.filter(playlist__isnull=False).exclude(playlist__exact='').distinct()
    

    如 miki725 所述,我编辑了上述内容以包括处理空白。不过可能不需要Q() 函数。并不是说Q() 函数有什么问题,我只是尽量避免使用它们以提高可读性。根据德摩根定理,NOT (playlist is null OR playlist is blank) 等价于(NOT playlist is null) AND (NOT playlist is blank)。我更喜欢filterexclude,但exclude 是空格所必需的,因为没有不相等的字段查找。你也可以exclude null 播放列表,但你不能做的是将排除合并到一个调用中,除非你使用 Q 函数,否则你会得到NOT (playlist is null AND playlist is blank),这是不等价的。

    【讨论】:

    • 这行不通,因为 Django 几乎总是将字符串存储为空字符串而不是 NULL,除非您以编程方式将字符串设置为 None 然后保存模型。请参阅我的答案以获得更好的解释。
    猜你喜欢
    • 1970-01-01
    • 2021-06-20
    • 2020-12-02
    • 2013-10-11
    • 2011-01-20
    • 2019-10-03
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多