简体   繁体   English

Django CreateView:如何在保存时执行操作

[英]Django CreateView: How to perform action upon save

I'm using a custom CreateView (CourseCreate) and UpdateView (CourseUpdate) to save and update a Course.我正在使用自定义 CreateView (CourseCreate) 和 UpdateView (CourseUpdate) 来保存和更新课程。 I want to take an action when the Course is saved.我想在保存课程时采取行动。 I will create a new many-to-many relationship between the instructor of the new course and the user (if it doesn't already exist).我将在新课程的讲师和用户之间创建一个新的多对多关系(如果它不存在的话)。

So, I want to save the Course as course, and then use course.faculty to create that new relationship.所以,我想将 Course 保存为 course,然后使用 course.faculty 创建新的关系。 Where is the best place to make this happen?实现这一目标的最佳地点在哪里?

I'm trying to do this in form_valid in the views, but I'm getting errors when trying to access form.instance.faculty bc the course isn't created yet (in CourseCreate).我试图在视图中的 form_valid 中执行此操作,但在尝试访问 form.instance.faculty 时出现错误,因为尚未创建课程(在 CourseCreate 中)。 The error message is like:错误信息如下:

"Course: ..." needs to have a value for field "course" before this many-to-many relationship can be used. "Course: ..." 需要为字段 "course" 设置一个值,然后才能使用这种多对多关系。

It's also not working in CourseUpdate.它在 CourseUpdate 中也不起作用。 The Assists relationship is not created.未创建 Assists 关系。 Should I be trying this in the Form?我应该在表格中尝试这个吗? But I'm not sure how to get the user info to the Form.但我不确定如何将用户信息获取到表单。 Thank you.谢谢你。

models.py模型.py

class Faculty(models.Model):
    last_name = models.CharField(max_length=20)

class Course(models.Model):
    class_title = models.CharField(max_length=120)
    faculty = models.ManyToManyField(Faculty)

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    faculty = models.ManyToManyField(Faculty, through='Assists')

class Assists(models.Model):
    user = models.ForeignKey(UserProfile)
    faculty = models.ForeignKey(Faculty)

views.py视图.py

class CourseCreate(CreateView):
    model = Course
    template_name = 'mcadb/course_form.html'
    form_class = CourseForm
    def form_valid(self, form):
        my_course = form.instance
        for f in my_course.faculty.all():
            a, created = Assists.objects.get_or_create(user=self.request.user.userprofile, faculty=f)
        return super(CourseCreate, self).form_valid(form)

class CourseUpdate(UpdateView):
    model = Course
    form_class = CourseForm
    def form_valid(self, form):
        my_course = form.instance
        for f in my_course.faculty.all():
            a, created = Assists.objects.get_or_create(user=self.request.user.userprofile, faculty=f)
        return super(CourseUpdate, self).form_valid(form)

The form_valid() method for CreateView and UpdateView saves the form, then redirects to the success url. CreateViewUpdateViewform_valid()方法保存表单,然后重定向到成功 url。 It's not possible to do return super() , because you want to do stuff in between the object being saved and the redirect. return super()是不可能的,因为你想在保存的对象和重定向之间做一些事情。

The first option is to not call super() , and duplicate the two lines in your view.第一个选项是不调用super() ,并在视图中复制这两行。 The advantage of this is that it's very clear what is going on.这样做的好处是非常清楚发生了什么。

def form_valid(self, form):
    self.object = form.save()
    # do something with self.object
    # remember the import: from django.http import HttpResponseRedirect
    return HttpResponseRedirect(self.get_success_url())

The second option is to continue to call super() , but don't return the response until after you have updated the relationship.第二种选择是继续调用super() ,但在更新关系之前不要返回响应。 The advantage of this is that you are not duplicating the code in super() , but the disadvantage is that it's not as clear what's going on, unless you are familiar with what super() does.这样做的好处是您不会复制super()中的代码,但缺点是不清楚发生了什么,除非您熟悉super()的作用。

def form_valid(self, form):
    response = super(CourseCreate, self).form_valid(form)
    # do something with self.object
    return response

I would suggest to use Django's Signal.我建议使用 Django 的 Signal。 That is an action that gets triggered when something happens to a Model, like save or update .这是当模型发生某些事情时触发的操作,例如saveupdate This way your code stays clean (no business logic in the form-handling), and you are sure that it only gets triggered after save .这样您的代码就可以保持干净(表单处理中没有业务逻辑),并且您确信它只会在save之后被触发。

#views.py
from django.dispatch import receiver
...

@receiver(post_save, sender=Course)
def post_save_course_dosomething(sender,instance, **kwargs):
    the_faculty = instance.faculty
    #...etc  

It is possible to do return super() as it is in the django doc: https://docs.djangoproject.com/en/4.0/topics/class-based-views/generic-editing/可以像在 django 文档中一样返回 super()https ://docs.djangoproject.com/en/4.0/topics/class-based-views/generic-editing/

def form_valid(self, form):
    # This method is called when valid form data has been POSTed.
    # It should return an HttpResponse.
    form.send_email()
    return super().form_valid(form)

If you need to modify also the Course object when call save function use False and after change save the object如果在调用保存函数时还需要修改 Course 对象,请使用 False 并在更改后保存对象

def form_valid(self, form):
    self.object = form.save(False)
    # make change at the object
    self.object.save()

    return HttpResponseRedirect(self.get_success_url())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM