Allow overriding login form via ``WAGTAILADMIN_USER_LOGIN_FORM`` setting

pull/3832/merge
Mike Dingjan 2017-09-05 14:40:32 +02:00 zatwierdzone przez Matt Westcott
rodzic 3097e5e610
commit ef27853a05
9 zmienionych plików z 80 dodań i 24 usunięć

Wyświetl plik

@ -24,6 +24,7 @@ Changelog
* Added `heading` kwarg to `InlinePanel` to allow heading to be set independently of button label (Adrian Turjak) * Added `heading` kwarg to `InlinePanel` to allow heading to be set independently of button label (Adrian Turjak)
* The value type returned from a `StructBlock` can now be customised (LB (Ben Johnston)) * The value type returned from a `StructBlock` can now be customised (LB (Ben Johnston))
* Added `bgcolor` image operation (Karl Hobley) * Added `bgcolor` image operation (Karl Hobley)
* Added `WAGTAILADMIN_USER_LOGIN_FORM` setting for overriding the admin login form (Mike Dingjan)
* Fix: Do not remove stopwords when generating slugs from non-ASCII titles, to avoid issues with incorrect word boundaries (Sævar Öfjörð Magnússon) * Fix: Do not remove stopwords when generating slugs from non-ASCII titles, to avoid issues with incorrect word boundaries (Sævar Öfjörð Magnússon)
* Fix: The PostgreSQL search backend now preserves ordering of the `QuerySet` when searching with `order_by_relevance=False` (Bertrand Bordage) * Fix: The PostgreSQL search backend now preserves ordering of the `QuerySet` when searching with `order_by_relevance=False` (Bertrand Bordage)
* Fix: Using `modeladmin_register` as a decorator no longer replaces the decorated class with `None` (Tim Heap) * Fix: Using `modeladmin_register` as a decorator no longer replaces the decorated class with `None` (Tim Heap)

Wyświetl plik

@ -224,6 +224,13 @@ Dashboard
This setting lets you change the number of items shown at 'Your most recent edits' on the dashboard. This setting lets you change the number of items shown at 'Your most recent edits' on the dashboard.
.. code-block:: python
WAGTAILADMIN_USER_LOGIN_FORM = 'users.forms.LoginForm'
Allows the default ``LoginForm`` to be extended with extra fields.
Images Images
------ ------

Wyświetl plik

@ -37,6 +37,7 @@ Other features
* Added ``heading`` kwarg to ``InlinePanel`` to allow heading to be set independently of button label (Adrian Turjak) * Added ``heading`` kwarg to ``InlinePanel`` to allow heading to be set independently of button label (Adrian Turjak)
* The value type returned from a ``StructBlock`` can now be customised. See :ref:`custom_value_class_for_structblock` (LB (Ben Johnston)) * The value type returned from a ``StructBlock`` can now be customised. See :ref:`custom_value_class_for_structblock` (LB (Ben Johnston))
* Added `bgcolor` image operation (Karl Hobley) * Added `bgcolor` image operation (Karl Hobley)
* Added ``WAGTAILADMIN_USER_LOGIN_FORM`` setting for overriding the admin login form (Mike Dingjan)
Bug fixes Bug fixes
~~~~~~~~~ ~~~~~~~~~

Wyświetl plik

@ -64,19 +64,24 @@ class EmailLinkChooserForm(forms.Form):
class LoginForm(AuthenticationForm): class LoginForm(AuthenticationForm):
username = forms.CharField( username = forms.CharField(
max_length=254, max_length=254, widget=forms.TextInput(attrs={'tabindex': '1'}))
widget=forms.TextInput(attrs={'tabindex': '1'}),
)
password = forms.CharField( password = forms.CharField(
widget=forms.PasswordInput(attrs={'placeholder': ugettext_lazy("Enter password"), widget=forms.PasswordInput(attrs={
'tabindex': '2', 'tabindex': '2',
}), 'placeholder': ugettext_lazy("Enter password"),
) }))
def __init__(self, request=None, *args, **kwargs): def __init__(self, request=None, *args, **kwargs):
super().__init__(request=request, *args, **kwargs) super().__init__(request=request, *args, **kwargs)
self.fields['username'].widget.attrs['placeholder'] = ugettext_lazy("Enter your %s") \ self.fields['username'].widget.attrs['placeholder'] = (
% self.username_field.verbose_name ugettext_lazy("Enter your %s") % self.username_field.verbose_name)
@property
def extra_fields(self):
for field_name, field in self.fields.items():
if field_name not in ['username', 'password']:
yield field_name, field
class PasswordResetForm(PasswordResetForm): class PasswordResetForm(PasswordResetForm):

Wyświetl plik

@ -56,6 +56,18 @@
<p class="help"><a href="{% url 'wagtailadmin_password_reset' %}">{% trans "Forgotten it?" %}</a></p> <p class="help"><a href="{% url 'wagtailadmin_password_reset' %}">{% trans "Forgotten it?" %}</a></p>
{% endif %} {% endif %}
</li> </li>
{% block extra_fields %}
{% for field_name, field in form.extra_fields %}
<li class="full">
{{ field.label_tag }}
<div class="field iconfield">
{{ field }}
</div>
</li>
{% endfor %}
{% endblock extra_fields %}
{% comment %} {% comment %}
Removed until functionality exists Removed until functionality exists
<li class="checkbox"> <li class="checkbox">

Wyświetl plik

@ -0,0 +1,18 @@
from django.forms.fields import CharField
from django.test import TestCase
from wagtail.admin.forms import LoginForm
class CustomLoginForm(LoginForm):
captcha = CharField(
label='Captcha', help_text="should be in extra_fields()")
class TestLoginForm(TestCase):
def test_extra_fields(self):
form = CustomLoginForm()
self.assertEqual(list(form.extra_fields), [
('captcha', form.fields['captcha'])
])

Wyświetl plik

@ -17,6 +17,15 @@ from wagtail.admin.utils import get_available_admin_languages
from wagtail.core.models import UserPagePermissionsProxy from wagtail.core.models import UserPagePermissionsProxy
from wagtail.users.forms import NotificationPreferencesForm, PreferredLanguageForm from wagtail.users.forms import NotificationPreferencesForm, PreferredLanguageForm
from wagtail.users.models import UserProfile from wagtail.users.models import UserProfile
from wagtail.utils.loading import get_custom_form
def get_user_login_form():
form_setting = 'WAGTAILADMIN_USER_LOGIN_FORM'
if hasattr(settings, form_setting):
return get_custom_form(form_setting)
else:
return forms.LoginForm
# Helper functions to check password management settings to enable/disable views as appropriate. # Helper functions to check password management settings to enable/disable views as appropriate.
@ -136,7 +145,7 @@ def login(request):
return auth_views.login( return auth_views.login(
request, request,
template_name='wagtailadmin/login.html', template_name='wagtailadmin/login.html',
authentication_form=forms.LoginForm, authentication_form=get_user_login_form(),
extra_context={ extra_context={
'show_password_reset': password_reset_enabled(), 'show_password_reset': password_reset_enabled(),
'username_field': get_user_model().USERNAME_FIELD, 'username_field': get_user_model().USERNAME_FIELD,

Wyświetl plik

@ -1,13 +1,12 @@
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.exceptions import ImproperlyConfigured
from django.db.models import Q from django.db.models import Q
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse from django.urls import reverse
from django.utils.module_loading import import_string
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.decorators.vary import vary_on_headers from django.views.decorators.vary import vary_on_headers
from wagtail.utils.loading import get_custom_form
from wagtail.utils.pagination import paginate from wagtail.utils.pagination import paginate
from wagtail.admin import messages from wagtail.admin import messages
from wagtail.admin.forms import SearchForm from wagtail.admin.forms import SearchForm
@ -28,20 +27,10 @@ change_user_perm = "{0}.change_{1}".format(AUTH_USER_APP_LABEL, AUTH_USER_MODEL_
delete_user_perm = "{0}.delete_{1}".format(AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME.lower()) delete_user_perm = "{0}.delete_{1}".format(AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME.lower())
def get_custom_user_form(form_setting):
try:
return import_string(getattr(settings, form_setting))
except ImportError:
raise ImproperlyConfigured(
"%s refers to a form '%s' that is not available" %
(form_setting, getattr(settings, form_setting))
)
def get_user_creation_form(): def get_user_creation_form():
form_setting = 'WAGTAIL_USER_CREATION_FORM' form_setting = 'WAGTAIL_USER_CREATION_FORM'
if hasattr(settings, form_setting): if hasattr(settings, form_setting):
return get_custom_user_form(form_setting) return get_custom_form(form_setting)
else: else:
return UserCreationForm return UserCreationForm
@ -49,7 +38,7 @@ def get_user_creation_form():
def get_user_edit_form(): def get_user_edit_form():
form_setting = 'WAGTAIL_USER_EDIT_FORM' form_setting = 'WAGTAIL_USER_EDIT_FORM'
if hasattr(settings, form_setting): if hasattr(settings, form_setting):
return get_custom_user_form(form_setting) return get_custom_form(form_setting)
else: else:
return UserEditForm return UserEditForm

Wyświetl plik

@ -0,0 +1,14 @@
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils.module_loading import import_string
def get_custom_form(form_setting):
"""Return custom form class if defined and available"""
try:
return import_string(getattr(settings, form_setting))
except ImportError:
raise ImproperlyConfigured(
"%s refers to a form '%s' that is not available" %
(form_setting, getattr(settings, form_setting))
)