将原始SQL映射到Django ORM
有没有办法简化一下这个有效的代码?这个代码是用来获取一个对象的所有不同投票类型的,大概有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 个回答
0
当然,使用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()
从这里开始,你就可以很简单地计算投票的数量了(只需要获取名为votes的列表的长度)。
我建议你去看看文档中关于多对一关系的部分,这非常实用。
http://www.djangoproject.com/documentation/models/many_to_one/
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