Django过滤器ManyToMany在查询中提出

时间:2018-11-27 08:38:07

标签: django filter many-to-many

我需要使用queryset中的ManyToMany过滤字段。必须仅保留活动的产品

class Product(model.Model):
    name = models.CharField()
    active = models.BooleanField(blank=True, default=True)


class Package(model.Model):
    name = models.CharField()
    products = models.ManyToManyField(Product)

我尝试过类似的事情。

packages = Package.objects.all()
for package in packages:
    active_products = package.products.filter(active=True)
    package.products = active_products

但是当我只需要更改查询集时,它将更新数据库中的包。

期望概念(实际上不需要嵌套结构,查询集就可以了):

 packages = [
    {'id': 1, 'name': 'First package', 'products': [
        {'id': 1, 'name': 'first product', 'active': True},
        {'id': 2, 'name': 'second product', 'active': True},
    ]},
    {'id': 2, 'name': 'Second package', 'products': [
        {'id': 2, 'name': 'first product', 'active': True},
        {'id': 3, 'name': 'third product', 'active': True},
    ]},
    {'id': 3, 'name': 'Third package', 'products': []}

]

我考虑过要通过 .values()从“包”中创建字典列表,然后对其进行迭代并排除所有未激活的产品。 您知道更优雅的方式吗?

2 个答案:

答案 0 :(得分:1)

AFAIK,您不会从Django获得 嵌套输出 :(但是您会得到与 类似的 QuerySet 类的> .values() 方法为

results = Package.objects.filter(products__active=True).values('id', 'name', 'products__id', 'products__name', 'products__active')
filtered_result = [result for result in results if result['products__active']]

答案 1 :(得分:1)

我不确定这是否行得通。但是我认为我们可以使用serializers.MethodSerialier进行游戏。如果失败,我们可以尝试返回其他内容,而不是直接返回Productserializer

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ('id', 'name')


class PackageSerializer(serializers.ModelSerializer):
    products = serializers.MethodSerializer()

    class Meta:
        model = Package
        fields = ('id', 'name', 'products')

    def get_products(self, obj):
        products = obj.products.filter(active=True)
        return ProductSerializer(products, many=True)


packages = Package.objects.filter(products__active=True)
serializer = PackageSerializer(packages, many=True)
# do something with the serializer