У меня есть три модели Student, Question и StudentAndQuestion
class Student(models.Model):
class Meta:
verbose_name_plural = "Students"
name = models.CharField(max_length=150)
surname = models.CharField(max_length=150)
code = models.CharField(max_length=10)
# group = models.ForeignKey(Group,on_delete=models.CASCADE)
points = models.IntegerField(default=0)
class Question(models.Model):
class Meta:
verbose_name_plural = "Questions"
text = models.CharField(max_length=1500)
variants = models.CharField(max_length=1500)
theme = models.OneToOneField(Theme, on_delete=models.CASCADE)
anwser = models.CharField(max_length=1500)
class StudentAndQuestion(models.Model):
question = models.OneToOneField(Question,on_delete=models.CASCADE)
student = models.OneToOneField(Student,on_delete=models.CASCADE)
is_learned = models.BooleanField(default=0)
points = models.IntegerField(default=0)
Я хочу, чтобы Django заполнял StudentAndQuestion, когда я создаю новый экземпляр учеников (например, создаю строки для всех вопросов и устанавливаю точки на ноль), и когда я создаю новый экземпляр вопроса, добавляю его всем старым ученикам
@Lemayzeur, я уже заметил это, спасибо!
Так он работает сейчас?
@Lemayzeur ага :)
Вы можете прослушать Опубликовать сигнал сохранения, генерируемый при сохранении этих моделей, и выполнить необходимое создание в обработчике. Этот сигнал вызывает обработчик с аргументом created
, который является True
, если была создана новая запись.
Обратитесь к документация по сигналам, чтобы узнать, как зарегистрировать свои обработчики. Образец выглядит следующим образом
from django.db.models.signals import post_delete, post_save
from .models import Student, Question, StudentAndQuestion
def add_question_to_students(sender, instance, created, *args, **kwargs):
question = instance
if created:
StudentAndQuestion.objects.bulk_create([
StudentAndQuestion(question=question, student_id=student_id)
for student_id in Student.objects.values_list("id", flat=True)
])
def add_student_to_question(sender, instance, created, *args, **kwargs):
student = instance
if created:
StudentAndQuestion.objects.bulk_create([
StudentAndQuestion(question=question_id, student=student)
for question_id in Question.objects.values_list("id", flat=True)
])
post_save.connect(add_question_to_students, sender=Question)
post_save.connect(add_student_to_question, sender=Student)
В качестве альтернативы вы можете переопределить сохранение в обеих моделях, чтобы сделать то же самое.
class Question(models.Model):
....
def save(*args, **kwargs):
is_create = self.pk is None
instance = super().save(*args, **kwargs)
add_question_to_students(Question, self, is_created)
class Student(models.Model):
....
def save(*args, **kwargs):
is_create = self.pk is None
instance = super().save(*args, **kwargs)
add_student_to_question(Student, self, is_created)
Я считаю, что последнее более ясно, так как легче узнать, что все происходит при сохранении, но это может привести к циклическим зависимостям, если модели находятся в разных приложениях.
Я получил сообщение "NOT NULL constraint failed", используя второй метод.
Вероятно, это потому, что вы сделали это до супер звонка ... Или, может быть, self
и instance
не равны, и это должен был быть self = super()
, но это кажется странным
уверены ли вы в OneToOneField, это означает, что когда у экземпляра
studentAndQuestion
естьquestion
, другие экземпляры больше не могут его иметь.ForeignKey
- это то, что нужно для работы + Сигнал Django