How do I create a custom UserChangeForm that does not allow certain fields to be edited?

14,184

Solution 1

First: to limit which fields are in the form, follow the documentation. There are basically two options to filter fields: fields and exclude.

Second: you are always creating a new user. Initialize form with the User instance, not only you will be able to save a form, but you will have an initial data set.

Your view code should read:

# in the POST:
form = UserChangeForm(request.POST, instance=request.user)

# otherwise
form = UserChangeForm(instance=request.user)

and remove value assignment from the form.py.

Solution 2

This needs to be updated: You cannot exclude fields in UserChangeForm()

Too bad.

Solution 3

Three things. First of all, you should set self.fields['username'] to a form field, like forms.CharField(initial=self.instance.username). Second of all, you're using UserChangeForm instead of CustomUserChangeForm, in your view. And thirdly, http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#using-a-subset-of-fields-on-the-form (a proper link now, not one to someone's hard drive...

Solution 4

I think I'm pretty late on this one, but still I will post my bits for the sake of future readers.

class UserUpdateForm(UserChangeForm):
    password = None

    class Meta:
        model = CustomUser
        fields = ['username', 'email', 'first_name', 'last_name', 'description', ]
        widgets = {
            'description': forms.Textarea(attrs={'rows': 3}),
            'username': forms.TextInput(attrs={'readonly': 'readonly'}),
            'email': forms.TextInput(attrs={'readonly': 'readonly'})
        }

This will create a custom form with username and email fields as readonly as you do not want your users to change these unique fields once the user account has been created. It also prevents the password field to be displayed as it does not make sense to show hased password on profile page.

Solution 5

It looks like you have not read the documentation carefully.

Let me help you with that, check out using-a-subset-of-fields-on-the-form.

Basically you just need to add exclude = ('fieldname',) to your modelforms meta.

Share:
14,184

Related videos on Youtube

modocache
Author by

modocache

LLVM, Swift, and swift-corelibs-xctest committer. Creator of Quick, the Swift (and Objective-C) testing framework. Former Japanese literature translator.

Updated on June 04, 2022

Comments

  • modocache
    modocache almost 2 years

    This is my second post on SO, as well as my second post on Django--please be gentle.

    I am working on a simple User model. Users should be able to sign up for the site, and after signing up they should be able to change their account settings upon login. However, if I do the following, Users see a huge form with all kinds of info I don't want them to edit:

    views.py

    from django.shortcuts import render_to_response, get_object_or_404
    from django.core import urlresolvers
    from django.http import HttpResponseRedirect
    from django.template import RequestContext
    from django.contrib.auth.decorators import login_required
    from django.contrib.auth.forms import UserChangeForm
    
    @login_required 
    def settings( request, template_name = 'accounts/settings.html' ):
        """
        Processes requests for the settings page, where users
        can edit their profiles.
        """
        page_title = 'Account Settings'
        if request.method == 'POST':
            postdata = request.POST.copy()
            form = UserChangeForm( postdata )
            if form.is_valid():
                form.save()
        else:
            form = UserChangeForm()
        title = 'Settings'
        return render_to_response( template_name, locals(), context_instance = RequestContext( request) )
    

    As if that wasn't bad enough, this form doesn't allow any changes to be made, citing "User with this Username already exists" as an error. This confuses me--I am attempting to save a UserChangeForm, so wouldn't it already existing be a given?

    I've been looking online for a while now, attempting making my own custom forms, based on other questions I've seen on SO, like so:

    forms.py

    class CustomUserChangeForm( UserChangeForm ):
        def __init__( self, *args, **kwargs ):
            super( CustomUserChangeForm, self ).__init__( *args, **kwargs )
            if self.instance and self.instance.pk:
                # Since the pk is set this is not a new instance
                self.fields['username'] = self.instance.username
                self.fields['username'].widgets.attrs['readonly'] = True
    

    Unfortunately this hasn't worked out. I'm kind of at a loss as to what to do, so any help would be greatly appreciated. Below are my urls.py and template:

    urls.py

    urlpatterns = patterns('appname.accounts.views',
    
        url(r'^settings/$', 'settings', { 
                'template_name': 'accounts/settings.html' 
            }, 'settings'
        ),
    )
    

    template

    {% extends "accounts/base.html" %}
    
    {% block main %}
        <h1>Welcome, {{ request.user.pk }}{{ request.user.username }} to accounts.templates.accounts.settings.html.</h1>
        <h2>Here you can update your user settings. You can change your password <a href="{% url change_password %}">here</a>.</h2>
        <form action="." method="post" accept-charset="utf-8">
            {% csrf_token %}
            {{ form.as_p }}
            <p><input type="submit" value="Update &rarr;"></p>
        </form>
    {% endblock %}
    

    Thanks in advance for any help!

  • modocache
    modocache about 13 years
    Thanks for your help! I should have checked the documentation more thoroughly, sorry about that. As per your suggestions I changed the form to take an instance of User. However, it seems like when inheriting UserChangeForm, I can't exclude User.username. Regardless of whether I set fields in the Meta, or exclude it specifically, the username field shows up on the form. I am wondering whether it might have something to do with this ticket. Your thoughts?
  • modocache
    modocache about 13 years
    I'm really embarrassed that I missed docs that specifically address my question--thanks for your help!
  • Jerzyk
    Jerzyk about 13 years
    I've got same issue some time ago... it looks like first Meta class definitions in the class-chain is kept without override
  • codingjoe
    codingjoe almost 11 years
    That doesn't seem to be true. I found out you apparently can't exclude username and password neither through exclude nor fields. Any Ideas on how to achieve that?
  • Lutfar Rahman Milu
    Lutfar Rahman Milu about 8 years
    You can't exclude fields for UserChangeForm

Related