Reputation: 6042
I'm using Django 1.4.3 w/ Python 2.7 on Ubuntu 13.04. I've run into a problem and can't seem to find a solution.
I have a series of related models (through FK) and I need to filter through them in a complex way.
Suppose I have a model Car
that has Parts
. I can get all the parts as car.parts_set
. Each part has a M2M field excluded_price
to Price
, with related_name='excluded_prices'
.
If I create a new part I need to add prices to the part's excluded_price
where each price has excluded_parts
for every other part related to that car. I'm trying to create a filter to help me find these prices.
Essentially I want something like this:
parts_set = [part for part in car.parts_set.exclude(pk=new_part.pk)]
Price.objects.filter(excluded_parts__contains=parts_set)
Effectively I want to find all prices where the excluded_parts
is a super set of the specific car parts (excluding the new part, obviously).
I've found a nifty way to do this if the "parts_set" were a series of strings.
parts_set = [Q(excluded_parts__contains=part) for part in car.parts_set.exclude(pk=new_part.pk)]
Price.objects.filter(reduce(operator.and_, parts_set))
Unfortunately __contains
only works for strings with an SQL statement of LIKE
.
Are there any features in Django's ORM that support a __contains
type filter that treats the value as an object rather than a string?
Upvotes: 1
Views: 5475
Reputation: 37319
If I follow your question correctly, you can do this by iteratively building up constraints on the queryset:
parts_set = car.parts_set.exclude(pk=new_part.pk)
price_qs = Price.objects.all()
for part in parts_set:
price_qs = price_qs.filter(excluded_parts=part)
This will require that the prices in the final queryset have all parts from the parts_set result in their excluded_parts
field. They can have other parts as well. price_qs
should end up returning your desired results:
all prices where the excluded_parts is a super set of the specific car parts
I don't know of a better way to construct a query requiring that a many-to-many field must contain multiple specific values.
Upvotes: 1