通过两个查询集之间的多对多关系进行过滤

时间:2019-07-22 10:25:10

标签: django

我有3种不同的模式,活动,类别和部门。类别与活动之间存在多对多的关系,类别与部门之间(一类对一个部门)存在一对多的关系。

在某种形式下,我要获得部门(必填),我也可以得到类别(非必填字段)。我将其存储在会话中,然后我想选择所选类别(如果有)或部门中的所有活动。

选择一个类别就可以了,我只过滤了activity_have_category上的活动。但是对于只有扇区的情况,我无法正确过滤。

我尝试了一个非常类似的问题的解决方案,但是没有用...

Solution tried: activity.objects.filter(category__sector__sector_name =request.session['sector']['sector_name'])

Result: Cannot resolve keyword 'category' into field. Choices are: activities_have_category, activities_have_countries, activities_have_output_outcome_impact, activity_name, description, outcome_impact, output_outcome, product_service

What I would like to get in SQL:
SELECT  activity_name FROM activity WHERE activities_have_category IN (SELECT category_name FROM category WHERE category_sector = "sector selected")

class sector(models.Model):
    sector_name = models.CharField(max_length=255, primary_key=True)
    description = models.TextField()
    def __str__(self):
        return self.sector_name

class category(models.Model):
    category_name = models.CharField(max_length=255, primary_key=True)
    description = models.TextField()
    category_sector = models.ManyToManyField('sector')
    def __str__(self):
        return self.category_name


class activity(models.Model):
    activity_name = models.CharField(max_length=255, primary_key=True)
    description = models.TextField()
    product_service = models.TextField()
    output_outcome = models.TextField()
    outcome_impact = models.TextField()
    activities_have_category = models.ManyToManyField('category')
    activities_have_output_outcome_impact = models.ManyToManyField('output_outcome_impact')
    activities_have_countries = models.ManyToManyField('country')
    def __str__(self):
        return self.activity_name

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

该关系的名称为activities_have_category,此外,categorysector的关系为category_sector,因此您应该像这样查询:

activity.objects.filter(
    activities_have_category__category_sector__sector_name=request.session['sector']['sector_name']
)

鉴于还可以提供类别值,则可以像这样进行过滤:

activity.objects.filter(
    activities_have_category__category_sector__sector_name=request.session['sector']['sector_name'],
    activities_have_category__category_name=category_name
)

但是我强烈建议您使用短名称。通常情况下, not 不会在模型名称前加上名称,根据PEP-8,您应该对模型使用CamelCase,您还可能希望在此处创建一个抽象类,将其上拉常见字段,例如:

class NameDescModel(models.Model):
    name = models.CharField(max_length=255, primary_key=True)
    description = models.TextField()

    class Meta:
        abstract = True

    def __str__(self):
        return self.name

class Sector(NameDescModel):
    pass


class Category(NameDescModel):
    sectors = models.ManyToManyField('Sector')


class Activity(NameDescModel):
    product_service = models.TextField()
    output_outcome = models.TextField()
    outcome_impact = models.TextField()
    categories = models.ManyToManyField('Category')
    output_outcome_impacts = models.ManyToManyField('output_outcome_impact')
    countries = models.ManyToManyField('Country')

现在查询将如下所示:

Activity.objects.filter(
    categories__sectors__name=request.session['sector']['sector_name'],
    category__name=category_name
)