From 7f2ae259207c7f3c2ec74940ef19e41c47502e45 Mon Sep 17 00:00:00 2001 From: arthur Date: Thu, 26 May 2016 19:14:39 +0200 Subject: [PATCH] Removing django-crispy-forms and django-floppyforms Resolve #433 #343 --- HISTORY.rst | 3 +- README.rst | 8 +- djadmin2/contrib/floppyforms.py | 253 ++++++++++++ djadmin2/forms.py | 277 +------------ djadmin2/tests/test_auth_admin.py | 15 +- .../djadmin2theme_bootstrap3/auth/login.html | 4 +- .../auth/password_change_form.html | 4 +- .../edit_inlines/stacked.html | 4 +- .../model_update_form.html | 4 +- djadmin2/types.py | 2 +- docs/installation.rst | 4 - example/blog/tests/test_modelforms.py | 381 ++---------------- example/db.sqlite3 | Bin 77824 -> 84992 bytes example/example/settings.py | 3 - requirements.txt | 2 - setup.py | 2 - tox.ini | 10 +- 17 files changed, 311 insertions(+), 665 deletions(-) create mode 100644 djadmin2/contrib/floppyforms.py diff --git a/HISTORY.rst b/HISTORY.rst index 794b0f7..8e49dad 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -4,7 +4,8 @@ History 0.6.2 (?) * Fix Django 1.8 issues and add 1.9 compatibility -* Update all dependancies (DRF, floppyforms, filters, ...) +* Update django-rest-framework +* Remove django-crispy-forms and django-floppyforms * Regenerate example project to make it django 1.9 compatible * Update tox and travis and add flake8 * Rename AdminModel2Mixin to Admin2ModelMixin diff --git a/README.rst b/README.rst index aaca72d..9fa5bb4 100644 --- a/README.rst +++ b/README.rst @@ -44,18 +44,16 @@ Screenshots Requirements ============ -* Django 1.6+ +* Django 1.7+ * Python 2.7+ or Python 3.3+ * django-braces_ * django-extra-views_ -* django-floppyforms_ * django-rest-framework_ * django-filter_ * Sphinx_ (for documentation) .. _django-braces: https://github.com/brack3t/django-braces .. _django-extra-views: https://github.com/AndrewIngram/django-extra-views -.. _django-floppyforms: https://github.com/brutasse/django-floppyforms .. _django-rest-framework: https://github.com/tomchristie/django-rest-framework .. _django-filter: https://github.com/alex/django-filter .. _Sphinx: http://sphinx-doc.org/ @@ -79,8 +77,6 @@ Add djadmin2 and rest_framework to your settings file: ... 'djadmin2', 'rest_framework', # for the browsable API templates - 'floppyforms', # For HTML5 form fields - 'crispy_forms', # Required for the default theme's layout ... ) @@ -94,7 +90,6 @@ Add setting for apps and the default theme in your settings file: 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 10 } - CRISPY_TEMPLATE_PACK = "bootstrap3" ADMIN2_THEME_DIRECTORY = "djadmin2theme_bootstrap3" Add djadmin2 urls to your URLconf: @@ -154,7 +149,6 @@ Themes are a new default theme based on bootstrap3 and also some new settings to 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 10 } - CRISPY_TEMPLATE_PACK = "bootstrap3" ADMIN2_THEME_DIRECTORY = "djadmin2theme_bootstrap3" diff --git a/djadmin2/contrib/floppyforms.py b/djadmin2/contrib/floppyforms.py new file mode 100644 index 0000000..bf43930 --- /dev/null +++ b/djadmin2/contrib/floppyforms.py @@ -0,0 +1,253 @@ +import django +import floppyforms +from copy import deepcopy + +_WIDGET_COMMON_ATTRIBUTES = ( + 'is_hidden', + 'needs_multipart_form', + 'is_localized', + 'is_required') + +_WIDGET_COMMON_ARGUMENTS = ('attrs',) + + +def _copy_attributes(original, new_widget, attributes): + for attr in attributes: + original_value = getattr(original, attr) + original_value = deepcopy(original_value) + + # Don't set the attribute if it is a property. In that case we can be + # sure that the widget class is taking care of the calculation for that + # property. + old_value_on_new_widget = getattr(new_widget.__class__, attr, None) + if not isinstance(old_value_on_new_widget, property): + setattr(new_widget, attr, original_value) + + +def _create_widget(widget_class, copy_attributes=(), init_arguments=()): + # attach defaults that apply for all widgets + copy_attributes = tuple(copy_attributes) + _WIDGET_COMMON_ATTRIBUTES + init_arguments = tuple(init_arguments) + _WIDGET_COMMON_ARGUMENTS + + def create_new_widget(original): + kwargs = {} + for argname in init_arguments: + kwargs[argname] = getattr(original, argname) + new_widget = widget_class(**kwargs) + _copy_attributes( + original, + new_widget, + copy_attributes) + return new_widget + return create_new_widget + + +def _create_radioselect(original): + # return original widget if the renderer is something else than what + # django ships with by default. This means if this condition evaluates to + # true, then a custom renderer was specified. We cannot emulate its + # behaviour so we shouldn't guess and just return the original widget + if original.renderer is not django.forms.widgets.RadioFieldRenderer: + return original + create_new_widget = _create_widget( + floppyforms.widgets.RadioSelect, + ('choices', 'allow_multiple_selected',)) + return create_new_widget(original) + + +def _create_splitdatetimewidget(widget_class): + def create_new_widget(original): + new_widget = widget_class( + attrs=original.attrs, + date_format=original.widgets[0].format, + time_format=original.widgets[1].format) + _copy_attributes(original, new_widget, _WIDGET_COMMON_ARGUMENTS) + return new_widget + return create_new_widget + + +def _create_multiwidget(widget_class, copy_attributes=(), init_arguments=()): + create_new_widget = _create_widget(widget_class, copy_attributes, + init_arguments) + + def create_new_multiwidget(original): + multiwidget = create_new_widget(original) + multiwidget.widgets = [ + floppify_widget(widget) + for widget in multiwidget.widgets] + return multiwidget + return create_new_multiwidget + +# this dictionary keeps a mapping from django's widget classes to a callable +# that will accept an instance of this class. It will return a new instance of +# a corresponding floppyforms widget, with the same semantics -- all relevant +# attributes will be copied to the new widget. +_django_to_floppyforms_widget = { + django.forms.widgets.Input: + _create_widget(floppyforms.widgets.Input, ('input_type',)), + django.forms.widgets.TextInput: + _create_widget(floppyforms.widgets.TextInput, ('input_type',)), + django.forms.widgets.PasswordInput: + _create_widget(floppyforms.widgets.PasswordInput, ('input_type',)), + django.forms.widgets.HiddenInput: + _create_widget(floppyforms.widgets.HiddenInput, ('input_type',)), + django.forms.widgets.MultipleHiddenInput: + _create_widget( + floppyforms.widgets.MultipleHiddenInput, + ('input_type',), + init_arguments=('choices',)), + django.forms.widgets.FileInput: + _create_widget(floppyforms.widgets.FileInput, ('input_type',)), + django.forms.widgets.ClearableFileInput: + _create_widget( + floppyforms.widgets.ClearableFileInput, + ( + 'input_type', 'initial_text', 'input_text', + 'clear_checkbox_label', 'template_with_initial', + 'template_with_clear')), + django.forms.widgets.Textarea: + _create_widget(floppyforms.widgets.Textarea), + django.forms.widgets.DateInput: + _create_widget( + floppyforms.widgets.DateInput, + init_arguments=('format',)), + django.forms.widgets.DateTimeInput: + _create_widget( + floppyforms.widgets.DateTimeInput, + init_arguments=('format',)), + django.forms.widgets.TimeInput: + _create_widget( + floppyforms.widgets.TimeInput, + init_arguments=('format',)), + django.forms.widgets.CheckboxInput: + _create_widget(floppyforms.widgets.CheckboxInput, ('check_test',)), + django.forms.widgets.Select: + _create_widget( + floppyforms.widgets.Select, + ('choices', 'allow_multiple_selected',)), + django.forms.widgets.NullBooleanSelect: + _create_widget( + floppyforms.widgets.NullBooleanSelect, + ('choices', 'allow_multiple_selected',)), + django.forms.widgets.SelectMultiple: + _create_widget( + floppyforms.widgets.SelectMultiple, + ('choices', 'allow_multiple_selected',)), + django.forms.widgets.RadioSelect: + _create_radioselect, + django.forms.widgets.CheckboxSelectMultiple: + _create_widget( + floppyforms.widgets.CheckboxSelectMultiple, + ('choices', 'allow_multiple_selected',)), + django.forms.widgets.MultiWidget: + _create_widget( + floppyforms.widgets.MultiWidget, + init_arguments=('widgets',)), + django.forms.widgets.SplitDateTimeWidget: + _create_splitdatetimewidget( + floppyforms.widgets.SplitDateTimeWidget), + django.forms.widgets.SplitHiddenDateTimeWidget: + _create_splitdatetimewidget( + floppyforms.widgets.SplitHiddenDateTimeWidget), + django.forms.extras.widgets.SelectDateWidget: + _create_widget( + floppyforms.widgets.SelectDateWidget, + init_arguments=('years',) if django.VERSION >= (1, 7) else ('years', 'required')), +} + +_django_field_to_floppyform_widget = { + django.forms.fields.FloatField: + _create_widget(floppyforms.widgets.NumberInput), + django.forms.fields.DecimalField: + _create_widget(floppyforms.widgets.NumberInput), + django.forms.fields.IntegerField: + _create_widget(floppyforms.widgets.NumberInput), + django.forms.fields.EmailField: + _create_widget(floppyforms.widgets.EmailInput), + django.forms.fields.URLField: + _create_widget(floppyforms.widgets.URLInput), + django.forms.fields.SlugField: + _create_widget(floppyforms.widgets.SlugInput), + django.forms.fields.GenericIPAddressField: + _create_widget(floppyforms.widgets.TextInput), + django.forms.fields.SplitDateTimeField: + _create_splitdatetimewidget(floppyforms.widgets.SplitDateTimeWidget), +} + + +def allow_floppify_widget_for_field(field): + ''' + We only allow to replace a widget with the floppyform counterpart if the + original, by django determined widget is still in place. We don't want to + override custom widgets that a user specified. + ''' + # There is a special case for IntegerFields (and all subclasses) that + # replaces the default TextInput with a NumberInput, if localization is + # turned off. That applies for Django 1.6 upwards. + # See the relevant source code in django: + # https://github.com/django/django/blob/1.9.6/django/forms/fields.py#L261-264 + if isinstance(field, django.forms.IntegerField) and not field.localize: + if field.widget.__class__ is django.forms.NumberInput: + return True + + # We can check if the widget was replaced by comparing the class of the + # specified widget with the default widget that is specified on the field + # class. + if field.widget.__class__ is field.__class__.widget: + return True + + # At that point we are assuming that the user replaced the original widget + # with a custom one. So we don't allow to overwrite it. + return False + + +def floppify_widget(widget, field=None): + ''' + Get an instance of django.forms.widgets.Widget and return a new widget + instance but using the corresponding floppyforms widget class. + + Only original django widgets will be replaced with a floppyforms version. + The widget will be returned unaltered if it is not known, e.g. if it's a + custom widget from a third-party app. + + The optional parameter ``field`` can be used to influence the widget + creation further. This is useful since floppyforms supports more widgets + than django does. For example is django using a ``TextInput`` for a + ``EmailField``, but floppyforms has a better suiting widget called + ``EmailInput``. If a widget is found specifically for the passed in + ``field``, it will take precendence to the first parameter ``widget`` + which will effectively be ignored. + ''' + if field is not None: + create_widget = _django_field_to_floppyform_widget.get( + field.__class__) + if create_widget is not None: + if allow_floppify_widget_for_field(field): + return create_widget(widget) + create_widget = _django_to_floppyforms_widget.get(widget.__class__) + if create_widget is not None: + return create_widget(widget) + return widget + + +def floppify_form(form_class): + ''' + Take a normal form and return a subclass of that form that replaces all + django widgets with the corresponding floppyforms widgets. + ''' + new_form_class = type(form_class.__name__, (form_class,), {}) + for field in new_form_class.base_fields.values(): + field.widget = floppify_widget(field.widget, field=field) + return new_form_class + + +def modelform_factory(model, form=django.forms.models.ModelForm, fields=None, + exclude=None, formfield_callback=None, widgets=None): + form_class = django.forms.models.modelform_factory( + model=model, + form=form, + fields=fields, + exclude=exclude, + formfield_callback=formfield_callback, + widgets=widgets) + return floppify_form(form_class) diff --git a/djadmin2/forms.py b/djadmin2/forms.py index ab7c24d..53a64bc 100644 --- a/djadmin2/forms.py +++ b/djadmin2/forms.py @@ -1,272 +1,16 @@ # -*- coding: utf-8 -*- from __future__ import division, absolute_import, unicode_literals -from copy import deepcopy - -import django -import django.forms -import django.forms.extras.widgets -import django.forms.models -import floppyforms +from django import forms from django.contrib.auth import authenticate from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.forms import UserCreationForm, UserChangeForm +from django.core.exceptions import ValidationError from django.core.urlresolvers import reverse_lazy + from django.utils.translation import ugettext_lazy as _ -_WIDGET_COMMON_ATTRIBUTES = ( - 'is_hidden', - 'needs_multipart_form', - 'is_localized', - 'is_required') - -_WIDGET_COMMON_ARGUMENTS = ('attrs',) - - -def _copy_attributes(original, new_widget, attributes): - for attr in attributes: - original_value = getattr(original, attr) - original_value = deepcopy(original_value) - - # Don't set the attribute if it is a property. In that case we can be - # sure that the widget class is taking care of the calculation for that - # property. - old_value_on_new_widget = getattr(new_widget.__class__, attr, None) - if not isinstance(old_value_on_new_widget, property): - setattr(new_widget, attr, original_value) - - -def _create_widget(widget_class, copy_attributes=(), init_arguments=()): - # attach defaults that apply for all widgets - copy_attributes = tuple(copy_attributes) + _WIDGET_COMMON_ATTRIBUTES - init_arguments = tuple(init_arguments) + _WIDGET_COMMON_ARGUMENTS - - def create_new_widget(original): - kwargs = {} - for argname in init_arguments: - kwargs[argname] = getattr(original, argname) - new_widget = widget_class(**kwargs) - _copy_attributes( - original, - new_widget, - copy_attributes) - return new_widget - return create_new_widget - - -def _create_radioselect(original): - # return original widget if the renderer is something else than what - # django ships with by default. This means if this condition evaluates to - # true, then a custom renderer was specified. We cannot emulate its - # behaviour so we shouldn't guess and just return the original widget - if original.renderer is not django.forms.widgets.RadioFieldRenderer: - return original - create_new_widget = _create_widget( - floppyforms.widgets.RadioSelect, - ('choices', 'allow_multiple_selected',)) - return create_new_widget(original) - - -def _create_splitdatetimewidget(widget_class): - def create_new_widget(original): - new_widget = widget_class( - attrs=original.attrs, - date_format=original.widgets[0].format, - time_format=original.widgets[1].format) - _copy_attributes(original, new_widget, _WIDGET_COMMON_ARGUMENTS) - return new_widget - return create_new_widget - - -def _create_multiwidget(widget_class, copy_attributes=(), init_arguments=()): - create_new_widget = _create_widget(widget_class, copy_attributes, - init_arguments) - - def create_new_multiwidget(original): - multiwidget = create_new_widget(original) - multiwidget.widgets = [ - floppify_widget(widget) - for widget in multiwidget.widgets] - return multiwidget - return create_new_multiwidget - - -# this dictionary keeps a mapping from django's widget classes to a callable -# that will accept an instance of this class. It will return a new instance of -# a corresponding floppyforms widget, with the same semantics -- all relevant -# attributes will be copied to the new widget. -_django_to_floppyforms_widget = { - django.forms.widgets.Input: - _create_widget(floppyforms.widgets.Input, ('input_type',)), - django.forms.widgets.TextInput: - _create_widget(floppyforms.widgets.TextInput, ('input_type',)), - django.forms.widgets.PasswordInput: - _create_widget(floppyforms.widgets.PasswordInput, ('input_type',)), - django.forms.widgets.HiddenInput: - _create_widget(floppyforms.widgets.HiddenInput, ('input_type',)), - django.forms.widgets.MultipleHiddenInput: - _create_widget( - floppyforms.widgets.MultipleHiddenInput, - ('input_type',), - init_arguments=('choices',)), - django.forms.widgets.FileInput: - _create_widget(floppyforms.widgets.FileInput, ('input_type',)), - django.forms.widgets.ClearableFileInput: - _create_widget( - floppyforms.widgets.ClearableFileInput, - ( - 'input_type', 'initial_text', 'input_text', - 'clear_checkbox_label', 'template_with_initial', - 'template_with_clear')), - django.forms.widgets.Textarea: - _create_widget(floppyforms.widgets.Textarea), - django.forms.widgets.DateInput: - _create_widget( - floppyforms.widgets.DateInput, - init_arguments=('format',)), - django.forms.widgets.DateTimeInput: - _create_widget( - floppyforms.widgets.DateTimeInput, - init_arguments=('format',)), - django.forms.widgets.TimeInput: - _create_widget( - floppyforms.widgets.TimeInput, - init_arguments=('format',)), - django.forms.widgets.CheckboxInput: - _create_widget(floppyforms.widgets.CheckboxInput, ('check_test',)), - django.forms.widgets.Select: - _create_widget( - floppyforms.widgets.Select, - ('choices', 'allow_multiple_selected',)), - django.forms.widgets.NullBooleanSelect: - _create_widget( - floppyforms.widgets.NullBooleanSelect, - ('choices', 'allow_multiple_selected',)), - django.forms.widgets.SelectMultiple: - _create_widget( - floppyforms.widgets.SelectMultiple, - ('choices', 'allow_multiple_selected',)), - django.forms.widgets.RadioSelect: - _create_radioselect, - django.forms.widgets.CheckboxSelectMultiple: - _create_widget( - floppyforms.widgets.CheckboxSelectMultiple, - ('choices', 'allow_multiple_selected',)), - django.forms.widgets.MultiWidget: - _create_widget( - floppyforms.widgets.MultiWidget, - init_arguments=('widgets',)), - django.forms.widgets.SplitDateTimeWidget: - _create_splitdatetimewidget( - floppyforms.widgets.SplitDateTimeWidget), - django.forms.widgets.SplitHiddenDateTimeWidget: - _create_splitdatetimewidget( - floppyforms.widgets.SplitHiddenDateTimeWidget), - django.forms.extras.widgets.SelectDateWidget: - _create_widget( - floppyforms.widgets.SelectDateWidget, - init_arguments=('years',) if django.VERSION >= (1, 7) else ('years', 'required')), -} - -_django_field_to_floppyform_widget = { - django.forms.fields.FloatField: - _create_widget(floppyforms.widgets.NumberInput), - django.forms.fields.DecimalField: - _create_widget(floppyforms.widgets.NumberInput), - django.forms.fields.IntegerField: - _create_widget(floppyforms.widgets.NumberInput), - django.forms.fields.EmailField: - _create_widget(floppyforms.widgets.EmailInput), - django.forms.fields.URLField: - _create_widget(floppyforms.widgets.URLInput), - django.forms.fields.SlugField: - _create_widget(floppyforms.widgets.SlugInput), - django.forms.fields.GenericIPAddressField: - _create_widget(floppyforms.widgets.TextInput), - django.forms.fields.SplitDateTimeField: - _create_splitdatetimewidget(floppyforms.widgets.SplitDateTimeWidget), -} - - -def allow_floppify_widget_for_field(field): - ''' - We only allow to replace a widget with the floppyform counterpart if the - original, by django determined widget is still in place. We don't want to - override custom widgets that a user specified. - ''' - # There is a special case for IntegerFields (and all subclasses) that - # replaces the default TextInput with a NumberInput, if localization is - # turned off. That applies for Django 1.6 upwards. - # See the relevant source code in django: - # https://github.com/django/django/blob/1.9.6/django/forms/fields.py#L261-264 - if isinstance(field, django.forms.IntegerField) and not field.localize: - if field.widget.__class__ is django.forms.NumberInput: - return True - - # We can check if the widget was replaced by comparing the class of the - # specified widget with the default widget that is specified on the field - # class. - if field.widget.__class__ is field.__class__.widget: - return True - - # At that point we are assuming that the user replaced the original widget - # with a custom one. So we don't allow to overwrite it. - return False - - -def floppify_widget(widget, field=None): - ''' - Get an instance of django.forms.widgets.Widget and return a new widget - instance but using the corresponding floppyforms widget class. - - Only original django widgets will be replaced with a floppyforms version. - The widget will be returned unaltered if it is not known, e.g. if it's a - custom widget from a third-party app. - - The optional parameter ``field`` can be used to influence the widget - creation further. This is useful since floppyforms supports more widgets - than django does. For example is django using a ``TextInput`` for a - ``EmailField``, but floppyforms has a better suiting widget called - ``EmailInput``. If a widget is found specifically for the passed in - ``field``, it will take precendence to the first parameter ``widget`` - which will effectively be ignored. - ''' - if field is not None: - create_widget = _django_field_to_floppyform_widget.get( - field.__class__) - if create_widget is not None: - if allow_floppify_widget_for_field(field): - return create_widget(widget) - create_widget = _django_to_floppyforms_widget.get(widget.__class__) - if create_widget is not None: - return create_widget(widget) - return widget - - -def floppify_form(form_class): - ''' - Take a normal form and return a subclass of that form that replaces all - django widgets with the corresponding floppyforms widgets. - ''' - new_form_class = type(form_class.__name__, (form_class,), {}) - for field in new_form_class.base_fields.values(): - field.widget = floppify_widget(field.widget, field=field) - return new_form_class - - -def modelform_factory(model, form=django.forms.models.ModelForm, fields=None, - exclude=None, formfield_callback=None, widgets=None): - form_class = django.forms.models.modelform_factory( - model=model, - form=form, - fields=fields, - exclude=exclude, - formfield_callback=formfield_callback, - widgets=widgets) - return floppify_form(form_class) - - # Translators : %(username)s will be replaced by the username_field name # (default : username, but could be email, or something else) ERROR_MESSAGE = _( @@ -284,8 +28,8 @@ class AdminAuthenticationForm(AuthenticationForm): error_messages = { 'required': _("Please log in again, because your session has expired."), } - this_is_the_login_form = django.forms.BooleanField( - widget=floppyforms.HiddenInput, + this_is_the_login_form = forms.BooleanField( + widget=forms.HiddenInput, initial=1, error_messages=error_messages ) @@ -298,16 +42,20 @@ class AdminAuthenticationForm(AuthenticationForm): if username and password: self.user_cache = authenticate(username=username, password=password) if self.user_cache is None: - raise floppyforms.ValidationError(message % { + raise ValidationError(message % { 'username': self.username_field.verbose_name }) elif not self.user_cache.is_active or not self.user_cache.is_staff: - raise floppyforms.ValidationError(message % { + raise ValidationError(message % { 'username': self.username_field.verbose_name }) return self.cleaned_data +class Admin2UserCreationForm(UserCreationForm): + pass + + class Admin2UserChangeForm(UserChangeForm): def __init__(self, *args, **kwargs): @@ -319,6 +67,3 @@ class Admin2UserChangeForm(UserChangeForm): if self.instance and self.instance.pk: return reverse_lazy('admin2:password_change', args=[self.instance.pk]) return 'password/' - -UserCreationForm = floppify_form(UserCreationForm) -UserChangeForm = floppify_form(Admin2UserChangeForm) diff --git a/djadmin2/tests/test_auth_admin.py b/djadmin2/tests/test_auth_admin.py index 88ae67d..be84bb0 100644 --- a/djadmin2/tests/test_auth_admin.py +++ b/djadmin2/tests/test_auth_admin.py @@ -1,10 +1,9 @@ +from django import forms from django.contrib.auth.models import User from django.core.urlresolvers import reverse from django.test import TestCase from django.test.client import RequestFactory -import floppyforms - from djadmin2.site import djadmin2_site from ..admin2 import UserAdmin2 @@ -23,7 +22,7 @@ class UserAdminTest(TestCase): form = UserAdmin2.create_form_class() self.assertTrue( isinstance(form.fields['username'].widget, - floppyforms.TextInput)) + forms.TextInput)) request = self.factory.get(reverse('admin2:auth_user_create')) request.user = self.user @@ -34,16 +33,16 @@ class UserAdminTest(TestCase): form = response.context_data['form'] self.assertTrue( isinstance(form.fields['username'].widget, - floppyforms.TextInput)) + forms.TextInput)) def test_update_form_uses_floppyform_widgets(self): form = UserAdmin2.update_form_class() self.assertTrue( isinstance(form.fields['username'].widget, - floppyforms.TextInput)) + forms.TextInput)) self.assertTrue( isinstance(form.fields['date_joined'].widget, - floppyforms.DateTimeInput)) + forms.DateTimeInput)) request = self.factory.get( reverse('admin2:auth_user_update', args=(self.user.pk,))) @@ -55,7 +54,7 @@ class UserAdminTest(TestCase): form = response.context_data['form'] self.assertTrue( isinstance(form.fields['username'].widget, - floppyforms.TextInput)) + forms.TextInput)) self.assertTrue( isinstance(form.fields['date_joined'].widget, - floppyforms.DateTimeInput)) + forms.DateTimeInput)) diff --git a/djadmin2/themes/djadmin2theme_bootstrap3/templates/djadmin2theme_bootstrap3/auth/login.html b/djadmin2/themes/djadmin2theme_bootstrap3/templates/djadmin2theme_bootstrap3/auth/login.html index 1c094a0..2424740 100644 --- a/djadmin2/themes/djadmin2theme_bootstrap3/templates/djadmin2theme_bootstrap3/auth/login.html +++ b/djadmin2/themes/djadmin2theme_bootstrap3/templates/djadmin2theme_bootstrap3/auth/login.html @@ -1,5 +1,5 @@ {% extends "djadmin2theme_bootstrap3/base.html" %} -{% load i18n staticfiles admin2_tags crispy_forms_tags %} +{% load i18n staticfiles admin2_tags %} {% block navbar %}{% endblock navbar %} {% block breacrumbs %}{% endblock breacrumbs %} @@ -17,7 +17,7 @@
{% csrf_token %} - {{ form|crispy }} + {{ form }}
diff --git a/djadmin2/themes/djadmin2theme_bootstrap3/templates/djadmin2theme_bootstrap3/edit_inlines/stacked.html b/djadmin2/themes/djadmin2theme_bootstrap3/templates/djadmin2theme_bootstrap3/edit_inlines/stacked.html index 83c6941..586da89 100644 --- a/djadmin2/themes/djadmin2theme_bootstrap3/templates/djadmin2theme_bootstrap3/edit_inlines/stacked.html +++ b/djadmin2/themes/djadmin2theme_bootstrap3/templates/djadmin2theme_bootstrap3/edit_inlines/stacked.html @@ -1,8 +1,8 @@ -{% load i18n admin2_tags crispy_forms_tags %} +{% load i18n admin2_tags %} {% for inline_form in formset %}
- {{ inline_form|crispy }} + {{ inline_form }} {% if not inline_form.visible_fields %}

{% trans "This form doesn't have visible fields. This doesn't mean there are no hidden fields." %} diff --git a/djadmin2/themes/djadmin2theme_bootstrap3/templates/djadmin2theme_bootstrap3/model_update_form.html b/djadmin2/themes/djadmin2theme_bootstrap3/templates/djadmin2theme_bootstrap3/model_update_form.html index 72eabe4..470845b 100644 --- a/djadmin2/themes/djadmin2theme_bootstrap3/templates/djadmin2theme_bootstrap3/model_update_form.html +++ b/djadmin2/themes/djadmin2theme_bootstrap3/templates/djadmin2theme_bootstrap3/model_update_form.html @@ -1,6 +1,6 @@ {% extends "djadmin2theme_bootstrap3/base.html" %} -{% load i18n admin2_tags crispy_forms_tags %} +{% load i18n admin2_tags %} {# Translators : examples : Add post, Change object #} {% block title %}{% blocktrans with action=action model_name=model_name %}{{ action_name }} {{ model_name }} @@ -53,7 +53,7 @@

{% csrf_token %} - {{ form|crispy }} + {{ form.as_p }} {% if not form.visible_fields %}

{% trans "This form doesn't have visible fields. This doesn't mean there are no hidden fields." %} diff --git a/djadmin2/types.py b/djadmin2/types.py index 22d522c..d3a366d 100644 --- a/djadmin2/types.py +++ b/djadmin2/types.py @@ -9,6 +9,7 @@ from collections import namedtuple import extra_views from django.conf.urls import url from django.core.urlresolvers import reverse +from django.forms import modelform_factory from django.utils.six import with_metaclass from . import actions @@ -16,7 +17,6 @@ from . import apiviews from . import settings from . import utils from . import views -from .forms import modelform_factory logger = logging.getLogger('djadmin2') diff --git a/docs/installation.rst b/docs/installation.rst index 8f00fec..5ddb351 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -23,8 +23,6 @@ Add djadmin2 and rest_framework to your settings file: 'djadmin2', 'djadmin2.themes.djadmin2theme_bootstrap3', # for the default theme 'rest_framework', # for the browsable API templates - 'floppyforms', # For HTML5 form fields - 'crispy_forms', # Required for the default theme's layout ... ) @@ -32,7 +30,6 @@ Add djadmin2 and rest_framework to your settings file: 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 10 } - CRISPY_TEMPLATE_PACK = "bootstrap3" ADMIN2_THEME_DIRECTORY = "djadmin2theme_bootstrap3" Add djadmin2 urls to your URLconf: @@ -70,5 +67,4 @@ Themes are a new default theme based on bootstrap3 and also some new settings to 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 10 } - CRISPY_TEMPLATE_PACK = "bootstrap3" ADMIN2_THEME_DIRECTORY = "djadmin2theme_bootstrap3" diff --git a/example/blog/tests/test_modelforms.py b/example/blog/tests/test_modelforms.py index 34cb204..7f98a98 100644 --- a/example/blog/tests/test_modelforms.py +++ b/example/blog/tests/test_modelforms.py @@ -1,10 +1,9 @@ from __future__ import unicode_literals -import floppyforms from django import forms +from django.forms import modelform_factory from django.test import TestCase -from djadmin2.forms import floppify_widget, floppify_form, modelform_factory from ..models import Post @@ -14,340 +13,7 @@ class ModelFormFactoryTest(TestCase): form_class = modelform_factory(Post, exclude=[]) self.assertTrue(form_class) field = form_class.base_fields['title'] - self.assertTrue(isinstance(field.widget, floppyforms.TextInput)) - - -class GetFloppyformWidgetTest(TestCase): - - def assertExpectWidget(self, instance, new_class_, - equal_attributes=None, new_attributes=None): - new_instance = floppify_widget(instance) - self.assertEqual(new_instance.__class__, new_class_) - if equal_attributes: - for attribute in equal_attributes: - self.assertTrue( - hasattr(instance, attribute), - 'Cannot check attribute %r, not available on original ' - 'widget %r' % (attribute, instance)) - self.assertTrue( - hasattr(new_instance, attribute), - 'Cannot check attribute %r, not available on generated ' - 'widget %r' % (attribute, new_instance)) - old_attr = getattr(instance, attribute) - new_attr = getattr(new_instance, attribute) - self.assertEqual(old_attr, new_attr, - 'Original widget\'s attribute was not copied: %r != %r' % - (old_attr, new_attr)) - if new_attributes: - for attribute, value in new_attributes.items(): - self.assertTrue( - hasattr(new_instance, attribute), - 'Cannot check new attribute %r, not available on ' - 'generated widget %r' % (attribute, new_instance)) - new_attr = getattr(new_instance, attribute) - self.assertEqual(new_attr, value, - 'Generated widget\'s attribute is not as expected: ' - '%r != %r' % (new_attr, value)) - - def test_created_widget_doesnt_leak_attributes_into_original_widget(self): - widget = forms.TextInput() - widget.is_required = True - widget.attrs = {'placeholder': 'Search ...'} - new_widget = floppify_widget(widget) - self.assertFalse(widget.__dict__ is new_widget.__dict__) - new_widget.is_required = False - self.assertEqual(widget.is_required, True) - new_widget.attrs['placeholder'] = 'Enter name' - self.assertEqual(widget.attrs['placeholder'], 'Search ...') - - def test_copy_attribute_is_required(self): - widget = forms.TextInput() - widget.is_required = True - self.assertExpectWidget( - widget, - floppyforms.TextInput, - equal_attributes=['is_required']) - - # Test individual widgets - - def test_input_widget(self): - self.assertExpectWidget( - forms.widgets.Input(), - floppyforms.widgets.Input) - - widget = forms.widgets.Input() - widget.input_type = 'email' - self.assertExpectWidget( - widget, - floppyforms.widgets.Input, - ['input_type']) - - def test_textinput_widget(self): - self.assertExpectWidget( - forms.widgets.TextInput(), - floppyforms.widgets.TextInput, - ['input_type'], - {'input_type': 'text'}) - - def test_passwordinput_widget(self): - self.assertExpectWidget( - forms.widgets.PasswordInput(), - floppyforms.widgets.PasswordInput, - ['input_type'], - {'input_type': 'password'}) - - def test_hiddeninput_widget(self): - self.assertExpectWidget( - forms.widgets.HiddenInput(), - floppyforms.widgets.HiddenInput) - - widget = forms.widgets.HiddenInput() - self.assertExpectWidget( - widget, - floppyforms.widgets.HiddenInput, - ['input_type']) - - def test_multiplehiddeninput_widget(self): - self.assertExpectWidget( - forms.widgets.MultipleHiddenInput(), - floppyforms.widgets.MultipleHiddenInput) - - widget = forms.widgets.MultipleHiddenInput(choices=( - ('no', 'Please, No!'), - ('yes', 'Ok, why not.'), - )) - self.assertExpectWidget( - widget, - floppyforms.widgets.MultipleHiddenInput, - ['choices']) - - def test_fileinput_widget(self): - self.assertExpectWidget( - forms.widgets.FileInput(), - floppyforms.widgets.FileInput) - - widget = forms.widgets.FileInput() - widget.needs_multipart_form = False - self.assertExpectWidget( - widget, - floppyforms.widgets.FileInput, - ['needs_multipart_form']) - - def test_clearablefileinput_widget(self): - self.assertExpectWidget( - forms.widgets.ClearableFileInput(), - floppyforms.widgets.ClearableFileInput) - - widget = forms.widgets.ClearableFileInput() - widget.initial_text = 'some random text 1' - widget.input_text = 'some random text 2' - widget.clear_checkbox_label = 'some random text 3' - widget.template_with_initial = 'some random text 4' - widget.template_with_clear = 'some random text 5' - self.assertExpectWidget( - widget, - floppyforms.widgets.ClearableFileInput, - ['initial_text', 'input_text', 'clear_checkbox_label', - 'template_with_initial', 'template_with_clear']) - - def test_textarea_widget(self): - self.assertExpectWidget( - forms.widgets.Textarea(), - floppyforms.widgets.Textarea) - - def test_dateinput_widget(self): - self.assertExpectWidget( - forms.DateInput(), - floppyforms.DateInput) - - widget = forms.widgets.DateInput(format='%Y-%m-%d') - self.assertExpectWidget( - widget, - floppyforms.widgets.DateInput, - ['format'], - {'input_type': 'date'}) - - def test_datetimeinput_widget(self): - self.assertExpectWidget( - forms.widgets.DateTimeInput(), - floppyforms.widgets.DateTimeInput) - - widget = forms.widgets.DateTimeInput(format='DATETIME_FORMAT') - self.assertExpectWidget( - widget, - floppyforms.widgets.DateTimeInput, - ['format'], - {'input_type': 'datetime'}) - - def test_timeinput_widget(self): - self.assertExpectWidget( - forms.widgets.TimeInput(), - floppyforms.widgets.TimeInput) - - widget = forms.widgets.TimeInput(format='TIME_FORMAT') - self.assertExpectWidget( - widget, - floppyforms.widgets.TimeInput, - ['format'], - {'input_type': 'time'}) - - def test_checkboxinput_widget(self): - self.assertExpectWidget( - forms.widgets.CheckboxInput(), - floppyforms.widgets.CheckboxInput) - - check_test = lambda v: False - widget = forms.widgets.CheckboxInput(check_test=check_test) - new_widget = floppify_widget(widget) - self.assertEqual(widget.check_test, new_widget.check_test) - self.assertTrue(new_widget.check_test is check_test) - - def test_select_widget(self): - choices = ( - ('draft', 'Draft'), - ('public', 'Public'), - ) - - self.assertExpectWidget( - forms.widgets.Select(), - floppyforms.widgets.Select) - - widget = forms.widgets.Select(choices=choices) - widget.allow_multiple_selected = True - self.assertExpectWidget( - widget, - floppyforms.widgets.Select, - ('choices', 'allow_multiple_selected',)) - - def test_nullbooleanselect_widget(self): - self.assertExpectWidget( - forms.widgets.NullBooleanSelect(), - floppyforms.widgets.NullBooleanSelect, - ('choices', 'allow_multiple_selected',)) - - widget = forms.widgets.NullBooleanSelect() - widget.choices = list(widget.choices) - - value, label = widget.choices[0] - widget.choices[0] = value, 'Maybe' - - self.assertExpectWidget( - widget, - floppyforms.widgets.NullBooleanSelect, - ('choices', 'allow_multiple_selected',)) - - def test_selectmultiple_widget(self): - choices = ( - ('draft', 'Draft'), - ('public', 'Public'), - ) - - self.assertExpectWidget( - forms.widgets.SelectMultiple(), - floppyforms.widgets.SelectMultiple) - - widget = forms.widgets.SelectMultiple(choices=choices) - widget.allow_multiple_selected = False - self.assertExpectWidget( - widget, - floppyforms.widgets.SelectMultiple, - ('choices', 'allow_multiple_selected',)) - - def test_radioselect_widget(self): - choices = ( - ('draft', 'Draft'), - ('public', 'Public'), - ) - - self.assertExpectWidget( - forms.widgets.RadioSelect(), - floppyforms.widgets.RadioSelect) - - self.assertExpectWidget( - forms.widgets.RadioSelect(choices=choices), - floppyforms.widgets.RadioSelect, - ('choices', 'allow_multiple_selected',)) - - widget = forms.widgets.RadioSelect(renderer='custom renderer') - # don't overwrite widget with floppyform widget if a custom renderer - # was used. We cannot copy this over since floppyform doesn't use the - # renderer. - self.assertExpectWidget( - widget, - forms.widgets.RadioSelect) - - def test_checkboxselectmultiple_widget(self): - choices = ( - ('draft', 'Draft'), - ('public', 'Public'), - ) - - self.assertExpectWidget( - forms.widgets.CheckboxSelectMultiple(), - floppyforms.widgets.CheckboxSelectMultiple) - - self.assertExpectWidget( - forms.widgets.CheckboxSelectMultiple(choices=choices), - floppyforms.widgets.CheckboxSelectMultiple, - ('choices', 'allow_multiple_selected',)) - - def test_multi_widget(self): - self.assertExpectWidget( - forms.widgets.MultiWidget([]), - floppyforms.widgets.MultiWidget) - - text_input = forms.widgets.TextInput() - widget = forms.widgets.MultiWidget([text_input]) - new_widget = floppify_widget(widget) - self.assertEqual(widget.widgets, new_widget.widgets) - self.assertTrue(new_widget.widgets[0] is text_input) - - def test_splitdatetime_widget(self): - widget = forms.widgets.SplitDateTimeWidget() - self.assertExpectWidget( - widget, - floppyforms.widgets.SplitDateTimeWidget) - - widget = forms.widgets.SplitDateTimeWidget( - date_format='%Y-%m-%d', time_format='TIME_FORMAT') - new_widget = floppify_widget(widget) - self.assertTrue(isinstance( - new_widget.widgets[0], floppyforms.widgets.DateInput)) - self.assertTrue(isinstance( - new_widget.widgets[1], floppyforms.widgets.TimeInput)) - self.assertEqual(new_widget.widgets[0].format, '%Y-%m-%d') - self.assertEqual(new_widget.widgets[1].format, 'TIME_FORMAT') - - def test_splithiddendatetime_widget(self): - widget = forms.widgets.SplitHiddenDateTimeWidget() - self.assertExpectWidget( - widget, - floppyforms.widgets.SplitHiddenDateTimeWidget) - - widget = forms.widgets.SplitHiddenDateTimeWidget( - date_format='%Y-%m-%d', time_format='TIME_FORMAT') - new_widget = floppify_widget(widget) - self.assertTrue(isinstance( - new_widget.widgets[0], floppyforms.widgets.DateInput)) - self.assertTrue(isinstance( - new_widget.widgets[1], floppyforms.widgets.TimeInput)) - self.assertEqual(new_widget.widgets[0].format, '%Y-%m-%d') - self.assertEqual(new_widget.widgets[0].is_hidden, True) - self.assertEqual(new_widget.widgets[1].format, 'TIME_FORMAT') - self.assertEqual(new_widget.widgets[1].is_hidden, True) - - def test_selectdate_widget(self): - self.assertExpectWidget( - forms.extras.widgets.SelectDateWidget(), - floppyforms.widgets.SelectDateWidget) - - widget = forms.extras.widgets.SelectDateWidget( - attrs={'attribute': 'value'}, - years=[2010, 2011, 2012, 2013]) - self.assertExpectWidget( - widget, - floppyforms.widgets.SelectDateWidget, - ('attrs', 'years')) + self.assertTrue(isinstance(field.widget, forms.TextInput)) class ModelFormTest(TestCase): @@ -360,7 +26,7 @@ class ModelFormTest(TestCase): form = form_class() self.assertTrue(isinstance( form.fields['title'].widget, - floppyforms.widgets.TextInput)) + forms.TextInput)) def test_declared_fields(self): class MyForm(forms.ModelForm): @@ -369,14 +35,14 @@ class ModelFormTest(TestCase): form_class = modelform_factory(model=Post, form=MyForm, exclude=[]) self.assertTrue(isinstance( form_class.base_fields['subtitle'].widget, - floppyforms.widgets.TextInput)) + forms.TextInput)) self.assertTrue(isinstance( form_class.declared_fields['subtitle'].widget, - floppyforms.widgets.TextInput)) + forms.TextInput)) self.assertTrue(isinstance( form_class.base_fields['title'].widget, - floppyforms.widgets.TextInput)) + forms.TextInput)) # title is not defined in declared fields def test_additional_form_fields(self): @@ -387,7 +53,7 @@ class ModelFormTest(TestCase): form = form_class() self.assertTrue(isinstance( form.fields['subtitle'].widget, - floppyforms.widgets.TextInput)) + forms.TextInput)) def test_subclassing_forms(self): class MyForm(forms.ModelForm): @@ -404,13 +70,13 @@ class ModelFormTest(TestCase): form = form_class() self.assertTrue(isinstance( form.fields['title'].widget, - floppyforms.widgets.TextInput)) + forms.TextInput)) self.assertTrue(isinstance( form.fields['subtitle'].widget, - floppyforms.widgets.TextInput)) + forms.TextInput)) self.assertTrue(isinstance( form.fields['created'].widget, - floppyforms.widgets.DateInput)) + forms.DateInput)) class FieldWidgetTest(TestCase): @@ -428,10 +94,9 @@ class FieldWidgetTest(TestCase): model = Post exclude = [] - form_class = floppify_form(MyForm) - widget = form_class().fields['email'].widget - self.assertFalse(isinstance(widget, floppyforms.widgets.EmailInput)) - self.assertTrue(isinstance(widget, floppyforms.widgets.Textarea)) + widget = MyForm().fields['email'].widget + self.assertFalse(isinstance(widget, forms.EmailInput)) + self.assertTrue(isinstance(widget, forms.Textarea)) def test_float_field(self): class MyForm(forms.ModelForm): @@ -439,7 +104,7 @@ class FieldWidgetTest(TestCase): form_class = modelform_factory(model=Post, form=MyForm, exclude=[]) widget = form_class().fields['float'].widget - self.assertTrue(isinstance(widget, floppyforms.widgets.NumberInput)) + self.assertTrue(isinstance(widget, forms.NumberInput)) self.assertEqual(widget.input_type, 'number') def test_decimal_field(self): @@ -448,7 +113,7 @@ class FieldWidgetTest(TestCase): form_class = modelform_factory(model=Post, form=MyForm, exclude=[]) widget = form_class().fields['decimal'].widget - self.assertTrue(isinstance(widget, floppyforms.widgets.NumberInput)) + self.assertTrue(isinstance(widget, forms.NumberInput)) self.assertEqual(widget.input_type, 'number') def test_integer_field(self): @@ -457,7 +122,7 @@ class FieldWidgetTest(TestCase): form_class = modelform_factory(model=Post, form=MyForm, exclude=[]) widget = form_class().fields['integer'].widget - self.assertTrue(isinstance(widget, floppyforms.widgets.NumberInput)) + self.assertTrue(isinstance(widget, forms.NumberInput)) self.assertEqual(widget.input_type, 'number') def test_email_field(self): @@ -466,7 +131,7 @@ class FieldWidgetTest(TestCase): form_class = modelform_factory(model=Post, form=MyForm, exclude=[]) widget = form_class().fields['email'].widget - self.assertTrue(isinstance(widget, floppyforms.widgets.EmailInput)) + self.assertTrue(isinstance(widget, forms.EmailInput)) self.assertEqual(widget.input_type, 'email') def test_url_field(self): @@ -475,7 +140,7 @@ class FieldWidgetTest(TestCase): form_class = modelform_factory(model=Post, form=MyForm, exclude=[]) widget = form_class().fields['url'].widget - self.assertTrue(isinstance(widget, floppyforms.widgets.URLInput)) + self.assertTrue(isinstance(widget, forms.URLInput)) self.assertEqual(widget.input_type, 'url') def test_slug_field(self): @@ -484,7 +149,7 @@ class FieldWidgetTest(TestCase): form_class = modelform_factory(model=Post, form=MyForm, exclude=[]) widget = form_class().fields['slug'].widget - self.assertTrue(isinstance(widget, floppyforms.widgets.SlugInput)) + self.assertTrue(isinstance(widget, forms.TextInput)) self.assertEqual(widget.input_type, 'text') def test_genericipaddress_field(self): @@ -493,7 +158,7 @@ class FieldWidgetTest(TestCase): form_class = modelform_factory(model=Post, form=MyForm, exclude=[]) widget = form_class().fields['ipaddress'].widget - self.assertTrue(isinstance(widget, floppyforms.widgets.TextInput)) + self.assertTrue(isinstance(widget, forms.TextInput)) self.assertEqual(widget.input_type, 'text') def test_splitdatetime_field(self): @@ -503,8 +168,8 @@ class FieldWidgetTest(TestCase): form_class = modelform_factory(model=Post, form=MyForm, exclude=[]) widget = form_class().fields['splitdatetime'].widget self.assertTrue(isinstance( - widget, floppyforms.widgets.SplitDateTimeWidget)) + widget, forms.SplitDateTimeWidget)) self.assertTrue(isinstance( - widget.widgets[0], floppyforms.widgets.DateInput)) + widget.widgets[0], forms.DateInput)) self.assertTrue(isinstance( - widget.widgets[1], floppyforms.widgets.TimeInput)) + widget.widgets[1], forms.TimeInput)) diff --git a/example/db.sqlite3 b/example/db.sqlite3 index 396feb1cdb5f88f5dc1528ab7f789b2d713f70aa..af9b94d73bf16532b678d4ffe5f891bf3bd4ca8c 100644 GIT binary patch delta 2483 zcmbVOeQXvCsC| zi9eF~)WvgFb(#ch-8;dA(1Z}u{+JL_Pt$}D8eN&h02NKZRG}i4Qb3GuVnXzvFpbwv z2uT^5z`pzG?%wzL`aRD*&prLV=INKUFPv(R5(IGxpXcxi@aeyP)qgI3U(fChGu;%C1w-3NI@#bBavJth9b@0V_00%Vu0Ox zu~bY(N`-j7wH4iJ9yoavuN-ZGX5F5c7?Y)JB$G?rXwkH&n!kPmRqzF9Z6V3;5O5Jg zfC!*oovW$ZVQMr^+Cg;!mAxYkbyMAFINgn&_v+9uyvP0ZM}0kmebHRD7|#|X#qvr# zBE|ZKaCqN0+U?+4b5UH%#2+wY#BJ-(l6Ke9w|P06!-1(Wthc z_yauB3j6i(4N+dn#7Ckz`9=t|)#B6=?-8(*ybZnyF5}DhQ14G{`leI6VGN^xq(=7C zelh(-$G-P9vg%%=a{5_Rl_u45Nd~Atk{D1^e1tqkki<;_%wxcR)OMxVFfrI*^bDbQ zPoFl`#cO$p(EHribstCHcf4(W;M*F_jjNir77e&YfNPKuj#rW%cAGuRqBn2`Mv`j3)&VcYcY44~g_PpFgcp9QMv-UmPj z$hQdcEpQc=GA&O-bDJXAn5+Qp8$3saPiLk0m|RE}2WY z(&5xpCOpeaTq;WQ3}^NDIaWx`P~q7bg-gXGoIC|{C|x{1zbu3Tl<0EMQKk|ohnP&d zMml%t{~_>y=Z_hu$Hpnk2;;y68mvwD#Ru>%0q?@QxI4TC7Y85*KCc|fe#q%RkMmvC z_Xs=?Zei7Lz}YV71phsk9kF|8J*TI>}!V8iFH8KX?wD zz!x)k%M5P7qp-o<@cJD1GO5AwoqgjD2?ou;pn^fDX@y{pAOqlMU=A370q@>vpt%O) zewR7YvVhg-YSya61@!k6i(d8ip!xJLtm@`b-phin1FhT)+~^bUS-|ae-zU^pd|H4M zUoZN!U)uyBL%<)x70BRMegIa!bW}?i&pB(|qd-v<6A?2-+(KhHS;V8Il$BOX@m&^J zGh^$a9OD!-PB})#SlY%~E_7&#&dbhPtHZ+fJ>fMmBgMpGE?e2Q<|d0F($Q;e174rFsk)i0T=q-e553_0E$kOX=7$6DcG` zhP4eaR&0M@%AZRYJ>1+ytBV@&4*RGTg{7=n>xI$Ouw{5mNKl2mIO?81Kjle!L?=Z_ zlw2r=e0v?DPS}ACL0M?~zdY~T=aQjDtkjsr#)|o3vXtK~(}x6ni2Zy3O?r4zzq?`} zPZ1h0f@_8B2P5D<4z3G4UbXOz#{Pb=Wqx!R9GC-*xE6Ty>9z^o-R^1aS>)Zm#hD@2 z(_nP>qw8dMPkngM2PEp>HnoyFT#A~7XU<$i!e$rny*Oz^&u<3NA1f!(?>BqlvXn=@ QN)Pf>zK%4N$H34(0q%v|$N&HU delta 680 zcmYk3TS$~a6vxk*^X*0VOFwOQ-FCgKuBi_znD%KF>#jl%YKlP@#A4ZK$z4k!S5eT| zHA#HvVk3T15n-3t$f1`aNa`)vh%9;u#Gs2rVMGr}mr)5Cm>+*;IRF2dGs#&~a!I-5 z$!Q0GeRBU>%~SrG?d?$cX~iUuGAX@&(MW5wN zjkslZNpIv-w8T3o3+kIBY623KbrNOO5?;TAr$oZxmdMDK(3}!h+gws{ZlOnDp)k-3 z3eynXrR#K_7DSG#nRwXNVOOnGWQ`0Yy2Atg(bM!1lq?&6Vkv;-)-93Ss0z;&! zCa^Phi1{FmSGYEk;LoQu{$R$#Lj@|YoU!xP(Pw;NWRmTuFtT;5Qk-YY%Z<(!EJVxY zV4iWY1rLk&XWY1MSo(+N#}!RALpM+rTVo++658}2a;?B&bOrIY2+cfgwwtgA=mLAi zW|>>cRR}_zoLrIBymzyI@ny-6WhsA?CC}%>vCYRGk4Jh>^o9FliRgbaAV=yn;?1~= vi={ony}W`q6~Fu=*Dn&dXi~G=0.6.5 django-braces>=1.3.0 djangorestframework>=3.3.3 -django-floppyforms>=1.6.2 django-filter>=0.13.0 -django-crispy-forms>=1.3.2 django-debug-toolbar>=0.9.4 future>=0.15.2 pytz==2016.4 diff --git a/setup.py b/setup.py index 8294491..c34d80f 100644 --- a/setup.py +++ b/setup.py @@ -131,9 +131,7 @@ setup( 'django-extra-views>=0.6.5', 'django-braces>=1.3.0', 'djangorestframework>=3.3.3', - 'django-floppyforms>=1.6.2', 'django-filter>=0.13.0', - 'django-crispy-forms>=1.3.2', 'pytz==2014.7', 'future>=0.15.2', ], diff --git a/tox.ini b/tox.ini index d1c275a..91b8d84 100644 --- a/tox.ini +++ b/tox.ini @@ -6,11 +6,11 @@ exclude = migrations/*,docs/* [tox] envlist = - py27-{1.8,1.9,master}, - py33-{1.8}, - py34-{1.8,1.9,master}, - py35-{1.8,1.9,master}, - +; py27-{1.8,1.9,master}, +; py33-{1.8}, +; py34-{1.8,1.9,master}, +; py35-{1.8,1.9,master}, + py35-1.9 [testenv] commands = flake8 djadmin2