简体   繁体   中英

django inlineformset won't save

I presume I have missed something silly, but I can't make the inlineformset to work with me. I have a very similar code in my site, which works fine. The original code was for registration and I have tried to modify it so user-data could be updated/changed.

models.py

class Profiles(AbstractBaseUser):
    activation_key = Utils().activationKey()
    email = models.EmailField(verbose_name = 'email address', max_length = 255, unique = True)
    activation_code = models.CharField(max_length=40, default=activation_key)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)
    objects = ProfilesManager()

    USERNAME_FIELD = 'email'
    def get_email(self):
        return self.email
    def get_full_name(self):
        # The user is identified by their email address
        userdata = ProfileData.objects.get(uid_id=self.id)
        return userdata.full_name
    def get_short_name(self):
        # The user is identified by their email address
        return self.email
    def __str__(self):              # __unicode__ on Python 2
        return self.email
    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True
    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True
    def __unicode__(self):
        return u'%d' % self.id
    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin

class ProfileData(models.Model):
    profile = models.ForeignKey(Profiles)
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    full_name = models.CharField(max_length=100)
    image = models.ImageField(upload_to='media/user/avatar', blank=True, null=True)
    def get_first_name(self):
        return self.first_name
    def get_last_name(self):
        return self.last_name
    def get_full_name(self):
        return self.full_name
    def get_avatar(self):
        return self.image
    def save(self, *args, **kwargs):
        self.full_name = '{0} {1}'.format(self.first_name, self.last_name)
        super(ProfileData, self).save(*args, **kwargs)

views.py

class ProfileView(TemplateView):
    template_name = 'profiles/profile.html'
    form = ProfileDataForm
    formset = ProfileFormset
    def get(self, request, user_id):
        profile = ProfileData.objects.select_related('Profiles').filter(profile=user_id).first()
        if request.user.id and user_id:
            if int(request.user.id) is int(user_id):
                instance = ProfileData.objects.filter(profile=request.user).first()
                return render(request, self.template_name, {'form': self.form(instance=request.user), 'formset': self.formset(), 'profile': profile})
        else:
            return render(request, self.template_name, {'profile': profile})
    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    @method_decorator(api_view(['POST']))
    @transaction.non_atomic_requests
    def post(self, request, user_id):
        form = self.form(request.POST, instance=request.user)
        if form.is_valid():
            if form.data['password'] == form.data['conf_password']:
                transaction.set_autocommit(False)
                try:
                    profile = form.save(commit=False)
                    profile_formset = self.formset(request.POST, request.FILES, instance=profile)
                    if profile_formset.is_valid():
                        print 'formset is valid...'
                        profile.save()
                        profile_formset.save()
                finally:
                    transaction.set_autocommit(True)
            else:
                print 'Passwords doesn\'t match'
        else:
            print 'Form is not valid...'
        user = ProfileData.objects.select_related().filter(profile=user_id).first()
        return HttpResponseRedirect('/user/{0}/'.format(user_id))

forms.py

class ProfileDataForm(forms.ModelForm):
    email = forms.CharField(max_length=100, label='', widget=forms.TextInput(attrs={'placeholder': 'E-mail', 'class': 'form-control'}), required=False)
    password = forms.CharField(max_length=100, label='', widget=forms.PasswordInput(attrs={'placeholder': 'Password', 'class': 'form-control'}), required=False)
    conf_password = forms.CharField(max_length=100, label='', widget=forms.PasswordInput(attrs={'placeholder': 'Confirm Password', 'class': 'form-control'}), required=False)
    class Meta:
        model = Profiles
        fields = ['email', 'password', 'conf_password']
        exclude = ('full_name', 'image', )

    def clean_password2(self):
        # Check that the two password entries match
        password = self.cleaned_data.get('password')
        conf_password = self.cleaned_data.get('conf_password')
        if password and conf_password and password != conf_password:
            raise forms.ValidationError('Passwords don\'t match')
        return conf_password

    def save(self, commit=True):
        print 'saving form...'
        # Save the provided password in hashed format
        user = super(ProfileDataForm, self).save(commit=False)
        user.set_password(self.cleaned_data['password'])
        if commit:
            user.save()
        return user

ProfileFormset = inlineformset_factory(Profiles, ProfileData,
    exclude=('full_name', ),
    can_delete=False,
    extra=1,
    widgets={
        'first_name': forms.TextInput(attrs={'placeholder': 'First name', 'class': 'form-control'}),
        'last_name': forms.TextInput(attrs={'placeholder': 'Last name', 'class': 'form-control'}),
    },
    labels={
        'first_name': None,
        'last_name': None
    },
)

I have made sure to include everything, there is no error, the debug doesn't pop up and form is saved (views->ProfilesViews->post). Despite everything, the inlineform doesn't save. I have tried to make a custom def save(), without success.

the variable "form" in views is connected to Profiles while "profile_formset" is connected to ProfileData.

I am usually rubbish at asking questions here, I shall edit if you find me unclear.

Although this is not a solution, There are a few things to note here:
1) I didn't understand why you are using exclude after selecting the fields.
2) You are doing password matching twice in forms.py and views.py
3) In forms.py the method that validates field, as far as I know should be like clean_fieldname.
Please correct me if I'm wrong.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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