Django ORM按2级外键关系获取数据

时间:2019-03-22 12:26:36

标签: python django django-models

我有以下型号:

class Project(models.Model):
     name = models.CharField(max_length=300, unique=True)
     description = models.CharField(max_length=2000)

class TemporaryUser(models.Model):
    username = models.CharField(max_length=400)
    project = models.ForeignKey(
        Project,
        on_delete=models.CASCADE,
        related_name='users'
    )

class QuestionSession(models.Model):
    project = models.ForeignKey(
        Project,
        on_delete=models.CASCADE,
        related_name='sessions',
        blank=True,
        null=True,
        default=None
    )

class Question(models.Model):
    # stores the main json object with all required information
    description = JSONField(
        max_length=10000, blank=True, null=True, default=None
    )

    question_session = models.ForeignKey(
        QuestionSession,
        on_delete=models.CASCADE,
        related_name='questions',
        blank=True,
        null=True,
        default=None
    )

class Answer(models.Model):
    question = models.ForeignKey(
        Question,
        related_name='answers_list',
        on_delete=models.CASCADE)

    answer = models.CharField(max_length=500)
    answered_by = models.ForeignKey(
        TemporaryUser,
        on_delete=models.CASCADE,
        related_name='answers',
        blank=True,
        null=True,
        default=None
    )
简而言之,我的应用程序包含问题,会话是问题的集合,而项目是会话的集合。每个用户在每个项目中都是唯一的。

我可以通过以下操作获取特定项目中的所有用户和所有答案:

TemporaryUser.objects.all().filter(project__id=project_id)

如何在会话中执行相同操作?我真的不知道该怎么做,我需要按会话过滤用户,有没有办法处理我的关系?

3 个答案:

答案 0 :(得分:2)

您的意思是:

TemporaryUser.objects.filter(project__sessions__id=id)

答案 1 :(得分:0)

我认为它的清洁器可以在此处使用reverse relation

session = QuestionSession.objects.first()
session.project.users.all()
# as User model has a FK with Project , and it has related_name="users"

您也可以在模板中使用它:

{% for qs in questionsessions %}  // questionsessions is the queryset of QuestionSession
     {% for user in qs.project.users.all %}
            {{ user.username }}
     {% endfor %}
{% endfor %}

答案 2 :(得分:0)

如果您只想通过一个查询获取用户,则方法是:

users = TemporaryUser.objects.filter(project__sessions=id)

但是,如果您想获取与该会话有关的更多数据,也许您应该考虑从会话本身获取(请参见Following relationships backward)。请谨慎,因为未优化对数据库的查询数量。

session = Session.objects.get(pk=id)
users = session.project.users.all()
questions = session.questions.all()

如果要减少查询,可以使用select_relatedprefetch_related。如果您有兴趣获取会话列表中的数据,而不仅仅是一个会话列表,那么这可能非常重要。