Django m2m form save “ through ” table

前端 未结 4 634
春和景丽
春和景丽 2020-11-28 09:15

I\'m having trouble in saving a m2m data, containing a \'through\' class table. I want to save all selected members (selected in the form) in the through table. But i don\'t

4条回答
  •  失恋的感觉
    2020-11-28 10:01

    Like what dzida did, but use form.cleaned_data instead of request.post:

    def save_classroom(request):
        if request.method == 'POST':
            form = ClassroomForm(request.POST, request.FILES)
    
            if form.is_valid():
               new_obj = form.save(commit=False)
               new_obj.user = request.user
               new_obj.save()
    
               for member in form.cleaned_data['members'].all():
                    Membership.objects.create(member = member,  classroom = new_obj)
    
               return HttpResponseRedirect('/')
        else:
            form = ClassroomForm()
        return render_to_response('save_classroom.html', locals())
    

    You also need to consider some memberships might be deleted, so:

    def save_classroom(request):
        if request.method == 'POST':
            form = ClassroomForm(request.POST, request.FILES)
    
            if form.is_valid():
               new_obj = form.save(commit=False)
               new_obj.user = request.user
               new_obj.save()
    
               final_members = form.cleaned_data['members'].all()
               initial_members = form.initial['members'].all()
    
               # create and save new members
               for member in final_members:
                    if member not in initial_members:
                        Membership.objects.create(member = member,  classroom = new_obj)
    
               # delete old members that were removed from the form
               for member in initial_members:
                   if member not in final_members:
                       Membership.objects.filter(member = member, classroom = new_obj).delete()
    
               return HttpResponseRedirect('/')
        else:
            form = ClassroomForm()
        return render_to_response('save_classroom.html', locals())
    

    If you use model forms (like in a generic CBV: form_class=ClassroomForm), override and put the saving logic above in the save method, something like:

    ClassroomForm(forms.ModelForm):
        members = ModelMultipleChoiceField(
            queryset=Classroom.objects.all(),
            widget=SelectMultiple
        )
    
        def save(self, commit=True):
            classroom = super().save(commit=False)
                if commit:
                    classroom.save()
                    if 'members' in self.changed_data:
                       final_members = self.cleaned_data['members'].all()
                       initial_members = self.initial['members']
    
                       # create and save new members
                       for member in final_members:
                            if member not in initial_members:
                                Membership.objects.create(member = member,  classroom = new_obj)
    
                       # delete old members that were removed from the form
                       for member in initial_members:
                           if member not in final_members:
                               Membership.objects.filter(member = member, classroom = new_obj).delete()
    
             return classroom
    

提交回复
热议问题