Django查询api:复杂子查询

时间:2017-10-08 13:17:51

标签: python sql django

我浪费了很多时间来尝试撰写此类查询。我的模特在这里:

class User(Dealer):
    pass


class Post(models.Model):
    text = models.CharField(max_length=500, default='')
    date = models.DateTimeField(default=timezone.now)
    interactions = models.ManyToManyField(User, through='UserPostInteraction', related_name='post_interaction')


class UserPostInteraction(models.Model):
    post = models.ForeignKey(Post, related_name='pppost')
    user = models.ForeignKey(User, related_name='uuuuser')
    status = models.SmallIntegerField()


    DISCARD = -1
    VIEWED = 0
    LIKED = 1
    DISLIKED = 2

我需要的是:

子查询是:(UserPostInteractions where status = LIKED) - (UserPostInteractions where status = DISLIKED) of Post(OuterRef('pk'))

查询是:Select all posts order by value of subquery

我遇到了错误Subquery returned multiple rows

ELP !!))

1 个答案:

答案 0 :(得分:0)

如果我理解你的需要,你可以通过这样的qs得到你需要的东西:

from django.db.models import Case, Sum, When, IntegerField

posts = Post.objects.values('id', 'text', 'date').annotate(
    rate=Sum(Case(
        When(pppost__status=1, then=1), 
        When(pppost__status=2, then=-1), 
        default=0, 
        output_field=IntegerField()
    ))
).order_by('rate')

在MySql中,它会在这样的sql查询中转换:

SELECT
  `yourapp_post`.`id`,
  `yourapp_post`.`text`,
  `yourapp_post`.`date`,
  SUM(
      CASE
        WHEN `yourapp_userpostinteraction`.`status` = 1
          THEN 1
        WHEN `yourapp_userpostinteraction`.`status` = 2
          THEN -1
        ELSE 0
      END) AS `rate`
FROM `yourapp_post`
  LEFT OUTER JOIN `yourapp_userpostinteraction` ON (`yourapp_post`.`id` = `yourapp_userpostinteraction`.`post_id`)
GROUP BY `yourapp_post`.`id`
ORDER BY `rate` ASC