diff --git a/django/contrib/admin/templates/admin/auth/user/add_form.html b/django/contrib/admin/templates/admin/auth/user/add_form.html index 65824a6b7d..b57f59b82e 100644 --- a/django/contrib/admin/templates/admin/auth/user/add_form.html +++ b/django/contrib/admin/templates/admin/auth/user/add_form.html @@ -1,33 +1,11 @@ {% extends "admin/change_form.html" %} {% load i18n %} -{% block after_field_sets %} - -

{% trans "First, enter a username and password. Then, you'll be able to edit more user options." %}

- -
- -
- {{ form.username.errors }} - {# TODO: get required class on label_tag #} - {{ form.username }} -

{{ form.username.help_text }}

-
- -
- {{ form.password1.errors }} - {# TODO: get required class on label_tag #} - {{ form.password1 }} -
- -
- {{ form.password2.errors }} - {# TODO: get required class on label_tag #} - {{ form.password2 }} -

{% trans 'Enter the same password as above, for verification.' %}

-
- - - -
+{% block form_top %} +

{% trans "First, enter a username and password. Then, you'll be able to edit more user options." %}

+ +{% endblock %} + +{% block after_field_sets %} + {% endblock %} diff --git a/django/contrib/admin/templates/registration/password_change_form.html b/django/contrib/admin/templates/registration/password_change_form.html index 6d7a6609de..f5c1ca5208 100644 --- a/django/contrib/admin/templates/registration/password_change_form.html +++ b/django/contrib/admin/templates/registration/password_change_form.html @@ -1,26 +1,50 @@ {% extends "admin/base_site.html" %} -{% load i18n %} +{% load i18n adminmedia %} +{% block extrastyle %}{{ block.super }}{% endblock %} {% block userlinks %}{% url django-admindocs-docroot as docsroot %}{% if docsroot %}{% trans 'Documentation' %} / {% endif %} {% trans 'Change password' %} / {% trans 'Log out' %}{% endblock %} {% block breadcrumbs %}{% endblock %} {% block title %}{% trans 'Password change' %}{% endblock %} -{% block content %} +{% block content %}
+ +
{% csrf_token %} +
+{% if form.errors %} +

+ {% blocktrans count form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %} +

+{% endif %}

{% trans 'Password change' %}

{% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}

-{% csrf_token %} +
-{{ form.old_password.errors }} -

{{ form.old_password }}

-{{ form.new_password1.errors }} -

{{ form.new_password1 }}

+
+ {{ form.old_password.errors }} + {{ form.old_password }} +
+ +
+ {{ form.new_password1.errors }} + {{ form.new_password1 }} +
+ +
{{ form.new_password2.errors }} -

{{ form.new_password2 }}

+ {{ form.new_password2 }} +
-

- +
+ +
+ +
+ + +
+
{% endblock %} diff --git a/django/contrib/auth/admin.py b/django/contrib/auth/admin.py index a06e3786ba..ee871a2715 100644 --- a/django/contrib/auth/admin.py +++ b/django/contrib/auth/admin.py @@ -1,4 +1,5 @@ from django import template +from django.db import transaction from django.conf import settings from django.contrib import admin from django.contrib.auth.forms import UserCreationForm, UserChangeForm, AdminPasswordChangeForm @@ -10,6 +11,7 @@ from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext from django.utils.html import escape from django.utils.translation import ugettext, ugettext_lazy as _ +from django.views.decorators.csrf import csrf_protect class GroupAdmin(admin.ModelAdmin): search_fields = ('name',) @@ -17,6 +19,8 @@ class GroupAdmin(admin.ModelAdmin): filter_horizontal = ('permissions',) class UserAdmin(admin.ModelAdmin): + add_form_template = 'admin/auth/user/add_form.html' + change_user_password_template = None fieldsets = ( (None, {'fields': ('username', 'password')}), (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}), @@ -24,6 +28,12 @@ class UserAdmin(admin.ModelAdmin): (_('Important dates'), {'fields': ('last_login', 'date_joined')}), (_('Groups'), {'fields': ('groups',)}), ) + add_fieldsets = ( + (None, { + 'classes': ('wide',), + 'fields': ('username', 'password1', 'password2')} + ), + ) form = UserChangeForm add_form = UserCreationForm change_password_form = AdminPasswordChangeForm @@ -41,14 +51,34 @@ class UserAdmin(admin.ModelAdmin): if url.endswith('password'): return self.user_change_password(request, url.split('/')[0]) return super(UserAdmin, self).__call__(request, url) - + + def get_fieldsets(self, request, obj=None): + if not obj: + return self.add_fieldsets + return super(UserAdmin, self).get_fieldsets(request, obj) + + def get_form(self, request, obj=None, **kwargs): + """ + Use special form during user creation + """ + defaults = {} + if not obj: + defaults = { + 'form': UserCreationForm, + 'fields': ['username'], + } + defaults.update(kwargs) + return super(UserAdmin, self).get_form(request, obj, **defaults) + def get_urls(self): from django.conf.urls.defaults import patterns return patterns('', (r'^(\d+)/password/$', self.admin_site.admin_view(self.user_change_password)) ) + super(UserAdmin, self).get_urls() - def add_view(self, request): + @csrf_protect + @transaction.commit_on_success + def add_view(self, request, form_url='', extra_context=None): # It's an error for a user to have add permission but NOT change # permission for users. If we allowed such users to add users, they # could create superusers, which would mean they would essentially have @@ -61,41 +91,14 @@ class UserAdmin(admin.ModelAdmin): # error message. raise Http404('Your user does not have the "Change user" permission. In order to add users, Django requires that your user account have both the "Add user" and "Change user" permissions set.') raise PermissionDenied - if request.method == 'POST': - form = self.add_form(request.POST) - if form.is_valid(): - new_user = form.save() - msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': 'user', 'obj': new_user} - self.log_addition(request, new_user) - if "_addanother" in request.POST: - messages.success(request, msg) - return HttpResponseRedirect(request.path) - elif '_popup' in request.REQUEST: - return self.response_add(request, new_user) - else: - messages.success(request, msg + ' ' + - ugettext("You may edit it again below.")) - return HttpResponseRedirect('../%s/' % new_user.id) - else: - form = self.add_form() - return render_to_response('admin/auth/user/add_form.html', { - 'title': _('Add user'), - 'form': form, - 'is_popup': '_popup' in request.REQUEST, - 'add': True, - 'change': False, - 'has_add_permission': True, - 'has_delete_permission': False, - 'has_change_permission': True, - 'has_file_field': False, - 'has_absolute_url': False, + if extra_context is None: + extra_context = {} + defaults = { 'auto_populated_fields': (), - 'opts': self.model._meta, - 'save_as': False, 'username_help_text': self.model._meta.get_field('username').help_text, - 'root_path': self.admin_site.root_path, - 'app_label': self.model._meta.app_label, - }, context_instance=template.RequestContext(request)) + } + extra_context.update(defaults) + return super(UserAdmin, self).add_view(request, form_url, extra_context) def user_change_password(self, request, id): if not self.has_change_permission(request): @@ -110,8 +113,14 @@ class UserAdmin(admin.ModelAdmin): return HttpResponseRedirect('..') else: form = self.change_password_form(user) - return render_to_response('admin/auth/user/change_password.html', { + + fieldsets = [(None, {'fields': form.base_fields.keys()})] + adminForm = admin.helpers.AdminForm(form, fieldsets, {}) + print adminForm, form + + return render_to_response(self.change_user_password_template or 'admin/auth/user/change_password.html', { 'title': _('Change password: %s') % escape(user.username), + 'adminForm': adminForm, 'form': form, 'is_popup': '_popup' in request.REQUEST, 'add': True, diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py index 55e770e553..74b0f2ba8e 100644 --- a/django/contrib/auth/forms.py +++ b/django/contrib/auth/forms.py @@ -15,7 +15,8 @@ class UserCreationForm(forms.ModelForm): help_text = _("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."), error_message = _("This value must contain only letters, numbers and underscores.")) password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput) - password2 = forms.CharField(label=_("Password confirmation"), widget=forms.PasswordInput) + password2 = forms.CharField(label=_("Password confirmation"), widget=forms.PasswordInput, + help_text = _("Enter the same password as above, for verification.")) class Meta: model = User diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py index 7a20aaacd5..38d5dfe397 100644 --- a/tests/regressiontests/admin_views/tests.py +++ b/tests/regressiontests/admin_views/tests.py @@ -1795,27 +1795,30 @@ class IncompleteFormTest(TestCase): fixtures = ['admin-views-users.xml'] def setUp(self): - self.client.login(username='super', password='secret') + self.client.login(username='super', password='secret') def tearDown(self): - self.client.logout() + self.client.logout() def test_user_creation(self): - response = self.client.post('/test_admin/admin/auth/user/add/', { - 'username': 'newuser', - 'password1': 'newpassword', - 'password2': 'newpassword', - }) - new_user = User.objects.order_by('-id')[0] - self.assertRedirects(response, '/test_admin/admin/auth/user/%s/' % new_user.pk) - self.assertNotEquals(new_user.password, UNUSABLE_PASSWORD) + response = self.client.post('/test_admin/admin/auth/user/add/', { + 'username': 'newuser', + 'password1': 'newpassword', + 'password2': 'newpassword', + '_continue': '1', + }) + new_user = User.objects.order_by('-id')[0] + self.assertRedirects(response, '/test_admin/admin/auth/user/%s/' % new_user.pk) + self.assertNotEquals(new_user.password, UNUSABLE_PASSWORD) def test_password_mismatch(self): - response = self.client.post('/test_admin/admin/auth/user/add/', { - 'username': 'newuser', - 'password1': 'newpassword', - 'password2': 'mismatch', - }) - self.assertEquals(response.status_code, 200) - self.assert_('password' not in response.context['form'].errors) - self.assertFormError(response, 'form', 'password2', ["The two password fields didn't match."]) + response = self.client.post('/test_admin/admin/auth/user/add/', { + 'username': 'newuser', + 'password1': 'newpassword', + 'password2': 'mismatch', + }) + self.assertEquals(response.status_code, 200) + adminform = response.context['adminform'] + self.assert_('password' not in adminform.form.errors) + self.assertEquals(adminform.form.errors['password2'], + [u"The two password fields didn't match."])