【问题标题】:Django filter ManyToMany filed in queryDjango过滤查询中的ManyToMany字段
【发布时间】:2018-11-27 17:38:55
【问题描述】:

我需要在查询集中使用 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() 从 Packages 中创建一个字典列表,然后对其进行迭代并排除所有非活动产品。 你知道更优雅的方法吗?

【问题讨论】:

  • 你在使用 Django REST 框架吗?
  • @JPG,是的,但我想在没有序列化的情况下在常规 django 中制作

标签: django filter many-to-many


【解决方案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

【讨论】:

    【解决方案2】:

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

    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']]

    【讨论】:

    • 此代码过滤并显示包含所有活动产品的包。虽然我只需要在包中显示活动产品(以任何方式显示包)。不需要嵌套结构,只显示期望的概念。
    • @KuskoAndrew 更新了我的答案:)
    • 更新的代码做同样的事情。当我需要过滤产品时,它会过滤包裹。以任何方式显示包。但是包装中的产品必须是活跃的。如何过滤每个模型的 ManyToMany 字段?
    • filtered_result 将保留所需的结果
    猜你喜欢
    • 1970-01-01
    • 2021-06-07
    • 2012-04-19
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 1970-01-01
    • 2011-12-21
    相关资源
    最近更新 更多