【问题标题】:map raw sql to django orm将原始 sql 映射到 django orm
【发布时间】:2010-11-12 03:53:08
【问题描述】:

有没有办法简化这个工作代码? 这段代码为一个对象获取所有不同的投票类型,大概有 20 种可能,并对每种类型进行计数。 我不喜欢编写原始 sql,而是使用 orm。这有点棘手,因为我在模型中使用了通用外键。

def get_object_votes(self, obj):
    """ 
    Get a dictionary mapping vote to votecount
    """
    ctype = ContentType.objects.get_for_model(obj)

    cursor = connection.cursor()
    cursor.execute("""
       SELECT v.vote , COUNT(*)
       FROM votes v
       WHERE %d = v.object_id AND %d = v.content_type_id
       GROUP BY 1
       ORDER BY 1 """ % ( obj.id, ctype.id )
    )
    votes = {}

    for row in cursor.fetchall():
       votes[row[0]] = row[1]

    return votes

我正在使用的模型

class Vote(models.Model):
    user = models.ForeignKey(User)

    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    payload = generic.GenericForeignKey('content_type', 'object_id')

    vote = models.IntegerField(choices = possible_votes.items() )


class Issue(models.Model):
    title = models.CharField( blank=True, max_length=200)

【问题讨论】:

    标签: python sql django orm django-models


    【解决方案1】:

    下面的代码对我有用!

    def get_object_votes(self, obj, all=False):
        """
        Get a dictionary mapping vote to votecount
        """
        object_id = obj._get_pk_val()
        ctype = ContentType.objects.get_for_model(obj)
        queryset = self.filter(content_type=ctype, object_id=object_id)
    
        if not all:
            queryset = queryset.filter(is_archived=False) # only pick active votes
    
        queryset = queryset.values('vote')
        queryset = queryset.annotate(vcount=Count("vote")).order_by()
    
        votes = {}
    
        for count in queryset:
            votes[count['vote']] = count['vcount']
    
        return votes
    

    【讨论】:

      【解决方案2】:

      是的,绝对使用 ORM。你真正应该在你的模型中做的是:

      class Obj(models.Model):
          #whatever the object has
      
      class Vote(models.Model):
          obj = models.ForeignKey(Obj) #this ties a vote to its object
      

      然后要从一个对象中获得所有选票,请将这些 Django 调用放在您的视图函数之一中:

      obj = Obj.objects.get(id=#the id)
      votes = obj.vote_set.all()
      

      从那里很容易看出如何计算它们(获取称为投票的列表的长度)。

      我建议阅读文档中的多对一关系,它非常方便。

      http://www.djangoproject.com/documentation/models/many_to_one/

      【讨论】:

      • 投票对象使用通用外键,我希望能够对任何对象进行投票。我也会添加模型代码。
      • 我猜你调查过外交关系?它们使您可以直接创建所需的特定对象。这个例子看起来可能有答案。 djangoproject.com/documentation/models/generic_relations
      猜你喜欢
      • 1970-01-01
      • 2010-10-20
      • 2020-10-21
      • 2019-04-03
      • 2022-08-18
      • 2019-06-11
      • 2019-08-05
      • 2017-10-02
      • 2020-06-11
      相关资源
      最近更新 更多