2015-10-07 31 views
11

カスタムCreateView(CourseCreate)とUpdateView(CourseUpdate)を使用してコースを保存および更新しています。私はコースが保存されるときに行動を起こしたい。私は、新しいコースのインストラクターとユーザー(まだ存在しない場合)との間に新しい多対多の関係を作成します。Django CreateView:保存時にアクションを実行する方法

私はコースをコースとして保存し、course.facultyを使用してその新しい関係を作成します。これを実現させる最良の場所はどこですか?

私はビューでform_validでこれを実行しようとしていますが、form.instance.facultyにアクセスしようとするとエラーが発生します.cコースはまだ作成されていません(CourseCreateで)。エラーメッセージは次のようになります。

「コース:...」は、この多対多リレーションシップを使用する前に、「コース」フィールドの値を持つ必要があります。

また、CourseUpdateでは機能しません。アシストの関係は作成されません。フォームでこれを試してください。しかし、フォームにユーザー情報を取得する方法がわかりません。 ありがとうございます。

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) 
+0

は 'my_course = form.save(偽=コミット)' – Vingtoft

+0

@Vingtoftで 'my_course = form.instance'を交換してください、ありがとうございました。これを試してみると、新しいコースを作成するときにSave btnをクリックしても、同じエラーが表示されます。「このコースでは、この多対多の関係を使用する前にコース 'コース'の値を設定する必要があります。私は「コース」という言葉がどこから来るのかよく分かりません...私はコースという名前のクラスを持っていますが、「コース」という名前のフィールドはありません。私の見解には、コース"。 – Carrie

答えて

22

CreateViewUpdateViewためform_valid()メソッドは、フォームを保存し、その後、成功URLにリダイレクトします。 return super()を実行することはできません。保存されているオブジェクトとリダイレクトの間に物事を入れたいからです。

最初のオプションは、super()を呼び出しずに、2つの線を複製して表示することです。これの利点は、何が起こっているかは非常に明確であるということです。

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

2番目のオプションはsuper()を呼び出すために継続することですが、あなたが関係を更新した後まで、応答を返しません。これの利点は、super()のコードを複製していないことですが、短所は、何が起きているのか分かりません。つまり、super()に精通していない限りです。

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

うわー、ありがとう、これは働いている(私は透明性のための最初のオプションを持って行った)。私はドキュメンテーションを調べるのに多くの時間を費やしましたが、このようなことを自分で解決するのは難しいです。大変ありがとう@Alasdair! – Carrie

+1

個人的に私は最初のオプションも好む。喜んでそれは助けた:-) – Alasdair

0

私はDjango's Signalを使用することをお勧めします。これは、など、モデルに何かが発生したときにトリガーされるアクションです。または更新を保存します。このようにしてコードはきれいになり(フォーム処理ではビジネスロジックなし)、の後にを保存した後にのみトリガーされます。

#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 
関連する問題