I've factored out common attributes from two classes into an abstract base class, however I have another model that needs to reference either one of those classes. It's not possible to reference an ABC as it doesn't actually have a database table.
The following example should illustrate my problem:
class Answer(models.Model): ovramt = models.ForeignKey("Ovramt") question = models.ForeignKey("Question") answer = models.CharField(max_length=3, choices=(("yes","yes"),("no","no") ("NA","N/A")) likelihood = models.IntegerField(choices=LIKELY_CHOICES) consequence = models.IntegerField(choices=CONSEQUENCE_CHOICES) class Meta: abstract = True class Answer_A(Answer): resident = models.ForeignKey("Resident") def __unicode__(self): return u"%s - %s - %s" %(self.ovramt.ssa.name, self.resident, self.question) class Answer_B(Answer): def __unicode__(self): return u"%s - %s" %(self.ovramt.ssa.name, self.question) class Answer_Risk(models.Model): answer = models.ForeignKey("Answer") risk = models.CharField(max_length=200) def __unicode__(self): return self.risk
Answer_A and Answer_B are slightly different in that Answer_A also needs a FK relationship to another table. Answer_B may also require some specific attributes later. The problem would STILL exist if I had Answer_B be the superclass - and have Answer_A subclass or compose it.
A 'Risk' is the same whether it's Answer_A or Answer_B. I also have other models that need to reference an 'Answer' regardless of it's sub-type. How can this be done? How can you reference a type regardless of it's sub-type?
Update:
I was trying to avoid a join operation but I don't think I'm going to be able to. Would it be worth having the reference to 'Resident' in all 'Answer's and just nulling it where required? Or is that considered very bad practice?
What is ForeignKey in Django? ForeignKey is a Field (which represents a column in a database table), and it's used to create many-to-one relationships within tables. It's a standard practice in relational databases to connect data using ForeignKeys.
Introduction to Django Foreign Key. A foreign key is a process through which the fields of one table can be used in another table flexibly. So, two different tables can be easily linked by means of the foreign key. This linking of the two tables can be easily achieved by means of foreign key processes.
An abstract model is a base class in which you define fields you want to include in all child models. Django doesn't create any database table for abstract models. A database table is created for each child model, including the fields inherited from the abstract class and the ones defined in the child model.
Generic relations. Adding a foreign key from one of your own models to ContentType allows your model to effectively tie itself to another model class, as in the example of the Permission model above.
A generic relation seems to be the solution. But it will complicate things even further.
It seems to me; your model structure is already more complex than necessary. I would simply merge all three Answer
models into one. This way:
Answer_Risk
would work without modification.resident
to None (NULL) in case of an Answer_A
.resident == None
. (in other words; same functionality)One more thing; are your answers likely to have more than one risk? If they'll have none or one risk you should consider following alternative implementations:
Answer
class.My main concern is neither database structure nor performance (although these changes should improve performance) but code maintainability.
My gut would be to suggest removing the abstract modifier on the base class. You'll get the same model structure, but Answer will be it's own table. The downside of this is that if these are large tables and/or your queries are complex, queries against it could be noticeably slower.
Alternatively, you could keep your models as is, but replace the ForeignKey to Answer with a GenericForeignKey. What you lose in the syntactic sugar of model inheritance, you gain a bit in query speed.
I don't believe it's possible to reference an abstract base model by ForeignKey (or anything functionally the same).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With