Django删除查询集中的重复项并访问其外键列表

时间:2017-03-11 19:45:31

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

这是我的模特:

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具有的项目列表(重复项仅显示一次)。在每个项目下,显示他们的摘要和评级。

我在这里有一些东西:(用户=用户A在这里)

//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,按等级或存储中的其他字段排序,并将其传递给查看?谢谢

1 个答案:

答案 0 :(得分:2)

我认为自定义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 %}