Commit 22b917518e2e1105fb74278490055ecc978528a4
1 parent
fbf424a9
Exists in
master
and in
39 other branches
Fixed admin for User model
(flake8 checks as well)
Showing
2 changed files
with
97 additions
and
103 deletions
Show diff stats
colab/accounts/admin.py
1 | 1 | ||
2 | -from django import forms | ||
3 | from django.contrib import admin | 2 | from django.contrib import admin |
4 | from django.contrib.auth import get_user_model | 3 | from django.contrib.auth import get_user_model |
5 | from django.contrib.auth.admin import UserAdmin | 4 | from django.contrib.auth.admin import UserAdmin |
6 | from django.utils.translation import ugettext_lazy as _ | 5 | from django.utils.translation import ugettext_lazy as _ |
7 | 6 | ||
8 | -from .forms import UserCreationForm | 7 | +from .forms import UserCreationForm, UserChangeForm |
9 | 8 | ||
10 | User = get_user_model() | 9 | User = get_user_model() |
11 | 10 | ||
12 | 11 | ||
13 | -class CustomUserCreationForm(UserCreationForm): | ||
14 | - class Meta: | ||
15 | - model = User | ||
16 | - fields = ("username", "email") | ||
17 | - | ||
18 | - #def __init__(self, *args, **kwargs): | ||
19 | - # super(CustomUserCreationForm, self).__init__(*args, **kwargs) | ||
20 | - # self.fields['email'].required = True | ||
21 | - | ||
22 | - | ||
23 | -class UserChangeForm(forms.ModelForm): | ||
24 | - class Meta: | ||
25 | - model = User | ||
26 | - fields = ('username', 'first_name', 'last_name', 'email', 'is_active', | ||
27 | - 'is_staff', 'is_superuser', 'groups', 'last_login', | ||
28 | - 'date_joined', 'twitter', 'facebook', 'google_talk', | ||
29 | - 'webpage') | ||
30 | - | ||
31 | - def __init__(self, *args, **kwargs): | ||
32 | - super(UserChangeForm, self).__init__(*args, **kwargs) | ||
33 | - self.fields['email'].required = True | ||
34 | - | ||
35 | - | ||
36 | - | ||
37 | -class MyUserAdmin(UserAdmin): | 12 | +class CustomUserAdmin(UserAdmin): |
38 | form = UserChangeForm | 13 | form = UserChangeForm |
39 | - add_form = CustomUserCreationForm | 14 | + add_form = UserCreationForm |
40 | 15 | ||
41 | fieldsets = ( | 16 | fieldsets = ( |
42 | (None, {'fields': ('username', 'email', 'password')}), | 17 | (None, {'fields': ('username', 'email', 'password')}), |
43 | - (_('Personal info'), {'fields': ('first_name', 'last_name', 'twitter', | ||
44 | - 'facebook', 'google_talk', 'webpage', | ||
45 | - )}), | ||
46 | - (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser', | 18 | + (_('Personal info'), {'fields': ('first_name', |
19 | + 'last_name', | ||
20 | + 'twitter', | ||
21 | + 'facebook', | ||
22 | + 'google_talk', | ||
23 | + 'webpage')}), | ||
24 | + (_('Permissions'), {'fields': ('is_active', | ||
25 | + 'is_staff', | ||
26 | + 'is_superuser', | ||
47 | 'groups')}), | 27 | 'groups')}), |
48 | (_('Important dates'), {'fields': ('last_login', 'date_joined')}) | 28 | (_('Important dates'), {'fields': ('last_login', 'date_joined')}) |
49 | ) | 29 | ) |
@@ -56,4 +36,4 @@ class MyUserAdmin(UserAdmin): | @@ -56,4 +36,4 @@ class MyUserAdmin(UserAdmin): | ||
56 | ) | 36 | ) |
57 | 37 | ||
58 | 38 | ||
59 | -admin.site.register(User, MyUserAdmin) | 39 | +admin.site.register(User, CustomUserAdmin) |
colab/accounts/forms.py
1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
2 | 2 | ||
3 | +from collections import OrderedDict | ||
4 | + | ||
3 | from django import forms | 5 | from django import forms |
4 | -from django.contrib.auth import get_user_model | ||
5 | -from django.contrib.auth.forms import OrderedDict, ReadOnlyPasswordHashField, \ | ||
6 | - default_token_generator | 6 | +from django.contrib.auth import authenticate, get_user_model |
7 | +from django.contrib.auth.forms import ReadOnlyPasswordHashField | ||
8 | +from django.contrib.auth.tokens import default_token_generator | ||
9 | +from django.contrib.sites.shortcuts import get_current_site | ||
10 | +from django.template import loader | ||
11 | +from django.utils.encoding import force_bytes | ||
12 | +from django.utils.http import urlsafe_base64_encode | ||
13 | +from django.utils.text import capfirst | ||
7 | from django.utils.translation import ugettext_lazy as _ | 14 | from django.utils.translation import ugettext_lazy as _ |
8 | 15 | ||
9 | from conversejs.models import XMPPAccount | 16 | from conversejs.models import XMPPAccount |
10 | 17 | ||
11 | -from ..super_archives.models import MailingList | ||
12 | from .utils.validators import validate_social_account | 18 | from .utils.validators import validate_social_account |
13 | from .utils import mailman | 19 | from .utils import mailman |
14 | 20 | ||
@@ -32,7 +38,7 @@ class UserForm(forms.ModelForm): | @@ -32,7 +38,7 @@ class UserForm(forms.ModelForm): | ||
32 | username = forms.CharField( | 38 | username = forms.CharField( |
33 | 39 | ||
34 | # Forces username to be lowercase always | 40 | # Forces username to be lowercase always |
35 | - widget=forms.TextInput(attrs={'style' : 'text-transform: lowercase;'}), | 41 | + widget=forms.TextInput(attrs={'style': 'text-transform: lowercase;'}), |
36 | ) | 42 | ) |
37 | required = ('first_name', 'last_name', 'username') | 43 | required = ('first_name', 'last_name', 'username') |
38 | 44 | ||
@@ -50,48 +56,6 @@ class UserForm(forms.ModelForm): | @@ -50,48 +56,6 @@ class UserForm(forms.ModelForm): | ||
50 | field.required = True | 56 | field.required = True |
51 | 57 | ||
52 | 58 | ||
53 | -class UserCreationForm(UserForm): | ||
54 | - | ||
55 | - class Meta: | ||
56 | - model = User | ||
57 | - fields = ('first_name', 'last_name', 'username') | ||
58 | - | ||
59 | - def clean_username(self): | ||
60 | - username = self.cleaned_data['username'] | ||
61 | - username = username.strip() | ||
62 | - if not username: | ||
63 | - raise forms.ValidationError(_('This field cannot be blank.')) | ||
64 | - return username | ||
65 | - | ||
66 | - | ||
67 | -class UserCreationFormNoBrowserId(UserCreationForm): | ||
68 | - | ||
69 | - password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput) | ||
70 | - password2 = forms.CharField(label=_("Confirm Password "), widget=forms.PasswordInput) | ||
71 | - email = forms.EmailField(label=_("Email address"), required=True) | ||
72 | - | ||
73 | - class Meta: | ||
74 | - model = User | ||
75 | - fields = ('first_name', 'last_name','email', 'username') | ||
76 | - | ||
77 | - def clean_password2(self): | ||
78 | - password1 = self.cleaned_data.get('password1') | ||
79 | - password2 = self.cleaned_data.get('password2') | ||
80 | - | ||
81 | - if password1 and password2 and password1 != password2: | ||
82 | - raise forms.ValidationError(_("The two password fields didn't match.")) | ||
83 | - return password2 | ||
84 | - | ||
85 | - def save(self, commit=True): | ||
86 | - """ | ||
87 | - Saves the new password. | ||
88 | - """ | ||
89 | - self.instance.set_password(self.cleaned_data["password1"]) | ||
90 | - if commit: | ||
91 | - self.instance.save() | ||
92 | - return self.instance | ||
93 | - | ||
94 | - | ||
95 | class UserUpdateForm(UserForm): | 59 | class UserUpdateForm(UserForm): |
96 | bio = forms.CharField( | 60 | bio = forms.CharField( |
97 | widget=forms.Textarea(attrs={'rows': '6', 'maxlength': '200'}), | 61 | widget=forms.Textarea(attrs={'rows': '6', 'maxlength': '200'}), |
@@ -102,10 +66,9 @@ class UserUpdateForm(UserForm): | @@ -102,10 +66,9 @@ class UserUpdateForm(UserForm): | ||
102 | ) | 66 | ) |
103 | 67 | ||
104 | def __init__(self, *args, **kwargs): | 68 | def __init__(self, *args, **kwargs): |
105 | - super (UserUpdateForm, self).__init__(*args, **kwargs) | 69 | + super(UserUpdateForm, self).__init__(*args, **kwargs) |
106 | self.fields.pop('username') | 70 | self.fields.pop('username') |
107 | 71 | ||
108 | - | ||
109 | class Meta: | 72 | class Meta: |
110 | model = User | 73 | model = User |
111 | fields = ('first_name', 'last_name', | 74 | fields = ('first_name', 'last_name', |
@@ -113,7 +76,8 @@ class UserUpdateForm(UserForm): | @@ -113,7 +76,8 @@ class UserUpdateForm(UserForm): | ||
113 | 'google_talk', 'github', 'webpage', 'bio') | 76 | 'google_talk', 'github', 'webpage', 'bio') |
114 | 77 | ||
115 | twitter = SocialAccountField(url='https://twitter.com/', required=False) | 78 | twitter = SocialAccountField(url='https://twitter.com/', required=False) |
116 | - facebook = SocialAccountField(url='https://graph.facebook.com/', required=False) | 79 | + facebook = SocialAccountField(url='https://graph.facebook.com/', |
80 | + required=False) | ||
117 | 81 | ||
118 | 82 | ||
119 | class ListsForm(forms.Form): | 83 | class ListsForm(forms.Form): |
@@ -129,10 +93,11 @@ class ListsForm(forms.Form): | @@ -129,10 +93,11 @@ class ListsForm(forms.Form): | ||
129 | 93 | ||
130 | class ChangeXMPPPasswordForm(forms.ModelForm): | 94 | class ChangeXMPPPasswordForm(forms.ModelForm): |
131 | password1 = forms.CharField(label=_("Password"), | 95 | password1 = forms.CharField(label=_("Password"), |
132 | - widget=forms.PasswordInput) | 96 | + widget=forms.PasswordInput) |
133 | password2 = forms.CharField(label=_("Password confirmation"), | 97 | password2 = forms.CharField(label=_("Password confirmation"), |
134 | - widget=forms.PasswordInput, | ||
135 | - help_text=_("Enter the same password as above, for verification.")) | 98 | + widget=forms.PasswordInput, |
99 | + help_text=_(("Enter the same password as above" | ||
100 | + ", for verification."))) | ||
136 | 101 | ||
137 | class Meta: | 102 | class Meta: |
138 | model = XMPPAccount | 103 | model = XMPPAccount |
@@ -161,6 +126,7 @@ class ChangeXMPPPasswordForm(forms.ModelForm): | @@ -161,6 +126,7 @@ class ChangeXMPPPasswordForm(forms.ModelForm): | ||
161 | self.instance.save() | 126 | self.instance.save() |
162 | return self.instance | 127 | return self.instance |
163 | 128 | ||
129 | + | ||
164 | class UserCreationForm(forms.ModelForm): | 130 | class UserCreationForm(forms.ModelForm): |
165 | """ | 131 | """ |
166 | A form that creates a user, with no privileges, from the given username and | 132 | A form that creates a user, with no privileges, from the given username and |
@@ -171,17 +137,21 @@ class UserCreationForm(forms.ModelForm): | @@ -171,17 +137,21 @@ class UserCreationForm(forms.ModelForm): | ||
171 | 'password_mismatch': _("The two password fields didn't match."), | 137 | 'password_mismatch': _("The two password fields didn't match."), |
172 | } | 138 | } |
173 | username = forms.RegexField(label=_("Username"), max_length=30, | 139 | username = forms.RegexField(label=_("Username"), max_length=30, |
174 | - regex=r'^[\w.@+-]+$', | ||
175 | - help_text=_("Required. 30 characters or fewer. Letters, digits and " | ||
176 | - "@/./+/-/_ only."), | ||
177 | - error_messages={ | ||
178 | - 'invalid': _("This value may contain only letters, numbers and " | ||
179 | - "@/./+/-/_ characters.")}) | 140 | + regex=r'^[\w.@+-]+$', |
141 | + help_text=_(("Required. 30 characters or fewer" | ||
142 | + ". Letters, digits and " | ||
143 | + "@/./+/-/_ only.")), | ||
144 | + error_messages={ | ||
145 | + 'invalid': _(("This value may contain only" | ||
146 | + " letters, numbers and " | ||
147 | + "@/./+/-/_ characters."))}) | ||
180 | password1 = forms.CharField(label=_("Password"), | 148 | password1 = forms.CharField(label=_("Password"), |
181 | - widget=forms.PasswordInput) | 149 | + widget=forms.PasswordInput) |
182 | password2 = forms.CharField(label=_("Password confirmation"), | 150 | password2 = forms.CharField(label=_("Password confirmation"), |
183 | - widget=forms.PasswordInput, | ||
184 | - help_text=_("Enter the same password as above, for verification.")) | 151 | + widget=forms.PasswordInput, |
152 | + help_text=_(("Enter the same password as above" | ||
153 | + ", for verification."))) | ||
154 | + email = forms.EmailField(required=True) | ||
185 | 155 | ||
186 | class Meta: | 156 | class Meta: |
187 | model = User | 157 | model = User |
@@ -190,7 +160,7 @@ class UserCreationForm(forms.ModelForm): | @@ -190,7 +160,7 @@ class UserCreationForm(forms.ModelForm): | ||
190 | def clean_username(self): | 160 | def clean_username(self): |
191 | # Since User.username is unique, this check is redundant, | 161 | # Since User.username is unique, this check is redundant, |
192 | # but it sets a nicer error message than the ORM. See #13147. | 162 | # but it sets a nicer error message than the ORM. See #13147. |
193 | - username = self.cleaned_data["username"] | 163 | + username = self.cleaned_data["username"].strip() |
194 | try: | 164 | try: |
195 | User._default_manager.get(username=username) | 165 | User._default_manager.get(username=username) |
196 | except User.DoesNotExist: | 166 | except User.DoesNotExist: |
@@ -227,9 +197,15 @@ class UserChangeForm(forms.ModelForm): | @@ -227,9 +197,15 @@ class UserChangeForm(forms.ModelForm): | ||
227 | 'invalid': _("This value may contain only letters, numbers and " | 197 | 'invalid': _("This value may contain only letters, numbers and " |
228 | "@/./+/-/_ characters.")}) | 198 | "@/./+/-/_ characters.")}) |
229 | password = ReadOnlyPasswordHashField(label=_("Password"), | 199 | password = ReadOnlyPasswordHashField(label=_("Password"), |
230 | - help_text=_("Raw passwords are not stored, so there is no way to see " | ||
231 | - "this user's password, but you can change the password " | ||
232 | - "using <a href=\"password/\">this form</a>.")) | 200 | + help_text=_("Raw passwords are not" |
201 | + " stored, so there is no" | ||
202 | + " way to see " | ||
203 | + "this user's password, " | ||
204 | + "but you can change the " | ||
205 | + "password " | ||
206 | + "using <a " | ||
207 | + "href=\"password/\">this" | ||
208 | + " form</a>.")) | ||
233 | 209 | ||
234 | class Meta: | 210 | class Meta: |
235 | model = User | 211 | model = User |
@@ -241,6 +217,9 @@ class UserChangeForm(forms.ModelForm): | @@ -241,6 +217,9 @@ class UserChangeForm(forms.ModelForm): | ||
241 | if f is not None: | 217 | if f is not None: |
242 | f.queryset = f.queryset.select_related('content_type') | 218 | f.queryset = f.queryset.select_related('content_type') |
243 | 219 | ||
220 | + # Set email as required field | ||
221 | + self.fields['email'].required = True | ||
222 | + | ||
244 | def clean_password(self): | 223 | def clean_password(self): |
245 | # Regardless of what the user provides, return the initial value. | 224 | # Regardless of what the user provides, return the initial value. |
246 | # This is done here, rather than on the field, because the | 225 | # This is done here, rather than on the field, because the |
@@ -248,6 +227,37 @@ class UserChangeForm(forms.ModelForm): | @@ -248,6 +227,37 @@ class UserChangeForm(forms.ModelForm): | ||
248 | return self.initial["password"] | 227 | return self.initial["password"] |
249 | 228 | ||
250 | 229 | ||
230 | +class UserCreationFormNoBrowserId(UserCreationForm): | ||
231 | + | ||
232 | + password1 = forms.CharField(label=_("Password"), | ||
233 | + widget=forms.PasswordInput) | ||
234 | + password2 = forms.CharField(label=_("Confirm Password "), | ||
235 | + widget=forms.PasswordInput) | ||
236 | + email = forms.EmailField(label=_("Email address"), required=True) | ||
237 | + | ||
238 | + class Meta: | ||
239 | + model = User | ||
240 | + fields = ('first_name', 'last_name', 'email', 'username') | ||
241 | + | ||
242 | + def clean_password2(self): | ||
243 | + password1 = self.cleaned_data.get('password1') | ||
244 | + password2 = self.cleaned_data.get('password2') | ||
245 | + | ||
246 | + if password1 and password2 and password1 != password2: | ||
247 | + raise forms.ValidationError( | ||
248 | + _("The two password fields didn't match.")) | ||
249 | + return password2 | ||
250 | + | ||
251 | + def save(self, commit=True): | ||
252 | + """ | ||
253 | + Saves the new password. | ||
254 | + """ | ||
255 | + self.instance.set_password(self.cleaned_data["password1"]) | ||
256 | + if commit: | ||
257 | + self.instance.save() | ||
258 | + return self.instance | ||
259 | + | ||
260 | + | ||
251 | class AuthenticationForm(forms.Form): | 261 | class AuthenticationForm(forms.Form): |
252 | """ | 262 | """ |
253 | Base class for authenticating users. Extend this to get a form that accepts | 263 | Base class for authenticating users. Extend this to get a form that accepts |
@@ -273,9 +283,11 @@ class AuthenticationForm(forms.Form): | @@ -273,9 +283,11 @@ class AuthenticationForm(forms.Form): | ||
273 | 283 | ||
274 | # Set the label for the "username" field. | 284 | # Set the label for the "username" field. |
275 | UserModel = get_user_model() | 285 | UserModel = get_user_model() |
276 | - self.username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD) | 286 | + self.username_field = UserModel._meta.get_field( |
287 | + UserModel.USERNAME_FIELD) | ||
277 | if self.fields['username'].label is None: | 288 | if self.fields['username'].label is None: |
278 | - self.fields['username'].label = capfirst(self.username_field.verbose_name) | 289 | + self.fields['username'].label = capfirst( |
290 | + self.username_field.verbose_name) | ||
279 | 291 | ||
280 | def clean(self): | 292 | def clean(self): |
281 | username = self.cleaned_data.get('username') | 293 | username = self.cleaned_data.get('username') |
@@ -362,10 +374,12 @@ class PasswordResetForm(forms.Form): | @@ -362,10 +374,12 @@ class PasswordResetForm(forms.Form): | ||
362 | email = loader.render_to_string(email_template_name, c) | 374 | email = loader.render_to_string(email_template_name, c) |
363 | 375 | ||
364 | if html_email_template_name: | 376 | if html_email_template_name: |
365 | - html_email = loader.render_to_string(html_email_template_name, c) | 377 | + html_email = loader.render_to_string(html_email_template_name, |
378 | + c) | ||
366 | else: | 379 | else: |
367 | html_email = None | 380 | html_email = None |
368 | - send_mail(subject, email, from_email, [user.email], html_message=html_email) | 381 | + send_mail(subject, email, from_email, [user.email], |
382 | + html_message=html_email) | ||
369 | 383 | ||
370 | 384 | ||
371 | class SetPasswordForm(forms.Form): | 385 | class SetPasswordForm(forms.Form): |