Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 865 Vote(s) - 3.49 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Django CreateView: How to perform action upon save

#1
I'm using a custom CreateView (CourseCreate) and UpdateView (CourseUpdate) to save and update a Course. 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. 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). The error message is like:

"Course: ..." needs to have a value for field "course" before this many-to-many relationship can be used.

It's also not working in CourseUpdate. The Assists relationship is not created. 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

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

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)
Reply

#2
The [`form_valid()`][1] method for `CreateView` and `UpdateView` saves the form, then redirects to the success url. It's not possible to do `return super()`, because you want to do stuff in between the object being saved and the redirect.

The first option is to not call `super()`, and duplicate the two lines in your view. 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. 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.

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

[To see links please register here]

Reply

#3
I would suggest to use Django's Signal. That is an action that gets triggered when something happens to a Model, like *save* or *update*. This way your code stays clean (no business logic in the form-handling), and you are sure that it only gets triggered after *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

Reply

#4
**It is possible to do return super()** as it is in the django doc:

[To see links please register here]


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)
Reply

#5
If you need to modify also the Course object when call save function use False and after change save the object

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

return HttpResponseRedirect(self.get_success_url())
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through