Django Models множественные отношения по внешнему ключу
Допустим, у меня есть модель, например,:
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")]
У нас есть и другая модель, например,:
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)
Как я могу создать отношение внешнего ключа от module
к topic
, используя три поля: date
, subject
и topic_id
?
Я хотел бы иметь такой формат, чтобы человеку, вставляющему в базу данных, не приходилось выяснять автогенерируемый id темы перед вставкой в таблицу модуля.
В одной теме много модулей, а в одном предмете много тем.
Измените свои отношения следующим образом:
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')
Тогда вы можете проверить subject
на наличие topic
следующим образом:
topic = Topic.objects.get('<topic-id>')
subject = topic.module.subject
Или найти все темы для данного модуля:
module = Module.objects.get('<module-id>')
topics = module.topics.all()
Если вы измените модель темы на эту, вы сможете подтвердить, что любой subject
на topic
должен совпадать с subject
на модуле следующим образом:
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)
Наконец, поле date
не является другой моделью, поэтому вам не нужно отношение foriegn key, вам действительно нужно только ограничение unique together, которое вы уже реализовали.