Django — concatenate filter on a many_to_many relation create unexpected join

Question:

class ProductionOrderProductionOrderStatus(sf_models.BaseModel):
    production_order = models.ForeignKey(ProductionOrder, on_delete=models.CASCADE)
    production_order_status = models.ForeignKey(ProductionOrderStatus, on_delete=models.CASCADE)

class ProductionOrderStatus(sf_models.BaseModel):
    status = models.IntegerField(null=False)
    begin_datetime = models.DateTimeField(default=timezone.now)
    end_datetime = models.DateTimeField(null=True, blank=True)

class ProductionOrder(sf_models.BaseModel):
    statuses = models.ManyToManyField(ProductionOrderStatus, through='ProductionOrderProductionOrderStatus', related_name='production_orders')

if i concatenate 2 filter like this ->

ProductionOrder.objects.filter(statuses__status=2).filter(statuses__end_datetime=None)
i get this sql:

'SELECT ... FROM "production_order_productionorder" 
INNER JOIN "production_order_productionorderproductionorderstatus" ON ("production_order_productionorder"."id" = "production_order_productionorderproductionorderstatus"."production_order_id") 
INNER JOIN "production_order_productionorderstatus" ON ("production_order_productionorderproductionorderstatus"."production_order_status_id" = "production_order_productionorderstatus"."id") 
LEFT OUTER JOIN "production_order_productionorderproductionorderstatus" T4 ON ("production_order_productionorder"."id" = T4."production_order_id") 
LEFT OUTER JOIN "production_order_productionorderstatus" T5 ON (T4."production_order_status_id" = T5."id") 
WHERE ("production_order_productionorderstatus"."status" = 2 AND T5."end_datetime" IS NULL)'

if i put on the same filter like this ->

ProductionOrder.objects.filter(statuses__status=2, statuses__end_datetime=None) i get this sql:

'SELECT ... FROM "production_order_productionorder" 
INNER JOIN "production_order_productionorderproductionorderstatus" ON ("production_order_productionorder"."id" = "production_order_productionorderproductionorderstatus"."production_order_id") 
INNER JOIN "production_order_productionorderstatus" ON ("production_order_productionorderproductionorderstatus"."production_order_status_id" = "production_order_productionorderstatus"."id") 
WHERE ("production_order_productionorderstatus"."end_datetime" IS NULL AND "production_order_productionorderstatus"."status" = 2)'

if i have a queryset created with this condition: ProductionOrder.objects.filter(statuses__status=2) how can i concatenate the second condition?

is there a solution to get a dict of the already filtered condition? (to get for example {‘statuses__status’:2}, so i can concatenate the second condition and recreate the query)

Asked By: Proma17

||

Answers:

This is a "by-design" Django behavior -> see Django docs

Possible duplicate of Chaining multiple filter() in Django, is this a bug?

Answered By: JFox