具有多对多关系的Django形式无法保存

时间:2022-10-04 16:05:55

I have a custom registration form for my users to add a profile on my app. However, a bug has recently popped up in that the form is not saving the information that is put into all the fields.

我有一个自定义注册表单供我的用户在我的应用上添加个人资料。但是,最近出现了一个错误,即表单没有保存放入所有字段的信息。

My user model, MyUser has a ManyToMany relationship with another model, Interest, and this is where the issues are arising. I am not sure if it is the RegistrationForm or the register view that is causing it, so I have included both below, as well as the model code. I also have a view for the users to update their profile, also included, once it is created, and this is working absolutely perfectly. This is the personal view. As I say, it is only the Interest field that is not being returned, even though it is being filled in on the registration page.

我的用户模型,MyUser与另一个模型,Interest有一个ManyToMany关系,这就是问题出现的地方。我不确定它是注册窗体还是引起它的寄存器视图,所以我在下面列出了它们以及模型代码。我还有一个视图,用户可以在创建后更新他们的个人资料,这也是非常完美的。这是个人观点。正如我所说的那样,只有兴趣字段才会返回,即使它正在注册页面上填写。

Any help or advice is much appreciated, thanks.

非常感谢任何帮助或建议,谢谢。

models.py

models.py

class Interest(models.Model):
    title = models.TextField()

    def __unicode__(self):
        return self.title

class MyUser(AbstractBaseUser):
    email = models.EmailField(
                        verbose_name='email address',
                        max_length=255,
                        unique=True,
                    )
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    date_of_birth = models.DateField()
    course = models.ForeignKey(Course, null=True)
    location = models.ForeignKey(Location, null=True)
    interests = models.ManyToManyField(Interest, null=True)
    bio = models.TextField(blank=True)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['date_of_birth']

views.py

views.py

def register(request):
    if request.method == 'POST':
        form = RegistrationForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('/friends/home/')
    else:
        form = RegistrationForm()

    template = "adduser.html"
    data = { 'form': form, }
    return render_to_response(template, data, context_instance=RequestContext(request))

@login_required(login_url='/friends/login/')
def personal(request):
    """
    Personal data of the user profile
    """
    profile = request.user

    if request.method == "POST":
        form = ProfileForm(request.POST, instance=profile)
        if form.is_valid():
            form.save()
            messages.add_message(request, messages.INFO, _("Your profile information has been updated successfully."))
            return redirect('/friends/success/')
    else:
        form = ProfileForm(instance=profile)

    template = "update_profile.html"
    data = { 'section': 'personal', 'form': form, }
    return render_to_response(template, data, context_instance=RequestContext(request))

forms.py

forms.py

class RegistrationForm(forms.ModelForm):
    """
    Form for registering a new account.
    """
    email = forms.EmailField(widget=forms.TextInput, label="Email")
    password1 = forms.CharField(widget=forms.PasswordInput,
                                label="Password")
    password2 = forms.CharField(widget=forms.PasswordInput,
                                label="Password (again)")
    course = forms.ModelChoiceField(queryset=Course.objects.order_by('title'))
    location = forms.ModelChoiceField(queryset=Location.objects.order_by('location'))

    class Meta:
        model = MyUser
        fields = [
            'first_name',
            'last_name',
            'date_of_birth',
            'email',
            'password1',
            'password2',
            'course',
            'location',
            'interests',
            'bio',
            ]

    def __init__(self, *args, **kwargs):#Sort interests alphabetically
        super(RegistrationForm, self).__init__(*args, **kwargs)
        self.fields['interests'].queryset = Interest.objects.order_by('title')

    def clean(self):
        cleaned_data = super(RegistrationForm, self).clean()
        if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:
            if self.cleaned_data['password1'] != self.cleaned_data['password2']:
                raise forms.ValidationError("Passwords don't match. Please enter again.")
        return self.cleaned_data

    def save(self, commit=True):
        user = super(RegistrationForm, self).save(commit=False)
        user.set_password(self.cleaned_data['password1'])
        if commit:
            user.save()
        return user

1 个解决方案

#1


19  

Since you use commit=false for the super(RegistrationForm, self).save call, it doesn't save the many-to-many field. You therefore need to add self.save_m2m() after user.save() in your save() method of RegistrationForm.

由于您对super(RegistrationForm,self).save调用使用commit = false,因此它不会保存多对多字段。因此,您需要在registrationForm的save()方法中的user.save()之后添加self.save_m2m()。

See https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method

请参阅https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method

EDIT: save_m2m() is on the Form, not the Model

编辑:save_m2m()在表单上,​​而不是模型

#1


19  

Since you use commit=false for the super(RegistrationForm, self).save call, it doesn't save the many-to-many field. You therefore need to add self.save_m2m() after user.save() in your save() method of RegistrationForm.

由于您对super(RegistrationForm,self).save调用使用commit = false,因此它不会保存多对多字段。因此,您需要在registrationForm的save()方法中的user.save()之后添加self.save_m2m()。

See https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method

请参阅https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method

EDIT: save_m2m() is on the Form, not the Model

编辑:save_m2m()在表单上,​​而不是模型