Ticket #6083: 6083_newforms_auth2.diff

File 6083_newforms_auth2.diff, 33.5 KB (added by brosner, 7 years ago)

more complete with tests and docs. looking for feedback.

  • django/contrib/admin/templates/admin/auth/user/add_form.html

    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 d478ec7..65824a6 100644
    a b  
    88<fieldset class="module aligned">
    99
    1010<div class="form-row">
    11   {{ form.username.html_error_list }}
     11  {{ form.username.errors }}
     12  {# TODO: get required class on label_tag #}
    1213  <label for="id_username" class="required">{% trans 'Username' %}:</label> {{ form.username }}
    13   <p class="help">{{ username_help_text }}</p>
     14  <p class="help">{{ form.username.help_text }}</p>
    1415</div>
    1516
    1617<div class="form-row">
    17   {{ form.password1.html_error_list }}
     18  {{ form.password1.errors }}
     19  {# TODO: get required class on label_tag #}
    1820  <label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }}
    1921</div>
    2022
    2123<div class="form-row">
    22   {{ form.password2.html_error_list }}
     24  {{ form.password2.errors }}
     25  {# TODO: get required class on label_tag #}
    2326  <label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }}
    2427  <p class="help">{% trans 'Enter the same password as above, for verification.' %}</p>
    2528</div>
  • django/contrib/admin/templates/admin/auth/user/change_password.html

    diff --git a/django/contrib/admin/templates/admin/auth/user/change_password.html b/django/contrib/admin/templates/admin/auth/user/change_password.html
    index a75ad87..5740feb 100644
    a b  
    1818<form action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %}
    1919<div>
    2020{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
    21 {% if form.error_dict %}
     21{% if form.errors %}
    2222    <p class="errornote">
    23     {% blocktrans count form.error_dict.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
     23    {% blocktrans count form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
    2424    </p>
    2525{% endif %}
    2626
     
    2929<fieldset class="module aligned">
    3030
    3131<div class="form-row">
    32   {{ form.password1.html_error_list }}
     32  {{ form.password1.errors }}
     33  {# TODO: get required class on label_tag #}
    3334  <label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }}
    3435</div>
    3536
    3637<div class="form-row">
    37   {{ form.password2.html_error_list }}
     38  {{ form.password2.errors }}
     39  {# TODO: get required class on label_tag #}
    3840  <label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }}
    3941  <p class="help">{% trans 'Enter the same password as above, for verification.' %}</p>
    4042</div>
  • django/contrib/auth/admin.py

    diff --git a/django/contrib/auth/admin.py b/django/contrib/auth/admin.py
    index 97d284c..3900e05 100644
    a b class UserAdmin(admin.ModelAdmin): 
    2727    def add_view(self, request):
    2828        if not self.has_change_permission(request):
    2929            raise PermissionDenied
    30         manipulator = UserCreationForm()
    3130        if request.method == 'POST':
    32             new_data = request.POST.copy()
    33             errors = manipulator.get_validation_errors(new_data)
    34             if not errors:
    35                 new_user = manipulator.save(new_data)
     31            form = UserCreationForm(request.POST)
     32            if form.is_valid():
     33                new_user = form.save()
    3634                msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': 'user', 'obj': new_user}
    3735                if "_addanother" in request.POST:
    3836                    request.user.message_set.create(message=msg)
    class UserAdmin(admin.ModelAdmin): 
    4139                    request.user.message_set.create(message=msg + ' ' + ugettext("You may edit it again below."))
    4240                    return HttpResponseRedirect('../%s/' % new_user.id)
    4341        else:
    44             errors = new_data = {}
    45         form = oldforms.FormWrapper(manipulator, new_data, errors)
     42            form = UserCreationForm()
    4643        return render_to_response('admin/auth/user/add_form.html', {
    4744            'title': _('Add user'),
    4845            'form': form,
  • django/contrib/auth/forms.py

    diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py
    index 47a974c..a1066aa 100644
    a b from django.contrib.auth import authenticate 
    33from django.contrib.sites.models import Site
    44from django.template import Context, loader
    55from django.core import validators
    6 from django import oldforms
     6from django import newforms as forms
    77from django.utils.translation import ugettext as _
    88
    9 class UserCreationForm(oldforms.Manipulator):
    10     "A form that creates a user, with no privileges, from the given username and password."
    11     def __init__(self):
    12         self.fields = (
    13             oldforms.TextField(field_name='username', length=30, max_length=30, is_required=True,
    14                 validator_list=[validators.isAlphaNumeric, self.isValidUsername]),
    15             oldforms.PasswordField(field_name='password1', length=30, max_length=60, is_required=True),
    16             oldforms.PasswordField(field_name='password2', length=30, max_length=60, is_required=True,
    17                 validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
    18         )
    19 
    20     def isValidUsername(self, field_data, all_data):
     9class UserCreationForm(forms.ModelForm):
     10    """
     11    A form that creates a user, with no privileges, from the given username and password.
     12    """
     13    username = forms.RegexField(label=_("Username"), max_length=30, regex=r'^\w+$',
     14        help_text = _("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."),
     15        error_message = _("This value must contain only letters, numbers and underscores."))
     16    password1 = forms.CharField(label=_("Password"), max_length=60, widget=forms.PasswordInput)
     17    password2 = forms.CharField(label=_("Password confirmation"), max_length=60, widget=forms.PasswordInput)
     18   
     19    class Meta:
     20        model = User
     21        fields = ("username",)
     22   
     23    def clean_username(self):
     24        username = self.cleaned_data["username"]
    2125        try:
    22             User.objects.get(username=field_data)
     26            User.objects.get(username=username)
    2327        except User.DoesNotExist:
    24             return
    25         raise validators.ValidationError, _('A user with that username already exists.')
    26 
    27     def save(self, new_data):
    28         "Creates the user."
    29         return User.objects.create_user(new_data['username'], '', new_data['password1'])
     28            return username
     29        raise forms.ValidationError(_("A user with that username already exists."))
     30   
     31    def clean_password2(self):
     32        password1 = self.cleaned_data["password1"]
     33        password2 = self.cleaned_data["password2"]
     34        if password1 != password2:
     35            raise forms.ValidationError(_("The two password fields didn't match."))
     36        return password2
     37   
     38    def save(self, commit=True):
     39        user = super(UserCreationForm, self).save(commit=False)
     40        user.set_password(self.cleaned_data["password1"])
     41        if commit:
     42            user.save()
     43        return user
    3044
    31 class AuthenticationForm(oldforms.Manipulator):
     45class AuthenticationForm(forms.Form):
    3246    """
    3347    Base class for authenticating users. Extend this to get a form that accepts
    3448    username/password logins.
    3549    """
    36     def __init__(self, request=None):
     50    username = forms.CharField(max_length=30)
     51    password = forms.CharField(max_length=30, widget=forms.PasswordInput)
     52   
     53    def __init__(self, request=None, *args, **kwargs):
    3754        """
    38         If request is passed in, the manipulator will validate that cookies are
     55        If request is passed in, the form will validate that cookies are
    3956        enabled. Note that the request (a HttpRequest object) must have set a
    4057        cookie with the key TEST_COOKIE_NAME and value TEST_COOKIE_VALUE before
    41         running this validator.
     58        running this validation.
    4259        """
    4360        self.request = request
    44         self.fields = [
    45             oldforms.TextField(field_name="username", length=15, max_length=30, is_required=True,
    46                 validator_list=[self.isValidUser, self.hasCookiesEnabled]),
    47             oldforms.PasswordField(field_name="password", length=15, max_length=30, is_required=True),
    48         ]
    4961        self.user_cache = None
    50 
    51     def hasCookiesEnabled(self, field_data, all_data):
    52         if self.request and not self.request.session.test_cookie_worked():
    53             raise validators.ValidationError, _("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in.")
    54 
    55     def isValidUser(self, field_data, all_data):
    56         username = field_data
    57         password = all_data.get('password', None)
    58         self.user_cache = authenticate(username=username, password=password)
    59         if self.user_cache is None:
    60             raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.")
    61         elif not self.user_cache.is_active:
    62             raise validators.ValidationError, _("This account is inactive.")
    63 
     62        super(AuthenticationForm, self).__init__(*args, **kwargs)
     63   
     64    def clean(self):
     65        username = self.cleaned_data.get('username')
     66        password = self.cleaned_data.get('password')
     67       
     68        if username and password:
     69            self.user_cache = authenticate(username=username, password=password)
     70            if self.user_cache is None:
     71                raise forms.ValidationError(_("Please enter a correct username and password. Note that both fields are case-sensitive."))
     72            elif not self.user_cache.is_active:
     73                raise forms.ValidationError(_("This account is inactive."))
     74       
     75        # TODO: determine whether this should move to its own method.
     76        if self.request:
     77            if not self.request.session.test_cookie_worked():
     78                raise forms.ValidationError(_("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."))
     79       
     80        return self.cleaned_data
     81   
    6482    def get_user_id(self):
    6583        if self.user_cache:
    6684            return self.user_cache.id
    6785        return None
    68 
     86   
    6987    def get_user(self):
    7088        return self.user_cache
    7189
    72 class PasswordResetForm(oldforms.Manipulator):
    73     "A form that lets a user request a password reset"
    74     def __init__(self):
    75         self.fields = (
    76             oldforms.EmailField(field_name="email", length=40, is_required=True,
    77                 validator_list=[self.isValidUserEmail]),
    78         )
    79 
    80     def isValidUserEmail(self, new_data, all_data):
    81         "Validates that a user exists with the given e-mail address"
    82         self.users_cache = list(User.objects.filter(email__iexact=new_data))
     90class PasswordResetForm(forms.Form):
     91    # used to be length of 40
     92    email = forms.EmailField()
     93   
     94    def clean_email(self):
     95        """
     96        Validates that a user exists with the given e-mail address.
     97        """
     98        email = self.cleaned_data["email"]
     99        self.users_cache = User.objects.filter(email__iexact=email)
    83100        if len(self.users_cache) == 0:
    84             raise validators.ValidationError, _("That e-mail address doesn't have an associated user account. Are you sure you've registered?")
    85 
     101            raise forms.ValidationError(_("That e-mail address doesn't have an associated user account. Are you sure you've registered?"))
     102   
    86103    def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'):
    87         "Calculates a new password randomly and sends it to the user"
     104        """
     105        Calculates a new password randomly and sends it to the user.
     106        """
    88107        from django.core.mail import send_mail
    89108        for user in self.users_cache:
    90109            new_pass = User.objects.make_random_password()
    class PasswordResetForm(oldforms.Manipulator): 
    103122                'domain': domain,
    104123                'site_name': site_name,
    105124                'user': user,
    106                 }
    107             send_mail(_('Password reset on %s') % site_name, t.render(Context(c)), None, [user.email])
     125            }
     126            send_mail(_("Password reset on %s") % site_name,
     127                t.render(Context(c)), None, [user.email])
    108128
    109 class PasswordChangeForm(oldforms.Manipulator):
    110     "A form that lets a user change his password."
    111     def __init__(self, user):
     129class PasswordChangeForm(forms.Form):
     130    """
     131    A form that lets a user change his/her password.
     132    """
     133    old_password = forms.CharField(max_length=30, widget=forms.PasswordInput)
     134    new_password1 = forms.CharField(max_length=30, widget=forms.PasswordInput)
     135    new_password2 = forms.CharField(max_length=30, widget=forms.PasswordInput)
     136   
     137    def __init__(self, user, *args, **kwargs):
    112138        self.user = user
    113         self.fields = (
    114             oldforms.PasswordField(field_name="old_password", length=30, max_length=30, is_required=True,
    115                 validator_list=[self.isValidOldPassword]),
    116             oldforms.PasswordField(field_name="new_password1", length=30, max_length=30, is_required=True,
    117                 validator_list=[validators.AlwaysMatchesOtherField('new_password2', _("The two 'new password' fields didn't match."))]),
    118             oldforms.PasswordField(field_name="new_password2", length=30, max_length=30, is_required=True),
    119         )
    120 
    121     def isValidOldPassword(self, new_data, all_data):
    122         "Validates that the old_password field is correct."
    123         if not self.user.check_password(new_data):
    124             raise validators.ValidationError, _("Your old password was entered incorrectly. Please enter it again.")
    125 
    126     def save(self, new_data):
    127         "Saves the new password."
    128         self.user.set_password(new_data['new_password1'])
    129         self.user.save()
    130 
    131 class AdminPasswordChangeForm(oldforms.Manipulator):
    132     "A form used to change the password of a user in the admin interface."
    133     def __init__(self, user):
     139        super(PasswordChangeForm, self).__init__(*args, **kwargs)
     140   
     141    def clean_old_password(self):
     142        """
     143        Validates that the old_password field is correct.
     144        """
     145        old_password = self.cleaned_data["old_password"]
     146        if not self.user.check_password(old_password):
     147            raise forms.ValidationError(_("Your old password was entered incorrectly. Please enter it again."))
     148        return old_password
     149   
     150    def clean_new_password2(self):
     151        password1 = self.cleaned_data.get('new_password1')
     152        password2 = self.cleaned_data.get('new_password2')
     153        if password1 and password2:
     154            if password1 != password2:
     155                raise forms.ValidationError(_("The two password fields didn't match."))
     156        return password2
     157   
     158    def save(self, commit=True):
     159        self.user.set_password(self.cleaned_data['new_password1'])
     160        if commit:
     161            self.user.save()
     162        return self.user
     163
     164class AdminPasswordChangeForm(forms.Form):
     165    """
     166    A form used to change the password of a user in the admin interface.
     167    """
     168    password1 = forms.CharField(max_length=60, widget=forms.PasswordInput)
     169    password2 = forms.CharField(max_length=60, widget=forms.PasswordInput)
     170   
     171    def __init__(self, user, *args, **kwargs):
    134172        self.user = user
    135         self.fields = (
    136             oldforms.PasswordField(field_name='password1', length=30, max_length=60, is_required=True),
    137             oldforms.PasswordField(field_name='password2', length=30, max_length=60, is_required=True,
    138                 validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
    139         )
    140 
    141     def save(self, new_data):
    142         "Saves the new password."
    143         self.user.set_password(new_data['password1'])
    144         self.user.save()
     173        super(AdminPasswordChangeForm, self).__init__(*args, **kwargs)
     174   
     175    def clean_password2(self):
     176        password1 = self.cleaned_data.get('password1')
     177        password2 = self.cleaned_data.get('password2')
     178        if password1 and password2:
     179            if password1 != password2:
     180                raise forms.ValidationError(_("The two password fields didn't match."))
     181        return password2
     182   
     183    def save(self, commit=True):
     184        """
     185        Saves the new password.
     186        """
     187        self.user.set_password(self.cleaned_data["password1"])
     188        if commit:
     189            self.user.save()
     190        return self.user
  • deleted file django/contrib/auth/tests.py

    diff --git a/django/contrib/auth/tests.py b/django/contrib/auth/tests.py
    deleted file mode 100644
    index d369ac5..0000000
    + -  
    1 """
    2 >>> from models import User, AnonymousUser
    3 >>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
    4 >>> u.has_usable_password()
    5 True
    6 >>> u.check_password('bad')
    7 False
    8 >>> u.check_password('testpw')
    9 True
    10 >>> u.set_unusable_password()
    11 >>> u.save()
    12 >>> u.check_password('testpw')
    13 False
    14 >>> u.has_usable_password()
    15 False
    16 >>> u2 = User.objects.create_user('testuser2', 'test2@example.com')
    17 >>> u2.has_usable_password()
    18 False
    19 
    20 >>> u.is_authenticated()
    21 True
    22 >>> u.is_staff
    23 False
    24 >>> u.is_active
    25 True
    26 
    27 >>> a = AnonymousUser()
    28 >>> a.is_authenticated()
    29 False
    30 >>> a.is_staff
    31 False
    32 >>> a.is_active
    33 False
    34 >>> a.groups.all()
    35 []
    36 >>> a.user_permissions.all()
    37 []
    38 """
    39  No newline at end of file
  • new file django/contrib/auth/tests/__init__.py

    diff --git a/django/contrib/auth/tests/__init__.py b/django/contrib/auth/tests/__init__.py
    new file mode 100644
    index 0000000..092fdd5
    - +  
     1from django.contrib.auth.tests.basic import BASIC_TESTS
     2from django.contrib.auth.tests.forms import FORM_TESTS, PasswordResetFormTestCase
     3
     4__test__ = {
     5    'BASIC_TESTS': BASIC_TESTS,
     6    'PASSWORDRESET_TESTS': PasswordResetFormTestCase,
     7    'FORM_TESTS': FORM_TESTS,
     8}
  • new file django/contrib/auth/tests/basic.py

    diff --git a/django/contrib/auth/tests/basic.py b/django/contrib/auth/tests/basic.py
    new file mode 100644
    index 0000000..950815e
    - +  
     1
     2BASIC_TESTS = """
     3>>> from django.contrib.auth.models import User, AnonymousUser
     4>>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
     5>>> u.has_usable_password()
     6True
     7>>> u.check_password('bad')
     8False
     9>>> u.check_password('testpw')
     10True
     11>>> u.set_unusable_password()
     12>>> u.save()
     13>>> u.check_password('testpw')
     14False
     15>>> u.has_usable_password()
     16False
     17>>> u2 = User.objects.create_user('testuser2', 'test2@example.com')
     18>>> u2.has_usable_password()
     19False
     20
     21>>> u.is_authenticated()
     22True
     23>>> u.is_staff
     24False
     25>>> u.is_active
     26True
     27
     28>>> a = AnonymousUser()
     29>>> a.is_authenticated()
     30False
     31>>> a.is_staff
     32False
     33>>> a.is_active
     34False
     35>>> a.groups.all()
     36[]
     37>>> a.user_permissions.all()
     38[]
     39"""
     40 No newline at end of file
  • new file django/contrib/auth/tests/forms.py

    diff --git a/django/contrib/auth/tests/forms.py b/django/contrib/auth/tests/forms.py
    new file mode 100644
    index 0000000..001323b
    - +  
     1
     2from django.core import mail
     3from django.test import TestCase
     4from django.contrib.auth.models import User
     5from django.contrib.auth.forms import PasswordResetForm
     6
     7class PasswordResetFormTestCase(TestCase):
     8    def testValidUser(self):
     9        data = {
     10            'email': 'nonexistent@example.com',
     11        }
     12        form = PasswordResetForm(data)
     13        self.assertEqual(form.is_valid(), False)
     14        self.assertEqual(form["email"].errors, [u"That e-mail address doesn't have an associated user account. Are you sure you've registered?"])
     15   
     16    def testEmail(self):
     17        # TODO: remove my email address from the test ;)
     18        User.objects.create_user('atestuser', 'atestuser@example.com', 'test789')
     19        data = {
     20            'email': 'atestuser@example.com',
     21        }
     22        form = PasswordResetForm(data)
     23        self.assertEqual(form.is_valid(), True)
     24        # TODO: look at why using contrib.sites breaks other tests
     25        form.save(domain_override="example.com")
     26        self.assertEqual(len(mail.outbox), 1)
     27        self.assertEqual(mail.outbox[0].subject, u'Password reset on example.com')
     28        # TODO: test mail body. need to figure out a way to get the password in plain text
     29        # self.assertEqual(mail.outbox[0].body, '')
     30
     31FORM_TESTS = """
     32>>> from django.contrib.auth.models import User
     33>>> from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
     34>>> from django.contrib.auth.forms import PasswordChangeForm
     35
     36The user already exists.
     37
     38>>> user = User.objects.create_user("jsmith", "jsmith@example.com", "test123")
     39>>> data = {
     40...     'username': 'jsmith',
     41...     'password1': 'test123',
     42...     'password2': 'test123',
     43... }
     44>>> form = UserCreationForm(data)
     45>>> form.is_valid()
     46False
     47>>> form["username"].errors
     48[u'A user with that username already exists.']
     49
     50The username contains invalid data.
     51
     52>>> data = {
     53...     'username': 'jsmith@example.com',
     54...     'password1': 'test123',
     55...     'password2': 'test123',
     56... }
     57>>> form = UserCreationForm(data)
     58>>> form.is_valid()
     59False
     60>>> form["username"].errors
     61[u'This value must contain only letters, numbers and underscores.']
     62
     63The verification password is incorrect.
     64
     65>>> data = {
     66...     'username': 'jsmith2',
     67...     'password1': 'test123',
     68...     'password2': 'test',
     69... }
     70>>> form = UserCreationForm(data)
     71>>> form.is_valid()
     72False
     73>>> form["password2"].errors
     74[u"The two password fields didn't match."]
     75
     76The success case.
     77
     78>>> data = {
     79...     'username': 'jsmith2',
     80...     'password1': 'test123',
     81...     'password2': 'test123',
     82... }
     83>>> form = UserCreationForm(data)
     84>>> form.is_valid()
     85True
     86>>> form.save()
     87<User: jsmith2>
     88
     89The user submits an invalid username.
     90
     91>>> data = {
     92...     'username': 'jsmith_does_not_exist',
     93...     'password': 'test123',
     94... }
     95
     96>>> form = AuthenticationForm(None, data)
     97>>> form.is_valid()
     98False
     99>>> form.non_field_errors()
     100[u'Please enter a correct username and password. Note that both fields are case-sensitive.']
     101
     102The user is inactive.
     103
     104>>> data = {
     105...     'username': 'jsmith',
     106...     'password': 'test123',
     107... }
     108>>> user.is_active = False
     109>>> user.save()
     110>>> form = AuthenticationForm(None, data)
     111>>> form.is_valid()
     112False
     113>>> form.non_field_errors()
     114[u'This account is inactive.']
     115
     116>>> user.is_active = True
     117>>> user.save()
     118
     119The success case
     120
     121>>> form = AuthenticationForm(None, data)
     122>>> form.is_valid()
     123True
     124>>> form.non_field_errors()
     125[]
     126
     127The old password is incorrect.
     128
     129>>> data = {
     130...     'old_password': 'test',
     131...     'new_password1': 'abc123',
     132...     'new_password2': 'abc123',
     133... }
     134>>> form = PasswordChangeForm(user, data)
     135>>> form.is_valid()
     136False
     137>>> form["old_password"].errors
     138[u'Your old password was entered incorrectly. Please enter it again.']
     139
     140The two new passwords do not match.
     141
     142>>> data = {
     143...     'old_password': 'test123',
     144...     'new_password1': 'abc123',
     145...     'new_password2': 'abc',
     146... }
     147>>> form = PasswordChangeForm(user, data)
     148>>> form.is_valid()
     149False
     150>>> form["new_password2"].errors
     151[u"The two password fields didn't match."]
     152
     153The success case.
     154
     155>>> data = {
     156...     'old_password': 'test123',
     157...     'new_password1': 'abc123',
     158...     'new_password2': 'abc123',
     159... }
     160>>> form = PasswordChangeForm(user, data)
     161>>> form.is_valid()
     162True
     163
     164"""
  • django/contrib/auth/views.py

    diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py
    index 509b96e..65d6b29 100644
    a b  
    11from django.contrib.auth.forms import AuthenticationForm
    22from django.contrib.auth.forms import PasswordResetForm, PasswordChangeForm, AdminPasswordChangeForm
    33from django.core.exceptions import PermissionDenied
    4 from django import oldforms
    54from django.shortcuts import render_to_response, get_object_or_404
    65from django.template import RequestContext
    76from django.contrib.sites.models import Site, RequestSite
    from django.contrib.auth.models import User 
    1413
    1514def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME):
    1615    "Displays the login form and handles the login action."
    17     manipulator = AuthenticationForm(request)
    1816    redirect_to = request.REQUEST.get(redirect_field_name, '')
    19     if request.POST:
    20         errors = manipulator.get_validation_errors(request.POST)
    21         if not errors:
     17    if request.method == "POST":
     18        form = AuthenticationForm(request, request.POST)
     19        if form.is_valid():
    2220            # Light security check -- make sure redirect_to isn't garbage.
    2321            if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
    2422                from django.conf import settings
    2523                redirect_to = settings.LOGIN_REDIRECT_URL
    2624            from django.contrib.auth import login
    27             login(request, manipulator.get_user())
     25            login(request, form.get_user())
    2826            request.session.delete_test_cookie()
    2927            return HttpResponseRedirect(redirect_to)
    3028    else:
    31         errors = {}
     29        form = AuthenticationForm(request)
    3230    request.session.set_test_cookie()
    33 
    3431    if Site._meta.installed:
    3532        current_site = Site.objects.get_current()
    3633    else:
    3734        current_site = RequestSite(request)
    38 
    3935    return render_to_response(template_name, {
    40         'form': oldforms.FormWrapper(manipulator, request.POST, errors),
     36        'form': form,
    4137        redirect_field_name: redirect_to,
    4238        'site_name': current_site.name,
    4339    }, context_instance=RequestContext(request))
    def redirect_to_login(next, login_url=None, redirect_field_name=REDIRECT_FIELD_N 
    6864
    6965def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',
    7066        email_template_name='registration/password_reset_email.html'):
    71     new_data, errors = {}, {}
    72     form = PasswordResetForm()
    73     if request.POST:
    74         new_data = request.POST.copy()
    75         errors = form.get_validation_errors(new_data)
    76         if not errors:
     67    if request.method == "POST":
     68        form = PasswordResetForm(request.POST)
     69        if form.is_valid():
    7770            if is_admin_site:
    7871                form.save(domain_override=request.META['HTTP_HOST'])
    7972            else:
    8073                form.save(email_template_name=email_template_name)
    8174            return HttpResponseRedirect('%sdone/' % request.path)
    82     return render_to_response(template_name, {'form': oldforms.FormWrapper(form, new_data, errors)},
    83         context_instance=RequestContext(request))
     75    else:
     76        form = PasswordResetForm()
     77    return render_to_response(template_name, {
     78        'form': form,
     79    }, context_instance=RequestContext(request))
    8480
    8581def password_reset_done(request, template_name='registration/password_reset_done.html'):
    8682    return render_to_response(template_name, context_instance=RequestContext(request))
    8783
    8884def password_change(request, template_name='registration/password_change_form.html'):
    89     new_data, errors = {}, {}
    90     form = PasswordChangeForm(request.user)
    91     if request.POST:
    92         new_data = request.POST.copy()
    93         errors = form.get_validation_errors(new_data)
    94         if not errors:
    95             form.save(new_data)
     85    if request.method == "POST":
     86        form = PasswordChangeForm(request.user, request.POST)
     87        if form.is_valid():
     88            form.save()
    9689            return HttpResponseRedirect('%sdone/' % request.path)
    97     return render_to_response(template_name, {'form': oldforms.FormWrapper(form, new_data, errors)},
    98         context_instance=RequestContext(request))
     90    else:
     91        form = PasswordChangeForm(request.user)
     92    return render_to_response(template_name, {
     93        'form': form,
     94    }, context_instance=RequestContext(request))
    9995password_change = login_required(password_change)
    10096
    10197def password_change_done(request, template_name='registration/password_change_done.html'):
    10298    return render_to_response(template_name, context_instance=RequestContext(request))
    10399
     100# TODO: move to admin.py in the ModelAdmin
    104101def user_change_password(request, id):
     102    from django import oldforms
    105103    if not request.user.has_perm('auth.change_user'):
    106104        raise PermissionDenied
    107105    user = get_object_or_404(User, pk=id)
    108     manipulator = AdminPasswordChangeForm(user)
    109106    if request.method == 'POST':
    110         new_data = request.POST.copy()
    111         errors = manipulator.get_validation_errors(new_data)
    112         if not errors:
    113             new_user = manipulator.save(new_data)
     107        form = AdminPasswordChangeForm(user, request.POST)
     108        if form.is_valid():
     109            new_user = form.save()
    114110            msg = _('Password changed successfully.')
    115111            request.user.message_set.create(message=msg)
    116112            return HttpResponseRedirect('..')
    117113    else:
    118         errors = new_data = {}
    119     form = oldforms.FormWrapper(manipulator, new_data, errors)
     114        form = AdminPasswordChangeForm(user)
    120115    return render_to_response('admin/auth/user/change_password.html', {
    121116        'title': _('Change password: %s') % escape(user.username),
    122117        'form': form,
  • django/contrib/comments/views/comments.py

    diff --git a/django/contrib/comments/views/comments.py b/django/contrib/comments/views/comments.py
    index 67da575..aac489f 100644
    a b import base64, datetime 
    1717
    1818COMMENTS_PER_PAGE = 20
    1919
     20class AuthenticationForm(oldforms.Manipulator):
     21    """
     22    Base class for authenticating users. Extend this to get a form that accepts
     23    username/password logins.
     24    """
     25    def __init__(self, request=None):
     26        """
     27        If request is passed in, the manipulator will validate that cookies are
     28        enabled. Note that the request (a HttpRequest object) must have set a
     29        cookie with the key TEST_COOKIE_NAME and value TEST_COOKIE_VALUE before
     30        running this validator.
     31        """
     32        self.request = request
     33        self.fields = [
     34            oldforms.TextField(field_name="username", length=15, max_length=30, is_required=True,
     35                validator_list=[self.isValidUser, self.hasCookiesEnabled]),
     36            oldforms.PasswordField(field_name="password", length=15, max_length=30, is_required=True),
     37        ]
     38        self.user_cache = None
     39
     40    def hasCookiesEnabled(self, field_data, all_data):
     41        if self.request and not self.request.session.test_cookie_worked():
     42            raise validators.ValidationError, _("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in.")
     43
     44    def isValidUser(self, field_data, all_data):
     45        username = field_data
     46        password = all_data.get('password', None)
     47        self.user_cache = authenticate(username=username, password=password)
     48        if self.user_cache is None:
     49            raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.")
     50        elif not self.user_cache.is_active:
     51            raise validators.ValidationError, _("This account is inactive.")
     52
     53    def get_user_id(self):
     54        if self.user_cache:
     55            return self.user_cache.id
     56        return None
     57
     58    def get_user(self):
     59        return self.user_cache
     60
    2061class PublicCommentManipulator(AuthenticationForm):
    2162    "Manipulator that handles public registered comments"
    2263    def __init__(self, user, ratings_required, ratings_range, num_rating_choices):
  • docs/authentication.txt

    diff --git a/docs/authentication.txt b/docs/authentication.txt
    index 5134e90..4d45fd9 100644
    a b successful login. 
    666666    * ``login_url``: The URL of the login page to redirect to. This
    667667      will default to ``settings.LOGIN_URL`` if not supplied.
    668668
    669 Built-in manipulators
    670 ---------------------
     669Built-in forms
     670--------------
     671
     672**New in Django development version.**
    671673
    672674If you don't want to use the built-in views, but want the convenience
    673 of not having to write manipulators for this functionality, the
    674 authentication system provides several built-in manipulators:
     675of not having to write forms for this functionality, the authentication
     676system provides several built-in forms:
    675677
    676     * ``django.contrib.auth.forms.AdminPasswordChangeForm``: A
    677       manipulator used in the admin interface to change a user's
    678       password.
     678    * ``django.contrib.auth.forms.AdminPasswordChangeForm``: A form used in
     679      the admin interface to change a user's password.
    679680
    680     * ``django.contrib.auth.forms.AuthenticationForm``: A manipulator
    681       for logging a user in.
     681    * ``django.contrib.auth.forms.AuthenticationForm``: A form for logging a
     682      user in.
    682683
    683     * ``django.contrib.auth.forms.PasswordChangeForm``: A manipulator
    684       for allowing a user to change their password.
     684    * ``django.contrib.auth.forms.PasswordChangeForm``: A form for allowing a
     685      user to change their password.
    685686
    686     * ``django.contrib.auth.forms.PasswordResetForm``: A manipulator
    687       for resetting a user's password and emailing the new password to
    688       them.
     687    * ``django.contrib.auth.forms.PasswordResetForm``: A form for resetting a
     688      user's password and emailing the new password to them.
    689689
    690     * ``django.contrib.auth.forms.UserCreationForm``: A manipulator
    691       for creating a new user.
     690    * ``django.contrib.auth.forms.UserCreationForm``: A form for creating a
     691      new user.
    692692
    693693Limiting access to logged-in users that pass a test
    694694---------------------------------------------------
Back to Top