Reputation: 390
I need to filter field with ManyToMany in queryset. There must stay only active Products
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)
I tried something like this.
packages = Package.objects.all()
for package in packages:
active_products = package.products.filter(active=True)
package.products = active_products
but it updates my packages in database, when i need only change queryset.
expectation concept (do not really need nested structure, query set is fine):
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': []}
]
I thought about creating a list of dictionaries from Packages by .values(), then iterate it and exclude all not active products. Do you know any more elegant way to do it?
Upvotes: 0
Views: 104
Reputation: 1024
I'm not sure if this will work. But I think that we can play using the serializers.MethodSerialier
. If it fails probably we can try to return another thing instead of the Productserializer
directly.
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
Upvotes: 1
Reputation: 88479
AFAIK, you won't get a nested output from Django :( But you will get something similar with .values()
method of QuerySet class as,
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']]
Upvotes: 1