Django Models multiple foreign key relationship
say I have a model, e.g.,:
class Topic(models.Model):
date = models.DateField(null=False, blank=False)
subject = models.ForeignKey(Subject, blank=False, null=False, on_delete=models.CASCADE)
topic_id = models.PositiveIntegerField(null=False, blank=False)
aggregate_difficulty = models.PositiveIntegerField(null=False, blank=False)
class Meta:
constraints = [models.UniqueConstraint(fields=["subject", "date", "topic_id"], name="topic_unique")]
And we have another model, e.g.,:
class Module(models.Model):
date = models.DateField(null=False, blank=False)
subject = models.ForeignKey(Subject, blank=False, null=False, on_delete=models.CASCADE)
topic_id = models.PositiveIntegerField(null=False, blank=False)
content = models.TextField()
difficulty = models.PositiveIntegerField(null=False, blank=False)
How can I create a foreign key relationship from module
to topic
using the three fields: date
, subject
and topic_id
?
I would like to have this format, so the person inserting into the database would not have to find out the auto-generated topic id before inserting into the module table.
There are many modules to one topic and many topics to one subject.
Change your relations like so:
class Subject(models.Model):
...
class Module(models.Model):
subject = models.ForeightKey('Subject', ..., related_name='modules')
class Topic(models.Model):
module = models.ForeignKey('Module', ..., related_name='topics')
Then you can check a the subject
for a topic
like so:
topic = Topic.objects.get('<topic-id>')
subject = topic.module.subject
Or find all of the topics for a given module:
module = Module.objects.get('<module-id>')
topics = module.topics.all()
If you change the topic model to this, you can validate that any subject
on a topic
must match the subject
on a module like so:
from django.core.exceptions import ValidationError
class Topic(models.Model):
module = models.ForeignKey('Module', ..., related_name='topics')
subject = models.ForeignKey('Subject', ..., related_name='topics')
def save(self, *args, **kwargs):
if self.module.subject != self.subject:
raise ValidationError('The subject must match the subject on the module!')
return super().save(*args, **kwargs)
Finally, the date
field isn't another model, so you don't want a foriegn key relation, you really just want a unique together constraint, which you have already implemented.