简体   繁体   中英

How to exclude fields from form prefilled with object

How to exclude some fields from form created in view from instance? I want to allow users to edit their attributes like username or telephone but in this form, they shouldn't change their password.

I've tried this:

del user_profile_form.fields['telephone']

But it raises CSRF token missing or incorrect. when I do that.

@login_required
def edit_profile(request):
    user = request.user
    user_form = UserForm(instance=user)
    user_profile_form = UserProfileForm(instance=user.userprofile)

    context = {'user_form': user_form,
               'user_profile_form': user_profile_form}

    return render(request, 'auth/profiles/edit-profile.html', context=context)

FORMS.PY

class UserForm(forms.ModelForm):
    password1 = forms.CharField(widget=forms.PasswordInput())
    password2 = forms.CharField(widget=forms.PasswordInput())

    class Meta:
        model = User
        fields = ('username', 'email', 'password1','password2', 'first_name', 'last_name')

    def clean(self):
        password1 = self.cleaned_data.get('password1')
        password2 = self.cleaned_data.get('password2')

        if password1 and password1 != password2:
            raise forms.ValidationError("Passwords don't match")

        return self.cleaned_data

class UserProfileForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = ('telephone','marital_status','how_do_you_know_about_us')

MODELS.PY

class UserProfile(models.Model):
    user = models.OneToOneField(User,on_delete=models.CASCADE,related_name='userprofile')

    # ATRIBUTY KTORE BUDE MAT KAZDY
    telephone = models.CharField(max_length=40,null=True)

    HOW_DO_YOU_KNOW_ABOUT_US_CHOICES = (
            ('coincidence',u'It was coincidence'),
            ('relative_or_friends','From my relatives or friends'),
            )
    how_do_you_know_about_us = models.CharField(max_length=40, choices=HOW_DO_YOU_KNOW_ABOUT_US_CHOICES, null=True)

    MARITAL_STATUS_CHOICES = (
        ('single','Single'),
        ('married','Married'),
        ('separated','Separated'),
        ('divorced','Divorced'),
        ('widowed','Widowed'),
    )
    marital_status = models.CharField(max_length=40, choices=MARITAL_STATUS_CHOICES, null=True)

    # OD KIAL STE SA O NAS DOZVEDELI
    # A STAV

    def __unicode__(self):
        return '{} {}'.format(self.user.first_name,self.user.last_name)

    def __str__(self):
        return '{} {}'.format(self.user.first_name,self.user.last_name)

NEW VIEW

@login_required
def edit_profile(request):
    user = request.user
    if request.method == 'POST':
        user_form = UserForm(request.POST)
        user_profile_form = UserProfileForm(request)
        if user_form.is_valid() and user_profile_form.is_valid():
            user_form.save()
            user_profile_form.save()
            return HttpResponseRedirect('/logged-in')
        else:
            print user_form.errors
            print user_profile_form.errors

    else:
        user_form = UserForm(instance=user)
        user_profile_form = UserProfileForm(instance=user.userprofile)
        temp_user_profile_form = deepcopy(user_profile_form)
        del temp_user_profile_form.fields['password1']
        del temp_user_profile_form.fields['password2']
    context = {'user_form': user_form,
               'user_profile_form': temp_user_profile_form}

    return render(request, 'auth/profiles/edit-profile.html', context=context)

ERROR

Exception Type: KeyError
Exception Value:    
'password1'

It looks like you're referencing password1 and password2 in your Meta class for the UserForm model form. These should be removed, as they aren't fields in your User model. So after the change, your UserForm should be:

class UserForm(forms.ModelForm):
    # These 2 fields are unbound fields...
    password1 = forms.CharField(widget=forms.PasswordInput())
    password2 = forms.CharField(widget=forms.PasswordInput())

    class Meta:
        model = User
        # These fields are your User model's fields
        fields = ('username', 'email', 'first_name', 'last_name')

    def clean(self):
        password1 = self.cleaned_data.get('password1')
        password2 = self.cleaned_data.get('password2')

        if password1 and password1 != password2:
            raise forms.ValidationError("Passwords don't match")

        return self.cleaned_data

You don't need to remove them in the view. Just exclude them in the template.

Additionally, you can make the form fields hidden inputs in the __init__ method for your form if you'd like. I'd recommend this approach.

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