代码之家  ›  专栏  ›  技术社区  ›  Stephan

将原始sql映射到django orm

  •  1
  • Stephan  · 技术社区  · 15 年前

    有没有办法简化这个工作代码? 这段代码为一个对象获取所有不同的投票类型,可能有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)
    
    2 回复  |  直到 15 年前
        1
  •  1
  •   Stephan    15 年前

    下面的代码帮我搞定了!

    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
  •  0
  •   AlbertoPL    15 年前

    是的,一定要用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/