在Django中模型创建时自动创建相关对象

wji*_*jin 12 python django django-models

我是Django的新手,请原谅我的无知:)

假设我有一个具有几个外键关系的模型,当我创建模型的实例时,我希望它自动为外键对象生成新实例.在这种情况下,我将课程注册建模为一个组,我将特定组作为模型上的外键引用.

class Course(models.Model):
    student_group = models.OneToOneField(Group, related_name="course_taken")
    teacher_group = models.OneToOneField(Group, related_name="course_taught")

    def clean(self):
        if self.id:
            try:
                self.student_group
            except Group.DoesNotExist:
                self.student_group, _ = Group.objects.get_or_create(name='_course_' + self.id + '_student')

            try:
                self.teacher_group
            except Group.DoesNotExist:
                self.teacher_group, _ = Group.objects.get_or_create(name='_course_' + self.id + '_teacher')
Run Code Online (Sandbox Code Playgroud)

看起来我可以挂钩模型的干净方法来做到这一点,但我希望能够将整个事情包装在一个事务中,这样如果以后无法创建课程,它就赢了不要创建相关的Group对象.有没有办法实现这个目标?

另外,我在这里做错了吗?Django提供了更好的方法吗?

wji*_*jin 8

最终我决定:

from django.db import models, transaction
class Course(models.Model):
    student_group = models.OneToOneField(Group, related_name="course_taken")

    @transaction.commit_on_success
    def save(self, *args, **kwargs):
        if not self.student_group_id:
            self.student_group, _ = Group.objects.get_or_create(name='_course_' + self.id + '_student')

        super(Course, self).save(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

编辑(2014/12/01):@Shasanoglu是正确的,上面的代码由于id尚未存在而无法正常工作.调用save 之后你必须做相关的对象创建(所以你调用super.save,创建相关的对象,更新这个对象并再次调用super.save - 不理想.那或者你从组名中省略了id,它就是精细).但最终,我完全将自动相关对象创建移出了模型.我在自定义表单的保存方法中完成了所有这一切,它更干净,并放弃在管理界面中使用此模型(这就是为什么我坚持在模型方法中首先执行所有这些操作)


Mac*_*Gol 6

您可以使用models.signals.post_save信号来处理这种情况:

from django.db import models

class Course(models.Model):
    student_group = models.OneToOneField(Group, related_name="course_taken")
    teacher_group = models.OneToOneField(Group, related_name="course_taught")


def create_course_groups(instance, created, raw, **kwargs):
    # Ignore fixtures and saves for existing courses.
    if not created or raw:
        return

    if not instance.student_group_id:
        group, _ = Group.objects.get_or_create(name='_course_' + self.id + '_student')
        instance.student_group = group

    if not instance.teacher_group_id:
        teacher_group, _ = Group.objects.get_or_create(name='_course_' + self.id + '_teacher')
        instance.teacher_group = teacher_group

    instance.save()

models.signals.post_save.connect(create_course_groups, sender=Course, dispatch_uid='create_course_groups')
Run Code Online (Sandbox Code Playgroud)