How do I create a custom UserChangeForm that does not allow certain fields to be edited?
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.
Related videos on Youtube
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, 2022Comments
-
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 →"></p> </form> {% endblock %}
Thanks in advance for any help!
-
modocache about 13 yearsThanks 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 about 13 yearsI'm really embarrassed that I missed docs that specifically address my question--thanks for your help!
-
Jerzyk about 13 yearsI've got same issue some time ago... it looks like first
Meta
class definitions in the class-chain is kept without override -
codingjoe almost 11 yearsThat doesn't seem to be true. I found out you apparently can't exclude
username
andpassword
neither throughexclude
norfields
. Any Ideas on how to achieve that? -
Lutfar Rahman Milu about 8 yearsYou can't exclude fields for UserChangeForm