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.

Back to Top