Reputation: 8722
Let me explain. I have 2 tables which are child classes of another abstract table. The abstract table has a relationship to a model called Foo
. The related_name
is set dynamically. The code looks like this:
class Foo(models.Model):
...
class Parent(models.Model):
foo = models.ForeignKey(
Foo,
on_delete=models.CASCADE,
related_name='%(app_label)s_%(class)s_related'
)
...
def bar(self):
print('bar')
class Meta:
abstract = True
class ChildOne(Parent):
...
class ChildTwo(Parent):
...
Therefore, the related names become 'myapp_childone_related'
, and 'myapp_childtwo_related'
.
Now, lets say I want to call the bar()
method of all the objects from the ChildOne
and ChildTwo
model that is related to a Foo
object. There is a catch though, I want to it from with a class method of the Foo
model. Currently, I'm doing it like this:
class Foo(models.Model):
...
def call_bar(self):
references = ('childone', 'childtwo')
for ref in references:
children = getattr(self, f'myapp_{ref}_related').all()
for child in children:
child.bar()
This works fine, but honestly feels a bit hack-y, especially when dealing with more than two children classes. Is there a nicer, more Pythonic solution to this problem?
Edit: I decided not to mention previously that I wanted to call the bar()
method from within a class method of the Foo
model because I thought that it was unnecessary for this question. However, Daneil Roseman's answer suggested making a list of classes, which is a good solution, but it would not work within the class method, as the classes have not yet been defined at that point in the module. So mentioning that in this edit.
Upvotes: 0
Views: 74
Reputation: 599490
A related_name is only syntactic sugar for performing a query from the related class itself. So you should just do this explicitly:
child_classes = [ChildOne, ChildTwo]
for child_class in child_classes:
children = child_class.objects.filter(foo=foo)
Upvotes: 1