【问题标题】:Django remove duplicates in queryset and access their list of foreign keyDjango 删除查询集中的重复项并访问其外键列表
【发布时间】:2017-08-02 01:29:33
【问题描述】:

这是我的模型:

class Item(models.Model):
    title = models.TextField()    

class Storage(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    rating = models.IntegerField(blank=True, null=True)
    review = models.CharField(max_length=1500, blank=True, null=True)

class SocialProfile(models.Model):
    user = models.OneToOneField(User, unique=True)
    follows = models.ManyToManyField('self', related_name='followed_by', symmetrical=False)

假设有 4 个用户 A、B、C、D。用户 A 只关注 B 和 C。 我正在尝试查看以用户 A 身份登录时的视图。显示 B 和 C 拥有的项目列表(重复项仅显示一次)。在每个项目下,显示他们的总结和评级。

我这里有东西:(user = User A here)

//get a list of users that User A follows
followings = user.socialprofile.follows.all()
//get B and C's saved item, eliminate the duplicates 
context['following_saved_article'] = Item.objects.filter(storage__user__in=followings.values('user')).distinct()

//get a flat list of all users A follows
context['followings'] = list(followings.values_list('user', flat=True).order_by('user'))

然后在模板中:

{% for item in following_saved_item %}
    {{ item.title }}
    {% for x in item.storage_set.all %}
         {% if x.user_id in followings %}
              {{ x.review }} {{ x.rating }}
         {% endif %}
    {% endfor %}
{% endfor %}

这似乎太多余了,如果我想按用户评分对评论进行排序,我将非常困难。

有没有办法生成一个不同的 Item 实例列表,仅根据关注获取 storage_set,按评级或存储中的其他字段排序,然后将其传递给查看?谢谢

【问题讨论】:

    标签: django many-to-many django-queryset


    【解决方案1】:

    我认为自定义 Prefetch 对象可以解决问题

    followings = user.socialprofile.follows.all()
    
    items = Item.objects.filter(
                storage__user__in=followings.values('user')
            ).distinct().prefetch_related(
                models.Prefetch('storage_set',
                    queryset=Storage.objects.filter(
                       user__in=followings.values('user')
                    ),
                    to_attr='storage_from_followings'
                )
            )
    
    #in the template
    {% for item in items %}
        {{ item.title }}
        {% for x in item.storage_from_followings %}
            {{ x.review }} {{ x.rating }}
        {% endfor %}
    {% endfor %}
    

    【讨论】:

    • 哇,这个效果很好。谢谢。如果我想按评级订购存储,我应该在哪里添加 order_by。我试了几个地方,他们都会带回重复的
    • 您是否尝试修改Storage 查询集?即queryset=Storage.objects.filter(user__in=followings.values('user')).order_by('rating')
    • 我累了。在过滤器之前和之后。在此处添加它将删除 distinct() 函数。重复项会再次出现,加上存储结果未排序
    • 这听起来很奇怪,Storage 查询在Items 之后执行,所以它不会影响.distinct 子句。然而,另一种简单的方法是在模板内进行排序:{% for x in item.storage_from_followings|dictsort:"rating" %}
    • 你是对的,我不小心删除了查询中的 distinct() ......哎哟。好的,再次感谢您的帮助
    猜你喜欢
    • 2018-10-26
    • 2021-04-12
    • 2011-08-18
    • 1970-01-01
    • 2019-03-19
    • 2018-11-16
    • 2015-11-29
    • 2021-05-06
    • 1970-01-01
    相关资源
    最近更新 更多