1
0
mirror of https://github.com/django/django.git synced 2025-07-04 17:59:13 +00:00

newforms-admin: Fixed #6083 -- Updated django.contrib.auth to use newforms. A big thanks to Greg Turner, Michael Newman and Petr Marhoun.

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7191 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Brian Rosner 2008-03-03 20:37:41 +00:00
parent 61b9c8fe00
commit ba2d0feb72
10 changed files with 416 additions and 160 deletions

View File

@ -8,18 +8,21 @@
<fieldset class="module aligned"> <fieldset class="module aligned">
<div class="form-row"> <div class="form-row">
{{ form.username.html_error_list }} {{ form.username.errors }}
{# TODO: get required class on label_tag #}
<label for="id_username" class="required">{% trans 'Username' %}:</label> {{ form.username }} <label for="id_username" class="required">{% trans 'Username' %}:</label> {{ form.username }}
<p class="help">{{ username_help_text }}</p> <p class="help">{{ form.username.help_text }}</p>
</div> </div>
<div class="form-row"> <div class="form-row">
{{ form.password1.html_error_list }} {{ form.password1.errors }}
{# TODO: get required class on label_tag #}
<label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }} <label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }}
</div> </div>
<div class="form-row"> <div class="form-row">
{{ form.password2.html_error_list }} {{ form.password2.errors }}
{# TODO: get required class on label_tag #}
<label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }} <label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }}
<p class="help">{% trans 'Enter the same password as above, for verification.' %}</p> <p class="help">{% trans 'Enter the same password as above, for verification.' %}</p>
</div> </div>

View File

@ -18,9 +18,9 @@
<form action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %} <form action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %}
<div> <div>
{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %} {% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
{% if form.error_dict %} {% if form.errors %}
<p class="errornote"> <p class="errornote">
{% blocktrans count form.error_dict.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %} {% blocktrans count form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
</p> </p>
{% endif %} {% endif %}
@ -29,12 +29,14 @@
<fieldset class="module aligned"> <fieldset class="module aligned">
<div class="form-row"> <div class="form-row">
{{ form.password1.html_error_list }} {{ form.password1.errors }}
{# TODO: get required class on label_tag #}
<label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }} <label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }}
</div> </div>
<div class="form-row"> <div class="form-row">
{{ form.password2.html_error_list }} {{ form.password2.errors }}
{# TODO: get required class on label_tag #}
<label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }} <label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }}
<p class="help">{% trans 'Enter the same password as above, for verification.' %}</p> <p class="help">{% trans 'Enter the same password as above, for verification.' %}</p>
</div> </div>

View File

@ -27,12 +27,10 @@ class UserAdmin(admin.ModelAdmin):
def add_view(self, request): def add_view(self, request):
if not self.has_change_permission(request): if not self.has_change_permission(request):
raise PermissionDenied raise PermissionDenied
manipulator = UserCreationForm()
if request.method == 'POST': if request.method == 'POST':
new_data = request.POST.copy() form = UserCreationForm(request.POST)
errors = manipulator.get_validation_errors(new_data) if form.is_valid():
if not errors: new_user = form.save()
new_user = manipulator.save(new_data)
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': 'user', 'obj': new_user} msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': 'user', 'obj': new_user}
if "_addanother" in request.POST: if "_addanother" in request.POST:
request.user.message_set.create(message=msg) request.user.message_set.create(message=msg)
@ -41,8 +39,7 @@ class UserAdmin(admin.ModelAdmin):
request.user.message_set.create(message=msg + ' ' + ugettext("You may edit it again below.")) request.user.message_set.create(message=msg + ' ' + ugettext("You may edit it again below."))
return HttpResponseRedirect('../%s/' % new_user.id) return HttpResponseRedirect('../%s/' % new_user.id)
else: else:
errors = new_data = {} form = UserCreationForm()
form = oldforms.FormWrapper(manipulator, new_data, errors)
return render_to_response('admin/auth/user/add_form.html', { return render_to_response('admin/auth/user/add_form.html', {
'title': _('Add user'), 'title': _('Add user'),
'form': form, 'form': form,

View File

@ -3,63 +3,81 @@ from django.contrib.auth import authenticate
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.template import Context, loader from django.template import Context, loader
from django.core import validators from django.core import validators
from django import oldforms from django import newforms as forms
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
class UserCreationForm(oldforms.Manipulator): class UserCreationForm(forms.ModelForm):
"A form that creates a user, with no privileges, from the given username and password." """
def __init__(self): A form that creates a user, with no privileges, from the given username and password.
self.fields = ( """
oldforms.TextField(field_name='username', length=30, max_length=30, is_required=True, username = forms.RegexField(label=_("Username"), max_length=30, regex=r'^\w+$',
validator_list=[validators.isAlphaNumeric, self.isValidUsername]), help_text = _("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."),
oldforms.PasswordField(field_name='password1', length=30, max_length=60, is_required=True), error_message = _("This value must contain only letters, numbers and underscores."))
oldforms.PasswordField(field_name='password2', length=30, max_length=60, is_required=True, password1 = forms.CharField(label=_("Password"), max_length=60, widget=forms.PasswordInput)
validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]), password2 = forms.CharField(label=_("Password confirmation"), max_length=60, widget=forms.PasswordInput)
)
def isValidUsername(self, field_data, all_data): class Meta:
model = User
fields = ("username",)
def clean_username(self):
username = self.cleaned_data["username"]
try: try:
User.objects.get(username=field_data) User.objects.get(username=username)
except User.DoesNotExist: except User.DoesNotExist:
return return username
raise validators.ValidationError, _('A user with that username already exists.') raise forms.ValidationError(_("A user with that username already exists."))
def save(self, new_data): def clean_password2(self):
"Creates the user." password1 = self.cleaned_data["password1"]
return User.objects.create_user(new_data['username'], '', new_data['password1']) password2 = self.cleaned_data["password2"]
if password1 != password2:
raise forms.ValidationError(_("The two password fields didn't match."))
return password2
class AuthenticationForm(oldforms.Manipulator): def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class AuthenticationForm(forms.Form):
""" """
Base class for authenticating users. Extend this to get a form that accepts Base class for authenticating users. Extend this to get a form that accepts
username/password logins. username/password logins.
""" """
def __init__(self, request=None): username = forms.CharField(max_length=30)
password = forms.CharField(max_length=30, widget=forms.PasswordInput)
def __init__(self, request=None, *args, **kwargs):
""" """
If request is passed in, the manipulator will validate that cookies are If request is passed in, the form will validate that cookies are
enabled. Note that the request (a HttpRequest object) must have set a enabled. Note that the request (a HttpRequest object) must have set a
cookie with the key TEST_COOKIE_NAME and value TEST_COOKIE_VALUE before cookie with the key TEST_COOKIE_NAME and value TEST_COOKIE_VALUE before
running this validator. running this validation.
""" """
self.request = request self.request = request
self.fields = [
oldforms.TextField(field_name="username", length=15, max_length=30, is_required=True,
validator_list=[self.isValidUser, self.hasCookiesEnabled]),
oldforms.PasswordField(field_name="password", length=15, max_length=30, is_required=True),
]
self.user_cache = None self.user_cache = None
super(AuthenticationForm, self).__init__(*args, **kwargs)
def hasCookiesEnabled(self, field_data, all_data): def clean(self):
if self.request and not self.request.session.test_cookie_worked(): username = self.cleaned_data.get('username')
raise validators.ValidationError, _("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in.") password = self.cleaned_data.get('password')
def isValidUser(self, field_data, all_data): if username and password:
username = field_data
password = all_data.get('password', None)
self.user_cache = authenticate(username=username, password=password) self.user_cache = authenticate(username=username, password=password)
if self.user_cache is None: if self.user_cache is None:
raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.") raise forms.ValidationError(_("Please enter a correct username and password. Note that both fields are case-sensitive."))
elif not self.user_cache.is_active: elif not self.user_cache.is_active:
raise validators.ValidationError, _("This account is inactive.") raise forms.ValidationError(_("This account is inactive."))
# TODO: determine whether this should move to its own method.
if self.request:
if not self.request.session.test_cookie_worked():
raise forms.ValidationError(_("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."))
return self.cleaned_data
def get_user_id(self): def get_user_id(self):
if self.user_cache: if self.user_cache:
@ -69,22 +87,22 @@ class AuthenticationForm(oldforms.Manipulator):
def get_user(self): def get_user(self):
return self.user_cache return self.user_cache
class PasswordResetForm(oldforms.Manipulator): class PasswordResetForm(forms.Form):
"A form that lets a user request a password reset" email = forms.EmailField(max_length=40)
def __init__(self):
self.fields = (
oldforms.EmailField(field_name="email", length=40, is_required=True,
validator_list=[self.isValidUserEmail]),
)
def isValidUserEmail(self, new_data, all_data): def clean_email(self):
"Validates that a user exists with the given e-mail address" """
self.users_cache = list(User.objects.filter(email__iexact=new_data)) Validates that a user exists with the given e-mail address.
"""
email = self.cleaned_data["email"]
self.users_cache = User.objects.filter(email__iexact=email)
if len(self.users_cache) == 0: if len(self.users_cache) == 0:
raise validators.ValidationError, _("That e-mail address doesn't have an associated user account. Are you sure you've registered?") raise forms.ValidationError(_("That e-mail address doesn't have an associated user account. Are you sure you've registered?"))
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'): def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'):
"Calculates a new password randomly and sends it to the user" """
Calculates a new password randomly and sends it to the user.
"""
from django.core.mail import send_mail from django.core.mail import send_mail
for user in self.users_cache: for user in self.users_cache:
new_pass = User.objects.make_random_password() new_pass = User.objects.make_random_password()
@ -104,41 +122,68 @@ class PasswordResetForm(oldforms.Manipulator):
'site_name': site_name, 'site_name': site_name,
'user': user, 'user': user,
} }
send_mail(_('Password reset on %s') % site_name, t.render(Context(c)), None, [user.email]) send_mail(_("Password reset on %s") % site_name,
t.render(Context(c)), None, [user.email])
class PasswordChangeForm(oldforms.Manipulator): class PasswordChangeForm(forms.Form):
"A form that lets a user change his password." """
def __init__(self, user): A form that lets a user change his/her password.
"""
old_password = forms.CharField(max_length=30, widget=forms.PasswordInput)
new_password1 = forms.CharField(max_length=30, widget=forms.PasswordInput)
new_password2 = forms.CharField(max_length=30, widget=forms.PasswordInput)
def __init__(self, user, *args, **kwargs):
self.user = user self.user = user
self.fields = ( super(PasswordChangeForm, self).__init__(*args, **kwargs)
oldforms.PasswordField(field_name="old_password", length=30, max_length=30, is_required=True,
validator_list=[self.isValidOldPassword]),
oldforms.PasswordField(field_name="new_password1", length=30, max_length=30, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('new_password2', _("The two 'new password' fields didn't match."))]),
oldforms.PasswordField(field_name="new_password2", length=30, max_length=30, is_required=True),
)
def isValidOldPassword(self, new_data, all_data): def clean_old_password(self):
"Validates that the old_password field is correct." """
if not self.user.check_password(new_data): Validates that the old_password field is correct.
raise validators.ValidationError, _("Your old password was entered incorrectly. Please enter it again.") """
old_password = self.cleaned_data["old_password"]
if not self.user.check_password(old_password):
raise forms.ValidationError(_("Your old password was entered incorrectly. Please enter it again."))
return old_password
def save(self, new_data): def clean_new_password2(self):
"Saves the new password." password1 = self.cleaned_data.get('new_password1')
self.user.set_password(new_data['new_password1']) password2 = self.cleaned_data.get('new_password2')
if password1 and password2:
if password1 != password2:
raise forms.ValidationError(_("The two password fields didn't match."))
return password2
def save(self, commit=True):
self.user.set_password(self.cleaned_data['new_password1'])
if commit:
self.user.save() self.user.save()
return self.user
class AdminPasswordChangeForm(oldforms.Manipulator): class AdminPasswordChangeForm(forms.Form):
"A form used to change the password of a user in the admin interface." """
def __init__(self, user): A form used to change the password of a user in the admin interface.
"""
password1 = forms.CharField(max_length=60, widget=forms.PasswordInput)
password2 = forms.CharField(max_length=60, widget=forms.PasswordInput)
def __init__(self, user, *args, **kwargs):
self.user = user self.user = user
self.fields = ( super(AdminPasswordChangeForm, self).__init__(*args, **kwargs)
oldforms.PasswordField(field_name='password1', length=30, max_length=60, is_required=True),
oldforms.PasswordField(field_name='password2', length=30, max_length=60, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
)
def save(self, new_data): def clean_password2(self):
"Saves the new password." password1 = self.cleaned_data.get('password1')
self.user.set_password(new_data['password1']) password2 = self.cleaned_data.get('password2')
if password1 and password2:
if password1 != password2:
raise forms.ValidationError(_("The two password fields didn't match."))
return password2
def save(self, commit=True):
"""
Saves the new password.
"""
self.user.set_password(self.cleaned_data["password1"])
if commit:
self.user.save() self.user.save()
return self.user

View File

@ -0,0 +1,8 @@
from django.contrib.auth.tests.basic import BASIC_TESTS
from django.contrib.auth.tests.forms import FORM_TESTS, PasswordResetFormTestCase
__test__ = {
'BASIC_TESTS': BASIC_TESTS,
'PASSWORDRESET_TESTS': PasswordResetFormTestCase,
'FORM_TESTS': FORM_TESTS,
}

View File

@ -1,5 +1,6 @@
"""
>>> from models import User, AnonymousUser BASIC_TESTS = """
>>> from django.contrib.auth.models import User, AnonymousUser
>>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw') >>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
>>> u.has_usable_password() >>> u.has_usable_password()
True True

View File

@ -0,0 +1,164 @@
from django.core import mail
from django.test import TestCase
from django.contrib.auth.models import User
from django.contrib.auth.forms import PasswordResetForm
class PasswordResetFormTestCase(TestCase):
def testValidUser(self):
data = {
'email': 'nonexistent@example.com',
}
form = PasswordResetForm(data)
self.assertEqual(form.is_valid(), False)
self.assertEqual(form["email"].errors, [u"That e-mail address doesn't have an associated user account. Are you sure you've registered?"])
def testEmail(self):
# TODO: remove my email address from the test ;)
User.objects.create_user('atestuser', 'atestuser@example.com', 'test789')
data = {
'email': 'atestuser@example.com',
}
form = PasswordResetForm(data)
self.assertEqual(form.is_valid(), True)
# TODO: look at why using contrib.sites breaks other tests
form.save(domain_override="example.com")
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, u'Password reset on example.com')
# TODO: test mail body. need to figure out a way to get the password in plain text
# self.assertEqual(mail.outbox[0].body, '')
FORM_TESTS = """
>>> from django.contrib.auth.models import User
>>> from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
>>> from django.contrib.auth.forms import PasswordChangeForm
The user already exists.
>>> user = User.objects.create_user("jsmith", "jsmith@example.com", "test123")
>>> data = {
... 'username': 'jsmith',
... 'password1': 'test123',
... 'password2': 'test123',
... }
>>> form = UserCreationForm(data)
>>> form.is_valid()
False
>>> form["username"].errors
[u'A user with that username already exists.']
The username contains invalid data.
>>> data = {
... 'username': 'jsmith@example.com',
... 'password1': 'test123',
... 'password2': 'test123',
... }
>>> form = UserCreationForm(data)
>>> form.is_valid()
False
>>> form["username"].errors
[u'This value must contain only letters, numbers and underscores.']
The verification password is incorrect.
>>> data = {
... 'username': 'jsmith2',
... 'password1': 'test123',
... 'password2': 'test',
... }
>>> form = UserCreationForm(data)
>>> form.is_valid()
False
>>> form["password2"].errors
[u"The two password fields didn't match."]
The success case.
>>> data = {
... 'username': 'jsmith2',
... 'password1': 'test123',
... 'password2': 'test123',
... }
>>> form = UserCreationForm(data)
>>> form.is_valid()
True
>>> form.save()
<User: jsmith2>
The user submits an invalid username.
>>> data = {
... 'username': 'jsmith_does_not_exist',
... 'password': 'test123',
... }
>>> form = AuthenticationForm(None, data)
>>> form.is_valid()
False
>>> form.non_field_errors()
[u'Please enter a correct username and password. Note that both fields are case-sensitive.']
The user is inactive.
>>> data = {
... 'username': 'jsmith',
... 'password': 'test123',
... }
>>> user.is_active = False
>>> user.save()
>>> form = AuthenticationForm(None, data)
>>> form.is_valid()
False
>>> form.non_field_errors()
[u'This account is inactive.']
>>> user.is_active = True
>>> user.save()
The success case
>>> form = AuthenticationForm(None, data)
>>> form.is_valid()
True
>>> form.non_field_errors()
[]
The old password is incorrect.
>>> data = {
... 'old_password': 'test',
... 'new_password1': 'abc123',
... 'new_password2': 'abc123',
... }
>>> form = PasswordChangeForm(user, data)
>>> form.is_valid()
False
>>> form["old_password"].errors
[u'Your old password was entered incorrectly. Please enter it again.']
The two new passwords do not match.
>>> data = {
... 'old_password': 'test123',
... 'new_password1': 'abc123',
... 'new_password2': 'abc',
... }
>>> form = PasswordChangeForm(user, data)
>>> form.is_valid()
False
>>> form["new_password2"].errors
[u"The two password fields didn't match."]
The success case.
>>> data = {
... 'old_password': 'test123',
... 'new_password1': 'abc123',
... 'new_password2': 'abc123',
... }
>>> form = PasswordChangeForm(user, data)
>>> form.is_valid()
True
"""

View File

@ -1,7 +1,6 @@
from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.forms import PasswordResetForm, PasswordChangeForm, AdminPasswordChangeForm from django.contrib.auth.forms import PasswordResetForm, PasswordChangeForm, AdminPasswordChangeForm
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django import oldforms
from django.shortcuts import render_to_response, get_object_or_404 from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext from django.template import RequestContext
from django.contrib.sites.models import Site, RequestSite from django.contrib.sites.models import Site, RequestSite
@ -14,30 +13,27 @@ from django.contrib.auth.models import User
def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME): def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME):
"Displays the login form and handles the login action." "Displays the login form and handles the login action."
manipulator = AuthenticationForm(request)
redirect_to = request.REQUEST.get(redirect_field_name, '') redirect_to = request.REQUEST.get(redirect_field_name, '')
if request.POST: if request.method == "POST":
errors = manipulator.get_validation_errors(request.POST) form = AuthenticationForm(request, request.POST)
if not errors: if form.is_valid():
# Light security check -- make sure redirect_to isn't garbage. # Light security check -- make sure redirect_to isn't garbage.
if not redirect_to or '//' in redirect_to or ' ' in redirect_to: if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
from django.conf import settings from django.conf import settings
redirect_to = settings.LOGIN_REDIRECT_URL redirect_to = settings.LOGIN_REDIRECT_URL
from django.contrib.auth import login from django.contrib.auth import login
login(request, manipulator.get_user()) login(request, form.get_user())
request.session.delete_test_cookie() request.session.delete_test_cookie()
return HttpResponseRedirect(redirect_to) return HttpResponseRedirect(redirect_to)
else: else:
errors = {} form = AuthenticationForm(request)
request.session.set_test_cookie() request.session.set_test_cookie()
if Site._meta.installed: if Site._meta.installed:
current_site = Site.objects.get_current() current_site = Site.objects.get_current()
else: else:
current_site = RequestSite(request) current_site = RequestSite(request)
return render_to_response(template_name, { return render_to_response(template_name, {
'form': oldforms.FormWrapper(manipulator, request.POST, errors), 'form': form,
redirect_field_name: redirect_to, redirect_field_name: redirect_to,
'site_name': current_site.name, 'site_name': current_site.name,
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
@ -68,55 +64,54 @@ def redirect_to_login(next, login_url=None, redirect_field_name=REDIRECT_FIELD_N
def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html', def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',
email_template_name='registration/password_reset_email.html'): email_template_name='registration/password_reset_email.html'):
new_data, errors = {}, {} if request.method == "POST":
form = PasswordResetForm() form = PasswordResetForm(request.POST)
if request.POST: if form.is_valid():
new_data = request.POST.copy()
errors = form.get_validation_errors(new_data)
if not errors:
if is_admin_site: if is_admin_site:
form.save(domain_override=request.META['HTTP_HOST']) form.save(domain_override=request.META['HTTP_HOST'])
else: else:
form.save(email_template_name=email_template_name) form.save(email_template_name=email_template_name)
return HttpResponseRedirect('%sdone/' % request.path) return HttpResponseRedirect('%sdone/' % request.path)
return render_to_response(template_name, {'form': oldforms.FormWrapper(form, new_data, errors)}, else:
context_instance=RequestContext(request)) form = PasswordResetForm()
return render_to_response(template_name, {
'form': form,
}, context_instance=RequestContext(request))
def password_reset_done(request, template_name='registration/password_reset_done.html'): def password_reset_done(request, template_name='registration/password_reset_done.html'):
return render_to_response(template_name, context_instance=RequestContext(request)) return render_to_response(template_name, context_instance=RequestContext(request))
def password_change(request, template_name='registration/password_change_form.html'): def password_change(request, template_name='registration/password_change_form.html'):
new_data, errors = {}, {} if request.method == "POST":
form = PasswordChangeForm(request.user) form = PasswordChangeForm(request.user, request.POST)
if request.POST: if form.is_valid():
new_data = request.POST.copy() form.save()
errors = form.get_validation_errors(new_data)
if not errors:
form.save(new_data)
return HttpResponseRedirect('%sdone/' % request.path) return HttpResponseRedirect('%sdone/' % request.path)
return render_to_response(template_name, {'form': oldforms.FormWrapper(form, new_data, errors)}, else:
context_instance=RequestContext(request)) form = PasswordChangeForm(request.user)
return render_to_response(template_name, {
'form': form,
}, context_instance=RequestContext(request))
password_change = login_required(password_change) password_change = login_required(password_change)
def password_change_done(request, template_name='registration/password_change_done.html'): def password_change_done(request, template_name='registration/password_change_done.html'):
return render_to_response(template_name, context_instance=RequestContext(request)) return render_to_response(template_name, context_instance=RequestContext(request))
# TODO: move to admin.py in the ModelAdmin
def user_change_password(request, id): def user_change_password(request, id):
from django import oldforms
if not request.user.has_perm('auth.change_user'): if not request.user.has_perm('auth.change_user'):
raise PermissionDenied raise PermissionDenied
user = get_object_or_404(User, pk=id) user = get_object_or_404(User, pk=id)
manipulator = AdminPasswordChangeForm(user)
if request.method == 'POST': if request.method == 'POST':
new_data = request.POST.copy() form = AdminPasswordChangeForm(user, request.POST)
errors = manipulator.get_validation_errors(new_data) if form.is_valid():
if not errors: new_user = form.save()
new_user = manipulator.save(new_data)
msg = _('Password changed successfully.') msg = _('Password changed successfully.')
request.user.message_set.create(message=msg) request.user.message_set.create(message=msg)
return HttpResponseRedirect('..') return HttpResponseRedirect('..')
else: else:
errors = new_data = {} form = AdminPasswordChangeForm(user)
form = oldforms.FormWrapper(manipulator, new_data, errors)
return render_to_response('admin/auth/user/change_password.html', { return render_to_response('admin/auth/user/change_password.html', {
'title': _('Change password: %s') % escape(user.username), 'title': _('Change password: %s') % escape(user.username),
'form': form, 'form': form,

View File

@ -17,6 +17,47 @@ import base64, datetime
COMMENTS_PER_PAGE = 20 COMMENTS_PER_PAGE = 20
class AuthenticationForm(oldforms.Manipulator):
"""
Base class for authenticating users. Extend this to get a form that accepts
username/password logins.
"""
def __init__(self, request=None):
"""
If request is passed in, the manipulator will validate that cookies are
enabled. Note that the request (a HttpRequest object) must have set a
cookie with the key TEST_COOKIE_NAME and value TEST_COOKIE_VALUE before
running this validator.
"""
self.request = request
self.fields = [
oldforms.TextField(field_name="username", length=15, max_length=30, is_required=True,
validator_list=[self.isValidUser, self.hasCookiesEnabled]),
oldforms.PasswordField(field_name="password", length=15, max_length=30, is_required=True),
]
self.user_cache = None
def hasCookiesEnabled(self, field_data, all_data):
if self.request and not self.request.session.test_cookie_worked():
raise validators.ValidationError, _("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in.")
def isValidUser(self, field_data, all_data):
username = field_data
password = all_data.get('password', None)
self.user_cache = authenticate(username=username, password=password)
if self.user_cache is None:
raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.")
elif not self.user_cache.is_active:
raise validators.ValidationError, _("This account is inactive.")
def get_user_id(self):
if self.user_cache:
return self.user_cache.id
return None
def get_user(self):
return self.user_cache
class PublicCommentManipulator(AuthenticationForm): class PublicCommentManipulator(AuthenticationForm):
"Manipulator that handles public registered comments" "Manipulator that handles public registered comments"
def __init__(self, user, ratings_required, ratings_range, num_rating_choices): def __init__(self, user, ratings_required, ratings_range, num_rating_choices):

View File

@ -666,29 +666,29 @@ successful login.
* ``login_url``: The URL of the login page to redirect to. This * ``login_url``: The URL of the login page to redirect to. This
will default to ``settings.LOGIN_URL`` if not supplied. will default to ``settings.LOGIN_URL`` if not supplied.
Built-in manipulators Built-in forms
--------------------- --------------
**New in Django development version.**
If you don't want to use the built-in views, but want the convenience If you don't want to use the built-in views, but want the convenience
of not having to write manipulators for this functionality, the of not having to write forms for this functionality, the authentication
authentication system provides several built-in manipulators: system provides several built-in forms:
* ``django.contrib.auth.forms.AdminPasswordChangeForm``: A * ``django.contrib.auth.forms.AdminPasswordChangeForm``: A form used in
manipulator used in the admin interface to change a user's the admin interface to change a user's password.
password.
* ``django.contrib.auth.forms.AuthenticationForm``: A manipulator * ``django.contrib.auth.forms.AuthenticationForm``: A form for logging a
for logging a user in. user in.
* ``django.contrib.auth.forms.PasswordChangeForm``: A manipulator * ``django.contrib.auth.forms.PasswordChangeForm``: A form for allowing a
for allowing a user to change their password. user to change their password.
* ``django.contrib.auth.forms.PasswordResetForm``: A manipulator * ``django.contrib.auth.forms.PasswordResetForm``: A form for resetting a
for resetting a user's password and emailing the new password to user's password and emailing the new password to them.
them.
* ``django.contrib.auth.forms.UserCreationForm``: A manipulator * ``django.contrib.auth.forms.UserCreationForm``: A form for creating a
for creating a new user. new user.
Limiting access to logged-in users that pass a test Limiting access to logged-in users that pass a test
--------------------------------------------------- ---------------------------------------------------