#django #django-models #relationship
Вопрос:
Я разрабатываю приложение Django, которое помогает учителям наблюдать за учениками во время уроков. Я определил модели для Lesson
и Student
, а FocusGroup
также модель для студентов , которые будут наблюдаться во время заданного Lesson
, FocusGroup
Объект имеет поля для наблюдения Student
за поведением Lesson
. Во время этого наблюдения за выборкой студентов проводится наблюдение Lesson
, и наблюдения должны быть зарегистрированы в FocusGroup
полях. В рамках подготовки учителя к заданному Lesson
он назначает это Lesson
нескольким FocusGroup
экземплярам (представляющим Student
s). Теперь приложение должно гарантировать , что то же Student
самое будет назначено не более одного раза заданному Lesson
. Я уже делаю это в своем шаблоне, но я также хочу обеспечить уникальность на стороне сервера.
Диаграмма должна проиллюстрировать это: Мой вопрос в том, как я должен гарантировать Lesson
, что назначается одно и то же Student
не более одного раза.
Должен ли я сделать это в FocusGroup
модели или в представлении получателя? И как я должен обеспечить безопасность этих отношений в Django?
Моя нынешняя реализация проверяет FocusGroup
Lesson
уникальность, но при FocusGroup
создании новых экземпляров есть вероятность, что то же Student
самое представлено несколькими FocusGroup
экземплярами, назначенными для этого Lesson
.
models.py
from django.db.models.functions import Random
from django.db import models
from django.db.models.fields.related import ForeignKey
from django.db.models.fields import AutoField, BooleanField, CharField, DateField, DateTimeField, IntegerField, TextField, URLField
class Student(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False
)
name = models.CharField()
class Lesson(models.Model):
id = AutoField(primary_key=True)
afholdt = DateField(help_text='Planlagt / faktisk dato for modulet')
class FocusGroup(models.Model):
id = AutoField(primary_key=True)
student = models.ForeignKey('Student', on_delete=models.RESTRICT, null=True)
lesson = models.ForeignKey(
'Lesson',
models.SET_NULL,
blank=True,
null=True,
)
rand_rank = models.FloatField( # Used to randomize sampling of Students
validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
default=Random(),
editable=False,
null=False
)
score = IntegerField(blank=True, null=True)
Комментарии:
1. Модели, по-видимому, предполагают, что в каждой фокус-группе может быть только 1 студент.
2. @bdbd: Правильно, так что проверка пройдет без проблем. Проблема возникает, когда я назначил одного и того же студента нескольким экземплярам FocusGroup-проверка не поймает эту личность. Т. Е. моя модель как есть не проверяет идентификатор связанного объекта Студента (другого экземпляра FocusGroup, уже назначенного этой лекцией) при назначении лекции в FocusGroup.
3. В таком случае, я думаю, что использования
UniqueConstraint
будет достаточно. Итак:UniqueConstraint(fields=['student', 'lesson'], name='unique_lesson_to_student')
добавленоFocusGroup
. Это гарантирует, что урок будет назначен учащемуся только один раз, независимо от того, в какой фокус-группе.4. @bdbd Выглядит хорошо. Результат здесь для обратной связи, когда я его опробую.
5. Я выполнил заявление, рекомендованное @bdbd. Затем, после запуска
python manage.py makemigrations
, а затем... migrate
в приложении, я действительно получаю ожидаемую реакцию (приложение выдаетdjango.db.utils.IntegrityError: UNIQUE constraint failed: myapp_focusgroup.student_id, myapp_focusgroup.lecture_id
ошибку). Сделайте это ответом, и я приму его.
Ответ №1:
В этом случае должно быть достаточно определить a UniqueConstraint
, чтобы гарантировать, что учащимся будет назначен урок только один раз, независимо от фокус-группы, поэтому:
class FocusGroup(models.Model):
...
class Meta:
constraints = [
models.UniqueConstraint(fields=['student', 'lesson'], name='unique_lesson_to_student')
]