Django ORM查询连接表然后分析

时间:2014-01-07 04:33:44

标签: python sql django django-orm

class Answer(models.Model):
    question = models.ForeignKey(Question)
    answer = models.CharField(max_length=30)


class Response(models.Model):
    answer = models.ForeignKey(Answer)
    user = models.ForeignKey(User)
    time = models.DateTimeField(auto_now_add=True)


class Profile(models.Model):
    GENDER_CHOICES = (
        ('M', 'Male'),
        ('F', 'Female'),
    )
    user = models.OneToOneField("auth.User")
    age = models.IntegerField(max_length=2)
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
    zipcode = models.IntegerField(max_length=5)
    state = models.CharField(max_length=15)

我有一个响应模型,它是每个用户的问题和个人资料模型的答案,并且想知道如何进行查询以获取每个用户答案的​​列表(它们对于每个用户的每个问题都是唯一的)和他们的个人资料。最后我想说的是,有多少比例的男性回答了一种方式,另外一种方式如何投票,等等。我能够查询每个问题投票的用户百分比,但还未能将其分解得更远。我如何进行查询以找到每个性别投票的答案的百分比?

如果我可以加入User上的Profile和Response表,我就可以制作一个numpy数组并对其进行分析,我认为这也很有帮助。

1 个答案:

答案 0 :(得分:3)

多对一魔术

当任何模型具有models.ForeignKey字段时,Django提供便利方法。有关详细信息,请参阅Many-To-One Relationships。查看此示例以查找what percentage of an answer each gender voted for?

特定Answeranswer

>>> answer.response_set.filter(user__profile__gender='M')
[<Repsonse 1>, <Repsonse 2>, <Repsonse 3>, ... ]

这将为您提供回答用户为男性的所有回复。

如果您只想知道统计信息而不关心返回的实际Response对象,您只需使用.count()方法,如下所示:

>>> queryset = answer.response_set.all()
>>> total_responses_for_answer = queryset.count()
>>> number_of_males = queryset.filter(user__profile__gender='M').count()
>>> print 'Percent', (number_of_males / float(total_responses_for_answer)) * 100
98.1

让我试着解释发生了什么。

response_set.filter()

model B的{​​{1}}字段指向models.ForeignKey时,Django使用model A关键字参数在related_name上创建一个特殊方法, model A中指向model B实例的关系。

如果未指定model A关键字,Django会将方法名称默认为related_name

在这种情况下,<relationship>_set模型上的answer字段未指定Response关键字参数,因此Django将方便方法related_name添加到response_set 1}}模型。

要查看选择Answer的所有Responses,请使用简单查询:

answer

如果您愿意,可以指定>>> answer.response_set.all() 来创建自己的关系方法。例如:

related_name

过滤器(用户_ 简档 _gender = 'M')

发生的第二点魔法就是你正在寻找的class Response(models.Model): ... answer = models.ForeignKey(Answer, related_name='responses') ... # and use the custom method name like so: >>> answer = Answer.objects.get(pk=pk) >>> answer.responses.all() JOINs返回response_set个对象的查询集。 Response模型有一个名为Response的字段。 user模型通过Profile字段Usermodels.OneToOne建立了关联,而user模型也包含该用户的性别(以及其他有趣的内容)。花哨的双下划线部分Profile只是说:

  

查找所有响应实例 WHERE 响应的用户的__个人资料的__性别等于'M'