Reputation: 7146
Suppose we have a base model:
class BaseModel(models.Model):
pass
with some subclasses:
class Submodel1(BaseModel):
some_field = models.TextField()
...
class Submodel9(BaseModel):
another_field = models.TextField()
Each submodel is defined in its own Django app. New apps with new submodels can appear.
We also have another model, let's call it RelatedModel
, which should have a one-to-one relation to BaseModel
:
class RelatedModel(models.Model):
the_thing = models.OneToOneField(BaseModel, null=True, blank=True)
Is it possible to do define such a relation if BaseModel.Meta.abstract == True
?
Or without defining BaseModel
at all?
I have posted some solutions as answers below, but they seem a bit ugly to me.
Upvotes: 6
Views: 4561
Reputation: 7146
https://stackoverflow.com/a/23547494/517316
Instead of putting the relation to RelatedModel
, it is possible to put it to Submodel1 .. Submodel9
.
class Submodel1(models.Model):
some_field = models.TextField()
related_model = models.OneToOneField(RelatedModel,
null=True, blank=True,
related_name='the_thing')
...
class Submodel9(models.Model):
another_field = models.TextField()
related_model = models.OneToOneField(RelatedModel,
null=True, blank=True,
related_name='the_thing')
Or, if we make BaseModel
abstract, we can define it right in BaseModel
:
class BaseModel(models.Model)
related_model = models.OneToOneField(RelatedModel,
null=True, blank=True,
related_name='the_thing')
class Meta:
abstract = True
This would allow accessing SubmodelX
from an instance of RelatedModel
using a field named the_thing
, just as in the multi-table inheritance example.
Upvotes: 4
Reputation: 7146
It is possible to achieve with GenericForeignKeys:
class RelatedModel(models.Model):
content_type_of_the_thing = models.ForeignKey(ContentType)
id_of_the_thing = models.PositiveIntegerField()
the_thing = GenericForeignKey('content_type_of_the_thing', 'id_of_the_thing')
class Meta:
unique_together = ('content_type_of_the_thing', 'id_of_the_thing')
# TODO: restrict `content_type_of_the_thing` by `Submodel1 .. Submodel9` somehow
# Take into account that new submodels can appear
Upvotes: 2