Dynamic model resolution in Django
I'm writing a reusable app with several abstract models. These models work together and that is all fine when they're normal concrete models. But when they're abstract and you want to work on a model that has not yet been defined in it's final used location it gets trickier.
The use case: The app is for competition logic. You participate in some kind of competition and then you win a prize and claim it.
So I got a Participant
that wins a Prize
and when the prize is won it'll create a Claim
object.
The logic for creating the claim has been put in Prize
but it doesn't have access to Claim
directly. So I added an attribute to my model that has the reference to Claim
.
from django.db import model
class ClaimClassResolution(object):
'''To fix object resolution dynamically add a class based off of the
current models app label
'''
_ClaimClass = None
@property
def ClaimClass(self):
if self._ClaimClass is None:
# self._meta.app_label is available on all models
self._ClaimClass = models.get_model(self._meta.app_label, 'Claim')
return self._ClaimClass
And then in my Prize.claim(...)
method where I used to do Claim.objects.create(...)
I now do self.ClaimClass.objects.create(...)
Worked like a charm and now my model is a little bit more dynamic.
The heavy lifting is done by django.db.models.get_model.
self._meta.app_label
is available on all models.