Reputation: 1343
I was trying to access the child object, through the parent object, as I want to perform different operations depending on the type of the object. What I have is:
#models.py
class A(models.Model):
...
class B(A):
field1 = models.CharField(...)
...
class C(A):
field2 = models.IntegerField(...)
I could perform 2 for loops and accomplish what I want:
for obj in B.objects.all():
if field1 == 'something':
do some operation
for obj in C.objects.all():
if field2 == 5:
do some other operation
But I was thinking, is it not possible to do this with 1 for loop and access the child through the parent?
for obj in A.objects.all():
if obj.b and obj.b.field1 == 'something':
do some operation
elif obj.c and obj.c.field2 == 5:
do some other operation
I also thought that select_related may do the trick, but it says it works only for ForeignKey
.
Moreover, I was hoping to get this done, without using additional apps such as django-model-utils or django-polymorphic, because I feel like there should be a simple query operation to do this.
Upvotes: 3
Views: 8191
Reputation: 146
Perhaps this may be useful for someone. hasattr
will return True
for the correct child instance, False
otherwise. Please note class name is in smallcase for hasattr
parameter.
for obj in A.objects.all():
if obj.hasattr('b'):
# do something specific to b
if obj.hasattr('c'):
# do something specific to c
Upvotes: 0
Reputation: 5482
You can get to a child object from parent like you did in the final for loop, but you'd also need to check if the child exists for parent like so:
for obj in A.objects.all():
try:
if obj.b.field1 == 'something':
do some operation
except ObjectDoesNotExist:
# obj does not have a child of class B
try:
if obj.c.field2 == 5:
do some other operation
except ObjectDoesNotExist:
# obj does not have a child of class C
You can also combine this into a single query using Q objects:
A.objects.filter(Q(b__isnull=False, b__field1='something') | Q(c__isnull=False, c__field2=5))
This would return objects of class A
Upvotes: 5