I want to add extra field which with value from 2nd level of related model. the problem is because the first level is one to many.
example Models:
class ModelA(BaseModel):
name=models.CharField()
class ModelB(BaseModel):
type=models.CharField(max_length=100, unique=True) #the value will be one of [x, y, z]
parent = models.ForeignKey('ModelA', related_name='related_models')
class ModelC(BaseModel):
ext = models.CharField(max_length=100, unique=True)
model_b = models.ForeignKey('ModelB', related_name='modelc')
example values of models
modelA = [
{'id': 1,'name': 'data1'},
{'id': 2,'name': 'data2'},
{'id': 3,'name': 'data3'},
{'id': 4,'name': 'data4'}
]
modelB = [
{'id': 1,'type': 'y', 'parent_id': 1},
{'id': 2,'type': 'z', 'parent_id': 1},
{'id': 3,'type': 'x', 'parent_id': 3},
{'id': 4,'type': 'z', 'parent_id': 3},
{'id': 5,'type': 'z', 'parent_id': 2},
]
modelC = [
{'id': 1, 'ext': 'juststr#1', 'model_b_id': 2},
{'id': 2, 'ext': 'juststr#2', 'model_b_id': 4},
]
expected output:
[
{'id': 1,'name': 'data1', 'mc_status': True},
{'id': 2,'name': 'data2', 'mc_status': False},
{'id': 3,'name': 'data3', 'mc_status': True},
{'id': 4,'name': 'data4', 'mc_status': False}
]
I've tried:
model_a = model_a.annotate(
mc_status=Case(
When(
Q('related_models__type'='z', 'related_models__modelc__isnull'=False),
then=True
),
default=Value(False),
output_field=BooleanField()
)
)
#wrong result :(
I don't know if the method I'm trying is correct or not, but obviously the result is wrong. I though its because the second level of the relationship between modelA to modelC tables is not one to one. if anyone knows how or have a reference it would be very useful thanks.|
update: finally I solve this problem, and the solution is
subquery_mb = ModelB.objects.filter(parent_id=OuterRef('pk'), modelc__isnull=False)
model_a = model_a.annotate(
mc_status=Exists(subquery_mb)
)
#this code is not tested and not exactly same with the real implemented code but same solution