【问题标题】:Autofill Django model fields when create instance of another model创建另一个模型的实例时自动填充 Django 模型字段
【发布时间】:2018-05-01 11:39:22
【问题描述】:

我有三个模型 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(例如,为所有问题创建行并将点设置为零)并且当我创建新的问题实例时将其添加到所有旧学生

【问题讨论】:

  • 你确定 OneToOneField,这意味着当一个studentAndQuestion 实例有一个question 时,其他实例不再能够拥有它。 ForeignKey 是让它工作所需的 + Django Signal
  • @Lemayzeur 我已经注意到了,谢谢!
  • 那么它现在工作了吗?
  • @Lemayzeur 是的 :)

标签: python django database-design


【解决方案1】:

您可以收听保存这些模型时发出的Post Save Signal,并在处理程序中进行所需的创建。此信号使用名为 created 的参数调用处理程序,如果创建了新记录,则该参数为 True

请参阅the documentation on signals 了解如何注册您的处理程序。 样例如下

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 约束失败”
  • 这可能是因为你在超级通话之前就这样做了...或者selfinstance 不相等,应该是self = super() 但感觉很奇怪
猜你喜欢
  • 2023-03-23
  • 2023-02-11
  • 1970-01-01
  • 2021-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-16
相关资源
最近更新 更多