在 django 中获取具有多对多关系的复杂查询集

Posted

技术标签:

【中文标题】在 django 中获取具有多对多关系的复杂查询集【英文标题】:Getting complex query set with a many to many relationship in django 【发布时间】:2018-08-01 23:19:48 【问题描述】:

更新:

为了澄清起见,我觉得我需要通过 Placement 模型来获得我需要的结果,因为我需要该模型中的 order 字段。

我正在尝试获取属于某个部分的所有文章对象在一个问题的版本中。即使在查看了 django 2.x 的 documentation 之后,我也很困惑

我可以获取所有版本以及属于某个问题的所有部分,但我不知道如何获取与每个版本的部分相关的文章。

对于上下文,这是我在 django 视图 中的工作查询,没有获取文章:

def issue_edit_form(request, iid=0):
    latest = utils.get_latest()
    issue = Issue.objects.get(pk=iid)
    editions = issue.edition_set.all()
    sections = []
    for i in editions:
        sections.append(i.section_set.all().order_by("order"))
    return render(request, 'issue_editor.html', 'latest': latest, 'issue': issue, 'editions': editions,
                                                 'sections': sections, 'article_form':
                                                     ArticleForm)

这是我的models.py

class Issue(models.Model):
        volume = models.SmallIntegerField(default=0)
        issue = models.SmallIntegerField(default=0)
        issue_date = models.DateField()
        published = models.BooleanField(default=False)

        class Meta:
            verbose_name = "   Issue"

        def __str__(self):
            return "Vol. " + str(self.volume) + " Issue: " + str(self.issue) + ": " + str(self.issue_date)


class Edition(models.Model):
        edition = models.CharField(max_length=100)
        issue = models.ForeignKey(Issue, on_delete=models.CASCADE, null=True)

        class Meta:
            verbose_name = "  Edition"

        @property
        def issue__name(self):
            return self.issue.issue_date


        def __str__(self):
            return self.edition


class Section(models.Model):
        section_name = models.CharField(max_length=100)
        section_image = models.ImageField(blank=True, null=True)
        order = models.SmallIntegerField(default=1)
        section_hidden = models.BooleanField(default=False);
        edition = models.ForeignKey(Edition, on_delete=models.CASCADE, null=True)

        class Meta:
            verbose_name = " Section"

        def __str__(self):
            return self.section_name


class Article(models.Model):
        title = models.CharField(max_length=255)
        article_url = models.URLField()
        admin_description = models.CharField(max_length=255, blank=True)
        # article_order = models.SmallIntegerField(default=1)
        sections = models.ManyToManyField(Section, through="Placement")

        class Meta:
            verbose_name = "Article"

        def __str__(self):
            return self.title


class Placement(models.Model):
        article = models.ForeignKey(Article, on_delete=models.DO_NOTHING, null=True)
        section = models.ForeignKey(Section, on_delete=models.DO_NOTHING, null=True)
        order = models.SmallIntegerField(default=1)

【问题讨论】:

Article.objects.filter(section__edition__issue_id=issue_id) 将为您提供属于某个版本中某个部分的文章对象。您想按版本进一步分组吗? 谢谢尼哈尔!我希望输出在一个模板中,我可以在其中循环浏览文章并将它们放在他们的部分中,并将这些部分放在他们的版本中。那有意义吗?这是代表这一点的屏幕截图。 pasteboard.co/H8N2zTt.png“Regular”、“Parents”等是版本。 “AWARDS...”、“ALUMNI”等是这些部分。 嗨 Nihal,这给了我文章对象,但我需要通过 Placement 模型来获取文章所在部分的顺序。你知道我将如何通过 Placement 来获取我正在寻找的结果? 【参考方案1】:

因此,如果您想要每个部分的文章列表,您可以这样做

edition_sections = edition.section_set.all()
for section in edition_sections:
    articles = section.articles_set.all()

或者,如果您不需要单独处理文章集,这也应该可以工作

edition_sections = edition.section_set.all()
articles = Article.objects.filter(sections__in=edition_sections)

这部分文档中有一些很好的例子 https://docs.djangoproject.com/en/2.0/topics/db/models/#intermediary-manytomany

【讨论】:

这似乎不起作用。我需要进入放置模型中的“订单”字段。 Placement 模型具有文章所属的部分,包括其在该部分中的顺序。 好的。如果文章仅在部分内而不是其他方式,则可以仅将 ManyToManyField 替换为 ForeignField。但是无论如何,一旦您拥有文章,您是否会通过 article.placement.order 获得订单?

以上是关于在 django 中获取具有多对多关系的复杂查询集的主要内容,如果未能解决你的问题,请参考以下文章

从 Django QuerySet 中获取所有相关的多对多对象

根据特定的多对多关系过滤 Django 查询集

Django内联表单集通过另一个模型在多对多关系中过滤

Django 查询集过滤具有相同多对多字段的对象

在多对多关系对象django的对象中获取null

多对多关系的查询集按列表中的匹配数排序