Skip to main content
 首页 » 编程设计

python之Django ORM Query 连接表然后分析

2024年08月28日28qq78292959

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) 

我有一个 Response 模型,它是每个用户的问题答案和 Profile 模型,我想知道如何进行查询以获得每个用户答案的​​列表(它们对于每个用户的每个问题都是唯一的)和他们的个人资料信息。最后我想说的是有多少人以一种方式回答了另一种方式,各州如何投票等等。我可以查询以查看有多少用户为每个问题投票,但无法进一步分割.我将如何进行查询以查找诸如每个性别投票给的答案的百分比之类的信息?

如果我可以加入 User 上的 Profile 和 Response 表,我将能够制作一个 numpy 数组并像那样分析它,我认为这也会很有帮助。

请您参考如下方法:

多对一魔法

当任何模型有 models.ForeignKey 时,Django 提供便利的方法 field 。参见 Many-To-One Relationships更多细节。查看此示例以查找 what percentage of an answer each gender voted for?

给定一个特定的 Answer作为answer :

>>> 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有一个 models.ForeignKey指向 model A 的字段, Django 使用 related_name在 model A 上创建特殊方法的关键字参数获取 model B 中的所有关系指向 model A实例。

如果related_name未指定关键字,Django 默认方法名称为 <relationship>_set .

在这种情况下,answer Response 上的字段型号未指定 related_name关键字参数,所以 Django 添加了便捷方法 response_set在 Answer 上模型。

查看全部Responses选择answer ,使用简单的查询:

>>> answer.response_set.all() 

如果需要,您可以指定 related_name创建自己的关系方法。例如:

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() 

过滤器(用户_个人资料_gender='M')

第二个魔法是 JOINs你正在寻找的。 response_set返回 Response 的查询集对象。 Response模型有一个名为 user 的字段. Profile模型与 User 有关系通过 models.OneToOne领域 user和 Profile模型还包含该用户的性别(和其他有趣的东西)。花哨的双下划线部分 user__profile__gender='M'只是在说:

Find all Response instances WHERE the Response's user's __ profile's __ gender equals 'M'