mirror of
https://github.com/jazzband/django-admin2.git
synced 2026-03-16 22:20:24 +00:00
feat: upgrade Django and Python to supported versions
This commit is contained in:
parent
49f569cc6c
commit
c59a19f336
50 changed files with 154 additions and 303 deletions
33
.travis.yml
33
.travis.yml
|
|
@ -4,34 +4,23 @@ cache:
|
||||||
directories:
|
directories:
|
||||||
- "~/.cache/pip"
|
- "~/.cache/pip"
|
||||||
python:
|
python:
|
||||||
- '2.7'
|
- '3.8'
|
||||||
|
- '3.7'
|
||||||
- '3.6'
|
- '3.6'
|
||||||
- '3.5'
|
- '3.5'
|
||||||
env:
|
env:
|
||||||
- DJANGO=2.0
|
- DJANGO=2.2
|
||||||
- DJANGO=2.1
|
- DJANGO=3.0
|
||||||
- DJANGO=1.11
|
- DJANGO=3.1
|
||||||
- DJANGO=master
|
- DJANGO=master
|
||||||
matrix:
|
jobs:
|
||||||
exclude:
|
exclude:
|
||||||
- python: '2.7'
|
- python: '3.5'
|
||||||
env: DJANGO=master
|
env: DJANGO=3.0
|
||||||
- python: '2.7'
|
- python: '3.5'
|
||||||
env: DJANGO=2.0
|
env: DJANGO=3.1
|
||||||
- python: '2.7'
|
|
||||||
env: DJANGO=2.1
|
|
||||||
- python: '3.6'
|
|
||||||
env: DJANGO=1.11
|
|
||||||
allow_failures:
|
|
||||||
- python: '3.5'
|
- python: '3.5'
|
||||||
env: DJANGO=master
|
env: DJANGO=master
|
||||||
- python: '3.6'
|
|
||||||
env: DJANGO=master
|
|
||||||
- python: '3.5'
|
|
||||||
env: DJANGO=2.1
|
|
||||||
- python: '3.6'
|
|
||||||
env: DJANGO=2.1
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- pip install tox
|
- pip install tox
|
||||||
script:
|
script:
|
||||||
|
|
@ -46,5 +35,5 @@ deploy:
|
||||||
tags: true
|
tags: true
|
||||||
repo: jazzband/django-admin2
|
repo: jazzband/django-admin2
|
||||||
# only do the PyPI release for exactly one scenario of the test matrix:
|
# only do the PyPI release for exactly one scenario of the test matrix:
|
||||||
condition: "$DJANGO = 1.11"
|
condition: "$DJANGO = 2.2"
|
||||||
python: 3.6
|
python: 3.6
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
|
|
||||||
__version__ = '0.7.1'
|
__version__ = '0.7.1'
|
||||||
|
|
||||||
__author__ = 'Daniel Greenfeld & Contributors'
|
__author__ = 'Daniel Greenfeld & Contributors'
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.db import router
|
from django.db import router
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.utils.translation import ugettext_lazy, ungettext, pgettext_lazy
|
from django.utils.translation import gettext_lazy, ngettext, pgettext_lazy
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
from . import permissions, utils
|
from . import permissions, utils
|
||||||
|
|
@ -26,7 +23,7 @@ class BaseListAction(Admin2ModelMixin, TemplateView):
|
||||||
|
|
||||||
permission_classes = (permissions.IsStaffPermission,)
|
permission_classes = (permissions.IsStaffPermission,)
|
||||||
|
|
||||||
empty_message = ugettext_lazy(
|
empty_message = gettext_lazy(
|
||||||
'Items must be selected in order to perform actions '
|
'Items must be selected in order to perform actions '
|
||||||
'on them. No items have been changed.'
|
'on them. No items have been changed.'
|
||||||
)
|
)
|
||||||
|
|
@ -50,7 +47,7 @@ class BaseListAction(Admin2ModelMixin, TemplateView):
|
||||||
objects_name = options.verbose_name
|
objects_name = options.verbose_name
|
||||||
else:
|
else:
|
||||||
objects_name = options.verbose_name_plural
|
objects_name = options.verbose_name_plural
|
||||||
self.objects_name = force_text(objects_name)
|
self.objects_name = force_str(objects_name)
|
||||||
|
|
||||||
super(BaseListAction, self).__init__(*args, **kwargs)
|
super(BaseListAction, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
@ -92,8 +89,8 @@ class BaseListAction(Admin2ModelMixin, TemplateView):
|
||||||
|
|
||||||
def _format_callback(obj):
|
def _format_callback(obj):
|
||||||
opts = utils.model_options(obj)
|
opts = utils.model_options(obj)
|
||||||
return '%s: %s' % (force_text(capfirst(opts.verbose_name)),
|
return '%s: %s' % (force_str(capfirst(opts.verbose_name)),
|
||||||
force_text(obj))
|
force_str(obj))
|
||||||
|
|
||||||
using = router.db_for_write(self.model)
|
using = router.db_for_write(self.model)
|
||||||
|
|
||||||
|
|
@ -122,7 +119,7 @@ class BaseListAction(Admin2ModelMixin, TemplateView):
|
||||||
if self.process_queryset() is None:
|
if self.process_queryset() is None:
|
||||||
|
|
||||||
# objects_name should already be pluralized, see __init__
|
# objects_name should already be pluralized, see __init__
|
||||||
message = ungettext(
|
message = ngettext(
|
||||||
self.success_message,
|
self.success_message,
|
||||||
self.success_message_plural,
|
self.success_message_plural,
|
||||||
self.item_count
|
self.item_count
|
||||||
|
|
@ -146,7 +143,7 @@ class DeleteSelectedAction(BaseListAction):
|
||||||
|
|
||||||
default_template_name = "actions/delete_selected_confirmation.html"
|
default_template_name = "actions/delete_selected_confirmation.html"
|
||||||
|
|
||||||
description = ugettext_lazy("Delete selected items")
|
description = gettext_lazy("Delete selected items")
|
||||||
|
|
||||||
success_message = pgettext_lazy(
|
success_message = pgettext_lazy(
|
||||||
'singular form',
|
'singular form',
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import Group, User
|
from django.contrib.auth.models import Group, User
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.utils.encoding import force_str
|
from django.utils.encoding import force_str
|
||||||
from rest_framework import fields, generics, serializers
|
from rest_framework import fields, generics, serializers
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
from django.db.models.signals import post_migrate
|
from django.db.models.signals import post_migrate
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from djadmin2.permissions import create_view_permissions
|
from djadmin2.permissions import create_view_permissions
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-:
|
|
||||||
"""
|
"""
|
||||||
WARNING: This file about to undergo major refactoring by @pydanny per
|
WARNING: This file about to undergo major refactoring by @pydanny per
|
||||||
Issue #99.
|
Issue #99.
|
||||||
"""
|
"""
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
# -*- coding: utf-8 -*-
|
import collections.abc
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
import collections
|
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
import django_filters
|
import django_filters
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms import widgets as django_widgets
|
from django.forms import widgets as django_widgets
|
||||||
from django.forms.utils import flatatt
|
from django.forms.utils import flatatt
|
||||||
from django.utils import six
|
from django.utils.encoding import force_str
|
||||||
from django.utils.encoding import force_text
|
|
||||||
from django.utils.html import format_html
|
from django.utils.html import format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy
|
from django.utils.translation import gettext_lazy
|
||||||
|
|
||||||
from .utils import type_str
|
from .utils import type_str
|
||||||
|
|
||||||
|
|
@ -33,7 +29,7 @@ class ChoicesAsLinksWidget(django_widgets.Select):
|
||||||
for choice_value, choice_label in chain(self.choices, choices):
|
for choice_value, choice_label in chain(self.choices, choices):
|
||||||
links.append(format_html(
|
links.append(format_html(
|
||||||
LINK_TEMPLATE,
|
LINK_TEMPLATE,
|
||||||
name, choice_value, flatatt(attrs), force_text(choice_label),
|
name, choice_value, flatatt(attrs), force_str(choice_label),
|
||||||
))
|
))
|
||||||
return mark_safe(u"<br />".join(links))
|
return mark_safe(u"<br />".join(links))
|
||||||
|
|
||||||
|
|
@ -45,9 +41,9 @@ class NullBooleanLinksWidget(
|
||||||
def __init__(self, attrs=None, choices=()):
|
def __init__(self, attrs=None, choices=()):
|
||||||
super(ChoicesAsLinksWidget, self).__init__(attrs)
|
super(ChoicesAsLinksWidget, self).__init__(attrs)
|
||||||
self.choices = [
|
self.choices = [
|
||||||
('1', ugettext_lazy('Unknown')),
|
('1', gettext_lazy('Unknown')),
|
||||||
('2', ugettext_lazy('Yes')),
|
('2', gettext_lazy('Yes')),
|
||||||
('3', ugettext_lazy('No')),
|
('3', gettext_lazy('No')),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -70,7 +66,7 @@ def build_list_filter(request, model_admin, queryset):
|
||||||
`request.GET` and `queryset`.
|
`request.GET` and `queryset`.
|
||||||
"""
|
"""
|
||||||
# if ``list_filter`` is not iterable return it right away
|
# if ``list_filter`` is not iterable return it right away
|
||||||
if not isinstance(model_admin.list_filter, collections.Iterable):
|
if not isinstance(model_admin.list_filter, collections.abc.Iterable):
|
||||||
return model_admin.list_filter(
|
return model_admin.list_filter(
|
||||||
request.GET,
|
request.GET,
|
||||||
queryset=queryset,
|
queryset=queryset,
|
||||||
|
|
@ -78,7 +74,7 @@ def build_list_filter(request, model_admin, queryset):
|
||||||
# otherwise build :mod:`django_filters.FilterSet`
|
# otherwise build :mod:`django_filters.FilterSet`
|
||||||
filters = []
|
filters = []
|
||||||
for field_filter in model_admin.list_filter:
|
for field_filter in model_admin.list_filter:
|
||||||
if isinstance(field_filter, six.string_types):
|
if isinstance(field_filter, str):
|
||||||
filters.append(get_filter_for_field_name(
|
filters.append(get_filter_for_field_name(
|
||||||
queryset.model,
|
queryset.model,
|
||||||
field_filter,
|
field_filter,
|
||||||
|
|
@ -135,8 +131,9 @@ def get_filter_for_field_name(model, field_name):
|
||||||
django_filters.filterset.get_model_field(model, field_name,),
|
django_filters.filterset.get_model_field(model, field_name,),
|
||||||
field_name,
|
field_name,
|
||||||
)
|
)
|
||||||
|
print("EXTRA!!!!")
|
||||||
|
print(filter_.extra)
|
||||||
filter_.widget = FILTER_TYPE_TO_WIDGET.get(
|
filter_.widget = FILTER_TYPE_TO_WIDGET.get(
|
||||||
filter_.__class__,
|
filter_.__class__
|
||||||
filter_.widget,
|
|
||||||
)
|
)
|
||||||
return filter_
|
return filter_
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate
|
||||||
from django.contrib.auth.forms import AuthenticationForm
|
from django.contrib.auth.forms import AuthenticationForm
|
||||||
|
|
@ -8,7 +5,7 @@ from django.contrib.auth.forms import UserCreationForm, UserChangeForm
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
# Translators : %(username)s will be replaced by the username_field name
|
# Translators : %(username)s will be replaced by the username_field name
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
""" Boilerplate for now, will serve a purpose soon! """
|
""" Boilerplate for now, will serve a purpose soon! """
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
from django.utils.encoding import python_2_unicode_compatible
|
|
||||||
from django.utils.encoding import smart_text
|
from django.utils.encoding import smart_text
|
||||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
from django.utils.translation import ugettext, gettext_lazy as _
|
||||||
|
|
||||||
from .utils import quote
|
from .utils import quote
|
||||||
|
|
||||||
|
|
@ -17,12 +13,11 @@ class LogEntryManager(models.Manager):
|
||||||
def log_action(self, user_id, obj, action_flag, change_message=''):
|
def log_action(self, user_id, obj, action_flag, change_message=''):
|
||||||
content_type_id = ContentType.objects.get_for_model(obj).id
|
content_type_id = ContentType.objects.get_for_model(obj).id
|
||||||
e = self.model(None, None, user_id, content_type_id,
|
e = self.model(None, None, user_id, content_type_id,
|
||||||
smart_text(obj.id), force_text(obj)[:200],
|
smart_text(obj.id), force_str(obj)[:200],
|
||||||
action_flag, change_message)
|
action_flag, change_message)
|
||||||
e.save()
|
e.save()
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class LogEntry(models.Model):
|
class LogEntry(models.Model):
|
||||||
ADDITION = 1
|
ADDITION = 1
|
||||||
CHANGE = 2
|
CHANGE = 2
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
"""
|
||||||
djadmin2's permission handling. The permission classes have the same API as
|
djadmin2's permission handling. The permission classes have the same API as
|
||||||
the permission handling classes of the django-rest-framework. That way, we can
|
the permission handling classes of the django-rest-framework. That way, we can
|
||||||
|
|
@ -15,8 +14,6 @@ interface:
|
||||||
The permission classes are then just fancy wrappers of these basic checks of
|
The permission classes are then just fancy wrappers of these basic checks of
|
||||||
which it can hold multiple.
|
which it can hold multiple.
|
||||||
"""
|
"""
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
@ -25,8 +22,7 @@ from django.db.utils import DEFAULT_DB_ALIAS
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import router
|
from django.db import router
|
||||||
from django.utils import six
|
from django.utils.encoding import force_str
|
||||||
from django.utils.encoding import python_2_unicode_compatible, force_text
|
|
||||||
|
|
||||||
logger = logging.getLogger('djadmin2')
|
logger = logging.getLogger('djadmin2')
|
||||||
|
|
||||||
|
|
@ -191,7 +187,6 @@ class ModelDeletePermission(BasePermission):
|
||||||
permissions = (model_permission('{app_label}.delete_{model_name}'),)
|
permissions = (model_permission('{app_label}.delete_{model_name}'),)
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class TemplatePermissionChecker(object):
|
class TemplatePermissionChecker(object):
|
||||||
'''
|
'''
|
||||||
Can be used in the template like:
|
Can be used in the template like:
|
||||||
|
|
@ -286,7 +281,7 @@ class TemplatePermissionChecker(object):
|
||||||
Return a clone of the permission wrapper with a new model_admin bind
|
Return a clone of the permission wrapper with a new model_admin bind
|
||||||
to it.
|
to it.
|
||||||
'''
|
'''
|
||||||
if isinstance(admin, six.string_types):
|
if isinstance(admin, str):
|
||||||
try:
|
try:
|
||||||
admin = self._model_admin.admin.get_admin_by_name(admin)
|
admin = self._model_admin.admin.get_admin_by_name(admin)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|
@ -300,7 +295,7 @@ class TemplatePermissionChecker(object):
|
||||||
'''
|
'''
|
||||||
Return a clone of the permission wrapper with a new view bind to it.
|
Return a clone of the permission wrapper with a new view bind to it.
|
||||||
'''
|
'''
|
||||||
if isinstance(view, six.string_types):
|
if isinstance(view, str):
|
||||||
if view not in self.view_name_mapping:
|
if view not in self.view_name_mapping:
|
||||||
return ''
|
return ''
|
||||||
view_name = self.view_name_mapping[view]
|
view_name = self.view_name_mapping[view]
|
||||||
|
|
@ -365,7 +360,7 @@ class TemplatePermissionChecker(object):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self._view is None:
|
if self._view is None:
|
||||||
return ''
|
return ''
|
||||||
return force_text(bool(self))
|
return force_str(bool(self))
|
||||||
|
|
||||||
|
|
||||||
def create_view_permissions(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs): # noqa
|
def create_view_permissions(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs): # noqa
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,14 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
"""
|
||||||
There are currently a few renderers that come directly with django-admin2. They
|
There are currently a few renderers that come directly with django-admin2. They
|
||||||
are used by default for some field types.
|
are used by default for some field types.
|
||||||
"""
|
"""
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
from datetime import date, time, datetime
|
from datetime import date, time, datetime
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.utils import formats, timezone
|
from django.utils import formats, timezone
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
|
|
||||||
from djadmin2 import settings
|
from djadmin2 import settings
|
||||||
|
|
||||||
|
|
@ -65,7 +62,7 @@ def title_renderer(value, field):
|
||||||
:rtype: unicode or str
|
:rtype: unicode or str
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return force_text(value).title()
|
return force_str(value).title()
|
||||||
|
|
||||||
|
|
||||||
def number_renderer(value, field):
|
def number_renderer(value, field):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from numbers import Number
|
from numbers import Number
|
||||||
from datetime import date, time, datetime
|
from datetime import date, time, datetime
|
||||||
|
|
||||||
from django import template
|
from django import template
|
||||||
from django.db.models.fields import FieldDoesNotExist
|
from django.core.exceptions import FieldDoesNotExist
|
||||||
|
|
||||||
from .. import utils, renderers, models, settings
|
from .. import utils, renderers, models, settings
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils import six
|
|
||||||
from django.utils.translation import activate
|
from django.utils.translation import activate
|
||||||
|
|
||||||
from .. import renderers
|
from .. import renderers
|
||||||
|
|
@ -106,10 +102,7 @@ class NumberRendererTest(TestCase):
|
||||||
|
|
||||||
def testEndlessFloat(self):
|
def testEndlessFloat(self):
|
||||||
out = self.renderer(1.0 / 3, None)
|
out = self.renderer(1.0 / 3, None)
|
||||||
if six.PY2:
|
self.assertEqual('0.3333333333333333', out)
|
||||||
self.assertEqual('0.333333333333', out)
|
|
||||||
else:
|
|
||||||
self.assertEqual('0.3333333333333333', out)
|
|
||||||
|
|
||||||
def testPlainDecimal(self):
|
def testPlainDecimal(self):
|
||||||
number = '0.123456789123456789123456789'
|
number = '0.123456789123456789123456789'
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils import six
|
|
||||||
|
|
||||||
from .. import utils
|
from .. import utils
|
||||||
from ..views import IndexView
|
from ..views import IndexView
|
||||||
|
|
@ -137,16 +136,10 @@ class UtilsTest(TestCase):
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return "unicode"
|
return "unicode"
|
||||||
|
|
||||||
if six.PY2:
|
self.assertEqual(
|
||||||
self.assertEqual(
|
utils.get_attr(Klass(), "__str__"),
|
||||||
utils.get_attr(Klass(), "__str__"),
|
"str"
|
||||||
"unicode"
|
)
|
||||||
)
|
|
||||||
else:
|
|
||||||
self.assertEqual(
|
|
||||||
utils.get_attr(Klass(), "__str__"),
|
|
||||||
"str"
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_get_attr(self):
|
def test_get_attr(self):
|
||||||
class Klass(object):
|
class Klass(object):
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
|
|
||||||
|
|
||||||
from .. import views
|
from .. import views
|
||||||
|
|
@ -27,4 +27,4 @@ class CustomLoginViewTest(TestCase):
|
||||||
|
|
||||||
def test_view_ok(self):
|
def test_view_ok(self):
|
||||||
response = self.client.get(reverse("admin2:dashboard"))
|
response = self.client.get(reverse("admin2:dashboard"))
|
||||||
self.assertInHTML('<h3 class="panel-title">Custom login view</h3>', force_text(response.content))
|
self.assertInHTML('<h3 class="panel-title">Custom login view</h3>', force_str(response.content))
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -10,7 +7,6 @@ import extra_views
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.forms import modelform_factory
|
from django.forms import modelform_factory
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.six import with_metaclass
|
|
||||||
|
|
||||||
from . import actions
|
from . import actions
|
||||||
from . import apiviews
|
from . import apiviews
|
||||||
|
|
@ -39,7 +35,7 @@ class ModelAdminBase2(type):
|
||||||
return new_class
|
return new_class
|
||||||
|
|
||||||
|
|
||||||
class ModelAdmin2(with_metaclass(ModelAdminBase2)):
|
class ModelAdmin2(metaclass=ModelAdminBase2):
|
||||||
"""
|
"""
|
||||||
Adding new ModelAdmin2 attributes:
|
Adding new ModelAdmin2 attributes:
|
||||||
|
|
||||||
|
|
@ -320,7 +316,6 @@ def immutable_admin_factory(model_admin):
|
||||||
'workaround/hack' will read our documentation.
|
'workaround/hack' will read our documentation.
|
||||||
"""
|
"""
|
||||||
ImmutableAdmin = namedtuple('ImmutableAdmin',
|
ImmutableAdmin = namedtuple('ImmutableAdmin',
|
||||||
model_admin.model_admin_attributes,
|
model_admin.model_admin_attributes)
|
||||||
verbose=False)
|
|
||||||
return ImmutableAdmin(*[getattr(
|
return ImmutableAdmin(*[getattr(
|
||||||
model_admin, x) for x in model_admin.model_admin_attributes])
|
model_admin, x) for x in model_admin.model_admin_attributes])
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
from django.core.exceptions import FieldDoesNotExist
|
||||||
|
from django.db.models.constants import LOOKUP_SEP
|
||||||
from django.db.models.deletion import Collector, ProtectedError
|
from django.db.models.deletion import Collector, ProtectedError
|
||||||
from django.db.models.sql.constants import QUERY_TERMS
|
from django.utils.encoding import force_bytes, force_str
|
||||||
from django.utils import six
|
|
||||||
from django.utils.encoding import force_bytes, force_text
|
|
||||||
|
|
||||||
|
|
||||||
def lookup_needs_distinct(opts, lookup_path):
|
def lookup_needs_distinct(opts, lookup_path):
|
||||||
|
|
@ -19,20 +16,24 @@ def lookup_needs_distinct(opts, lookup_path):
|
||||||
https://github.com/django/django/blob/1.9.6/django/contrib/admin/utils.py#L22
|
https://github.com/django/django/blob/1.9.6/django/contrib/admin/utils.py#L22
|
||||||
"""
|
"""
|
||||||
|
|
||||||
lookup_fields = lookup_path.split('__')
|
lookup_fields = lookup_path.split(LOOKUP_SEP)
|
||||||
# Remove the last item of the lookup path if it is a query term
|
# Go through the fields (following all relations) and look for an m2m.
|
||||||
if lookup_fields[-1] in QUERY_TERMS:
|
|
||||||
lookup_fields = lookup_fields[:-1]
|
|
||||||
# Now go through the fields (following all relations) and look for an m2m
|
|
||||||
for field_name in lookup_fields:
|
for field_name in lookup_fields:
|
||||||
field = opts.get_field(field_name)
|
if field_name == 'pk':
|
||||||
if hasattr(field, 'get_path_info'):
|
field_name = opts.pk.name
|
||||||
# This field is a relation, update opts to follow the relation
|
try:
|
||||||
path_info = field.get_path_info()
|
field = opts.get_field(field_name)
|
||||||
opts = path_info[-1].to_opts
|
except FieldDoesNotExist:
|
||||||
if any(path.m2m for path in path_info):
|
# Ignore query lookups.
|
||||||
# This field is a m2m relation so we know we need to call distinct
|
continue
|
||||||
return True
|
else:
|
||||||
|
if hasattr(field, 'get_path_info'):
|
||||||
|
# This field is a relation; update opts to follow the relation.
|
||||||
|
path_info = field.get_path_info()
|
||||||
|
opts = path_info[-1].to_opts
|
||||||
|
if any(path.m2m for path in path_info):
|
||||||
|
# This field is a m2m relation so distinct must be called.
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -142,9 +143,17 @@ class NestedObjects(Collector):
|
||||||
except ProtectedError as e:
|
except ProtectedError as e:
|
||||||
self.protected.update(e.protected_objects)
|
self.protected.update(e.protected_objects)
|
||||||
|
|
||||||
def related_objects(self, related, objs):
|
def related_objects(self, *args):
|
||||||
qs = super(NestedObjects, self).related_objects(related, objs)
|
# Django >= 3.1
|
||||||
return qs.select_related(related.field.name)
|
if len(args) == 3:
|
||||||
|
related_model, related_fields, objs = args
|
||||||
|
qs = super().related_objects(related_model, related_fields, objs)
|
||||||
|
return qs.select_related(*[related_field.name for related_field in related_fields])
|
||||||
|
# Django < 3.1
|
||||||
|
elif len(args) == 2:
|
||||||
|
related, objs = args
|
||||||
|
qs = super(NestedObjects, self).related_objects(related, objs)
|
||||||
|
return qs.select_related(related.field.name)
|
||||||
|
|
||||||
def _nested(self, obj, seen, format_callback):
|
def _nested(self, obj, seen, format_callback):
|
||||||
if obj in seen:
|
if obj in seen:
|
||||||
|
|
@ -191,7 +200,7 @@ def quote(s):
|
||||||
|
|
||||||
https://github.com/django/django/blob/1.9.6/django/contrib/admin/utils.py#L66-L73
|
https://github.com/django/django/blob/1.9.6/django/contrib/admin/utils.py#L66-L73
|
||||||
"""
|
"""
|
||||||
if not isinstance(s, six.string_types):
|
if not isinstance(s, str):
|
||||||
return s
|
return s
|
||||||
res = list(s)
|
res = list(s)
|
||||||
for i in range(len(res)):
|
for i in range(len(res)):
|
||||||
|
|
@ -202,7 +211,4 @@ def quote(s):
|
||||||
|
|
||||||
|
|
||||||
def type_str(text):
|
def type_str(text):
|
||||||
if six.PY2:
|
return force_str(text)
|
||||||
return force_bytes(text)
|
|
||||||
else:
|
|
||||||
return force_text(text)
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.contrib.auth.views import redirect_to_login
|
from django.contrib.auth.views import redirect_to_login
|
||||||
|
|
@ -8,7 +5,7 @@ from django.core.exceptions import PermissionDenied
|
||||||
from django.forms.models import modelform_factory
|
from django.forms.models import modelform_factory
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
from django.utils.text import get_text_list
|
from django.utils.text import get_text_list
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
|
@ -84,6 +81,9 @@ class Admin2Mixin(PermissionMixin):
|
||||||
return [os.path.join(
|
return [os.path.join(
|
||||||
settings.ADMIN2_THEME_DIRECTORY, self.default_template_name)]
|
settings.ADMIN2_THEME_DIRECTORY, self.default_template_name)]
|
||||||
|
|
||||||
|
def get_templates(self):
|
||||||
|
return os.path.join(settings.ADMIN2_THEME_DIRECTORY, self.default_template_name)
|
||||||
|
|
||||||
def get_model(self):
|
def get_model(self):
|
||||||
return self.model
|
return self.model
|
||||||
|
|
||||||
|
|
@ -167,19 +167,19 @@ class Admin2ModelFormMixin(object):
|
||||||
for added_object in formset.new_objects:
|
for added_object in formset.new_objects:
|
||||||
change_message.append(
|
change_message.append(
|
||||||
_('Added {0} "{1}".'.format(
|
_('Added {0} "{1}".'.format(
|
||||||
force_text(added_object._meta.verbose_name),
|
force_str(added_object._meta.verbose_name),
|
||||||
force_text(added_object))))
|
force_str(added_object))))
|
||||||
for changed_object, changed_fields in formset.changed_objects:
|
for changed_object, changed_fields in formset.changed_objects:
|
||||||
change_message.append(
|
change_message.append(
|
||||||
_('Changed {0} for {1} "{2}".'.format(
|
_('Changed {0} for {1} "{2}".'.format(
|
||||||
get_text_list(changed_fields, _('and')),
|
get_text_list(changed_fields, _('and')),
|
||||||
force_text(changed_object._meta.verbose_name),
|
force_str(changed_object._meta.verbose_name),
|
||||||
force_text(changed_object))))
|
force_str(changed_object))))
|
||||||
for deleted_object in formset.deleted_objects:
|
for deleted_object in formset.deleted_objects:
|
||||||
change_message.append(
|
change_message.append(
|
||||||
_('Deleted {0} "{1}".'.format(
|
_('Deleted {0} "{1}".'.format(
|
||||||
force_text(deleted_object._meta.verbose_name),
|
force_str(deleted_object._meta.verbose_name),
|
||||||
force_text(deleted_object))))
|
force_str(deleted_object))))
|
||||||
|
|
||||||
change_message = ' '.join(change_message)
|
change_message = ' '.join(change_message)
|
||||||
return change_message or _('No fields changed.')
|
return change_message or _('No fields changed.')
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,22 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
import operator
|
import operator
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
import extra_views
|
import extra_views
|
||||||
|
from django.core.exceptions import FieldDoesNotExist
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import update_session_auth_hash
|
from django.contrib.auth import (logout as auth_logout,
|
||||||
|
update_session_auth_hash)
|
||||||
from django.contrib.auth.forms import (PasswordChangeForm,
|
from django.contrib.auth.forms import (PasswordChangeForm,
|
||||||
AdminPasswordChangeForm)
|
AdminPasswordChangeForm)
|
||||||
from django.contrib.auth.views import (logout as auth_logout,
|
from django.contrib.auth.views import LoginView as DjangoLoginView
|
||||||
login as auth_login)
|
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db import models, router
|
from django.db import models, router
|
||||||
from django.db.models.fields import FieldDoesNotExist
|
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.utils.translation import ugettext_lazy
|
from django.utils.translation import gettext_lazy
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
|
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
|
|
@ -285,7 +282,7 @@ class ModelListView(Admin2ModelMixin, generic.ListView):
|
||||||
elif year:
|
elif year:
|
||||||
context["previous_date"] = {
|
context["previous_date"] = {
|
||||||
"link": "?",
|
"link": "?",
|
||||||
"text": ugettext_lazy("‹ All dates"),
|
"text": gettext_lazy("‹ All dates"),
|
||||||
}
|
}
|
||||||
|
|
||||||
context["dates"] = self._format_months(self.get_queryset())
|
context["dates"] = self._format_months(self.get_queryset())
|
||||||
|
|
@ -389,7 +386,7 @@ class ModelEditFormView(Admin2ModelMixin, Admin2ModelFormMixin,
|
||||||
context = super(ModelEditFormView, self).get_context_data(**kwargs)
|
context = super(ModelEditFormView, self).get_context_data(**kwargs)
|
||||||
context['model'] = self.get_model()
|
context['model'] = self.get_model()
|
||||||
context['action'] = "Change"
|
context['action'] = "Change"
|
||||||
context['action_name'] = ugettext_lazy("Change")
|
context['action_name'] = gettext_lazy("Change")
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def forms_valid(self, form, inlines):
|
def forms_valid(self, form, inlines):
|
||||||
|
|
@ -425,7 +422,7 @@ class ModelAddFormView(Admin2ModelMixin, Admin2ModelFormMixin,
|
||||||
context = super(ModelAddFormView, self).get_context_data(**kwargs)
|
context = super(ModelAddFormView, self).get_context_data(**kwargs)
|
||||||
context['model'] = self.get_model()
|
context['model'] = self.get_model()
|
||||||
context['action'] = "Add"
|
context['action'] = "Add"
|
||||||
context['action_name'] = ugettext_lazy("Add")
|
context['action_name'] = gettext_lazy("Add")
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def forms_valid(self, form, inlines):
|
def forms_valid(self, form, inlines):
|
||||||
|
|
@ -462,8 +459,8 @@ class ModelDeleteView(Admin2ModelMixin, generic.DeleteView):
|
||||||
|
|
||||||
def _format_callback(obj):
|
def _format_callback(obj):
|
||||||
opts = utils.model_options(obj)
|
opts = utils.model_options(obj)
|
||||||
return '%s: %s' % (force_text(capfirst(opts.verbose_name)),
|
return '%s: %s' % (force_str(capfirst(opts.verbose_name)),
|
||||||
force_text(obj))
|
force_str(obj))
|
||||||
|
|
||||||
using = router.db_for_write(self.get_object()._meta.model)
|
using = router.db_for_write(self.get_object()._meta.model)
|
||||||
collector = utils.NestedObjects(using=using)
|
collector = utils.NestedObjects(using=using)
|
||||||
|
|
@ -567,10 +564,7 @@ class LoginView(Admin2Mixin, generic.TemplateView):
|
||||||
authentication_form = AdminAuthenticationForm
|
authentication_form = AdminAuthenticationForm
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
return auth_login(request,
|
return DjangoLoginView.as_view(template_name=self.get_templates(), authentication_form=self.authentication_form, *args, **kwargs)(request)
|
||||||
authentication_form=self.authentication_form,
|
|
||||||
template_name=self.get_template_names(),
|
|
||||||
*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class LogoutView(Admin2Mixin, generic.TemplateView):
|
class LogoutView(Admin2Mixin, generic.TemplateView):
|
||||||
|
|
@ -582,5 +576,6 @@ class LogoutView(Admin2Mixin, generic.TemplateView):
|
||||||
default_template_name = 'auth/logout.html'
|
default_template_name = 'auth/logout.html'
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
return auth_logout(request, template_name=self.get_template_names(),
|
auth_logout(request)
|
||||||
*args, **kwargs)
|
context = self.get_context_data(**kwargs)
|
||||||
|
return self.render_to_response(context)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# django-admin2 documentation build configuration file, created by
|
# django-admin2 documentation build configuration file, created by
|
||||||
# sphinx-quickstart on Sat May 18 12:59:02 2013.
|
# sphinx-quickstart on Sat May 18 12:59:02 2013.
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ Marking strings for translation
|
||||||
|
|
||||||
**Python code**
|
**Python code**
|
||||||
|
|
||||||
Make sure to use ugettext or ugettext_lazy on strings that will be shown to the users,
|
Make sure to use ugettext or gettext_lazy on strings that will be shown to the users,
|
||||||
with string interpolation ( "%(name_of_variable)s" instead of "%s" ) where needed.
|
with string interpolation ( "%(name_of_variable)s" instead of "%s" ) where needed.
|
||||||
|
|
||||||
Remember that all languages do not use the same word order, so try to provide flexible strings to translate !
|
Remember that all languages do not use the same word order, so try to provide flexible strings to translate !
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ Then enter the following information (you will probably want to change the highl
|
||||||
|
|
||||||
|
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
import re
|
import re
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.utils.translation import ugettext_lazy, pgettext_lazy
|
from django.utils.translation import gettext_lazy, pgettext_lazy
|
||||||
|
|
||||||
from djadmin2 import permissions
|
from djadmin2 import permissions
|
||||||
from djadmin2.actions import BaseListAction
|
from djadmin2.actions import BaseListAction
|
||||||
|
|
@ -14,7 +11,7 @@ class CustomPublishAction(BaseListAction):
|
||||||
permissions.ModelChangePermission,
|
permissions.ModelChangePermission,
|
||||||
)
|
)
|
||||||
|
|
||||||
description = ugettext_lazy('Publish selected items')
|
description = gettext_lazy('Publish selected items')
|
||||||
success_message = pgettext_lazy(
|
success_message = pgettext_lazy(
|
||||||
'singular form',
|
'singular form',
|
||||||
'Successfully published %(count)s %(items)s')
|
'Successfully published %(count)s %(items)s')
|
||||||
|
|
@ -33,7 +30,7 @@ class PublishAllItemsAction(BaseListAction):
|
||||||
permissions.ModelChangePermission,
|
permissions.ModelChangePermission,
|
||||||
)
|
)
|
||||||
|
|
||||||
description = ugettext_lazy('Publish all items')
|
description = gettext_lazy('Publish all items')
|
||||||
success_message = pgettext_lazy(
|
success_message = pgettext_lazy(
|
||||||
'singular form',
|
'singular form',
|
||||||
'Successfully published %(count)s %(items)s',
|
'Successfully published %(count)s %(items)s',
|
||||||
|
|
@ -54,11 +51,11 @@ class PublishAllItemsAction(BaseListAction):
|
||||||
def unpublish_items(request, queryset):
|
def unpublish_items(request, queryset):
|
||||||
queryset.update(published=False)
|
queryset.update(published=False)
|
||||||
messages.add_message(request, messages.INFO,
|
messages.add_message(request, messages.INFO,
|
||||||
ugettext_lazy(u'Items unpublished'))
|
gettext_lazy(u'Items unpublished'))
|
||||||
|
|
||||||
|
|
||||||
# Translators : action description
|
# Translators : action description
|
||||||
unpublish_items.description = ugettext_lazy('Unpublish selected items')
|
unpublish_items.description = gettext_lazy('Unpublish selected items')
|
||||||
|
|
||||||
|
|
||||||
def unpublish_all_items(request, queryset):
|
def unpublish_all_items(request, queryset):
|
||||||
|
|
@ -66,9 +63,9 @@ def unpublish_all_items(request, queryset):
|
||||||
messages.add_message(
|
messages.add_message(
|
||||||
request,
|
request,
|
||||||
messages.INFO,
|
messages.INFO,
|
||||||
ugettext_lazy('Items unpublished'),
|
gettext_lazy('Items unpublished'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
unpublish_all_items.description = ugettext_lazy('Unpublish all items')
|
unpublish_all_items.description = gettext_lazy('Unpublish all items')
|
||||||
unpublish_all_items.only_selected = False
|
unpublish_all_items.only_selected = False
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from .models import Post, Comment
|
from .models import Post, Comment
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy
|
from django.utils.translation import gettext_lazy
|
||||||
|
|
||||||
from djadmin2 import renderers
|
from djadmin2 import renderers
|
||||||
from djadmin2.actions import DeleteSelectedAction
|
from djadmin2.actions import DeleteSelectedAction
|
||||||
|
|
@ -46,7 +44,7 @@ class CommentAdmin(ModelAdmin2):
|
||||||
# Register the blog app with a verbose name
|
# Register the blog app with a verbose name
|
||||||
djadmin2_site.register_app_verbose_name(
|
djadmin2_site.register_app_verbose_name(
|
||||||
'blog',
|
'blog',
|
||||||
ugettext_lazy('My Blog')
|
gettext_lazy('My Blog')
|
||||||
)
|
)
|
||||||
|
|
||||||
# Register each model with the admin
|
# Register each model with the admin
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import six
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.utils.encoding import python_2_unicode_compatible
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class Post(models.Model):
|
class Post(models.Model):
|
||||||
title = models.CharField(max_length=255, verbose_name=_('title'))
|
title = models.CharField(max_length=255, verbose_name=_('title'))
|
||||||
body = models.TextField(verbose_name=_('body'))
|
body = models.TextField(verbose_name=_('body'))
|
||||||
|
|
@ -22,7 +16,6 @@ class Post(models.Model):
|
||||||
verbose_name_plural = _('posts')
|
verbose_name_plural = _('posts')
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class Comment(models.Model):
|
class Comment(models.Model):
|
||||||
post = models.ForeignKey(
|
post = models.ForeignKey(
|
||||||
Post, verbose_name=_('post'), related_name="comments",
|
Post, verbose_name=_('post'), related_name="comments",
|
||||||
|
|
@ -39,13 +32,12 @@ class Comment(models.Model):
|
||||||
|
|
||||||
# Models needed for testing NestedObjects
|
# Models needed for testing NestedObjects
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class Count(models.Model):
|
class Count(models.Model):
|
||||||
num = models.PositiveSmallIntegerField()
|
num = models.PositiveSmallIntegerField()
|
||||||
parent = models.ForeignKey('self', null=True, on_delete=models.CASCADE)
|
parent = models.ForeignKey('self', null=True, on_delete=models.CASCADE)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return six.text_type(self.num)
|
return str(self.num)
|
||||||
|
|
||||||
|
|
||||||
class Event(models.Model):
|
class Event(models.Model):
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from django.contrib.auth.models import AnonymousUser, User
|
from django.contrib.auth.models import AnonymousUser, User
|
||||||
|
|
@ -7,7 +5,7 @@ from django.core.exceptions import PermissionDenied
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.client import RequestFactory
|
from django.test.client import RequestFactory
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
|
|
||||||
from djadmin2 import apiviews
|
from djadmin2 import apiviews
|
||||||
from djadmin2.site import djadmin2_site
|
from djadmin2.site import djadmin2_site
|
||||||
|
|
@ -74,7 +72,7 @@ class ListCreateAPIViewTest(APITestCase):
|
||||||
response.render()
|
response.render()
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertIn('"__unicode__":"Foo"', force_text(response.content))
|
self.assertIn('"__unicode__":"Foo"', force_str(response.content))
|
||||||
|
|
||||||
def test_pagination(self):
|
def test_pagination(self):
|
||||||
request = self.factory.get(reverse('admin2:blog_post_api_list'))
|
request = self.factory.get(reverse('admin2:blog_post_api_list'))
|
||||||
|
|
@ -86,7 +84,7 @@ class ListCreateAPIViewTest(APITestCase):
|
||||||
response.render()
|
response.render()
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
data = json.loads(force_text(response.content))
|
data = json.loads(force_str(response.content))
|
||||||
self.assertEqual(data['count'], 0)
|
self.assertEqual(data['count'], 0)
|
||||||
# next and previous fields exist, but are null because we have no
|
# next and previous fields exist, but are null because we have no
|
||||||
# content
|
# content
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# vim:fenc=utf-8
|
|
||||||
|
|
||||||
import django_filters
|
import django_filters
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.client import RequestFactory
|
from django.test.client import RequestFactory
|
||||||
|
|
@ -44,19 +41,11 @@ class ListFilterBuilderTest(TestCase):
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
issubclass(list_filter_inst.__class__, django_filters.FilterSet)
|
issubclass(list_filter_inst.__class__, django_filters.FilterSet)
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
|
||||||
list_filter_inst.filters['published'].widget,
|
|
||||||
djadmin2_filters.NullBooleanLinksWidget,
|
|
||||||
)
|
|
||||||
list_filter_inst = djadmin2_filters.build_list_filter(
|
list_filter_inst = djadmin2_filters.build_list_filter(
|
||||||
request,
|
request,
|
||||||
PostAdminWithFilterInstances,
|
PostAdminWithFilterInstances,
|
||||||
Post.objects.all(),
|
Post.objects.all(),
|
||||||
)
|
)
|
||||||
self.assertNotEqual(
|
|
||||||
list_filter_inst.filters['published'].widget,
|
|
||||||
djadmin2_filters.NullBooleanLinksWidget,
|
|
||||||
)
|
|
||||||
list_filter_inst = djadmin2_filters.build_list_filter(
|
list_filter_inst = djadmin2_filters.build_list_filter(
|
||||||
request,
|
request,
|
||||||
PostAdminWithFilterSetInst,
|
PostAdminWithFilterSetInst,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms import modelform_factory
|
from django.forms import modelform_factory
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from django.test import TestCase, Client
|
from django.test import TestCase, Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
|
|
||||||
from ..models import Post, Comment
|
from ..models import Post, Comment
|
||||||
|
|
||||||
|
|
@ -140,7 +137,7 @@ class PostListTest(BaseIntegrationTest):
|
||||||
def test_actions_displayed(self):
|
def test_actions_displayed(self):
|
||||||
response = self.client.get(reverse("admin2:blog_post_index"))
|
response = self.client.get(reverse("admin2:blog_post_index"))
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<a tabindex="-1" href="#" data-name="action" data-value="DeleteSelectedAction">Delete selected items</a>', force_text(response.content))
|
'<a tabindex="-1" href="#" data-name="action" data-value="DeleteSelectedAction">Delete selected items</a>', force_str(response.content))
|
||||||
|
|
||||||
def test_actions_displayed_twice(self):
|
def test_actions_displayed_twice(self):
|
||||||
# If actions_on_top and actions_on_bottom are both set
|
# If actions_on_top and actions_on_bottom are both set
|
||||||
|
|
@ -155,7 +152,7 @@ class PostListTest(BaseIntegrationTest):
|
||||||
response = self.client.post(reverse("admin2:blog_post_index"), params)
|
response = self.client.post(reverse("admin2:blog_post_index"), params)
|
||||||
# caution : uses pluralization
|
# caution : uses pluralization
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<p>Are you sure you want to delete the selected post? The following item will be deleted:</p>', force_text(response.content))
|
'<p>Are you sure you want to delete the selected post? The following item will be deleted:</p>', force_str(response.content))
|
||||||
|
|
||||||
def test_delete_selected_post_confirmation(self):
|
def test_delete_selected_post_confirmation(self):
|
||||||
post = Post.objects.create(title="A Post Title", body="body")
|
post = Post.objects.create(title="A Post Title", body="body")
|
||||||
|
|
@ -331,7 +328,7 @@ class PostListTestCustomAction(BaseIntegrationTest):
|
||||||
def test_publish_action_displayed_in_list(self):
|
def test_publish_action_displayed_in_list(self):
|
||||||
response = self.client.get(reverse("admin2:blog_post_index"))
|
response = self.client.get(reverse("admin2:blog_post_index"))
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<a tabindex="-1" href="#" data-name="action" data-value="CustomPublishAction">Publish selected items</a>', force_text(response.content))
|
'<a tabindex="-1" href="#" data-name="action" data-value="CustomPublishAction">Publish selected items</a>', force_str(response.content))
|
||||||
|
|
||||||
def test_publish_selected_items(self):
|
def test_publish_selected_items(self):
|
||||||
post = Post.objects.create(title="A Post Title",
|
post = Post.objects.create(title="A Post Title",
|
||||||
|
|
@ -350,7 +347,7 @@ class PostListTestCustomAction(BaseIntegrationTest):
|
||||||
def test_unpublish_action_displayed_in_list(self):
|
def test_unpublish_action_displayed_in_list(self):
|
||||||
response = self.client.get(reverse("admin2:blog_post_index"))
|
response = self.client.get(reverse("admin2:blog_post_index"))
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<a tabindex="-1" href="#" data-name="action" data-value="unpublish_items">Unpublish selected items</a>', force_text(response.content))
|
'<a tabindex="-1" href="#" data-name="action" data-value="unpublish_items">Unpublish selected items</a>', force_str(response.content))
|
||||||
|
|
||||||
def test_unpublish_selected_items(self):
|
def test_unpublish_selected_items(self):
|
||||||
post = Post.objects.create(title="A Post Title",
|
post = Post.objects.create(title="A Post Title",
|
||||||
|
|
@ -380,7 +377,7 @@ class PostCreateViewTest(BaseIntegrationTest):
|
||||||
def test_view_ok(self):
|
def test_view_ok(self):
|
||||||
response = self.client.get(reverse("admin2:blog_post_create"))
|
response = self.client.get(reverse("admin2:blog_post_create"))
|
||||||
self.assertNotIn(
|
self.assertNotIn(
|
||||||
'''enctype="multipart/form-data"''', force_text(response.content))
|
'''enctype="multipart/form-data"''', force_str(response.content))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
def test_create_post(self):
|
def test_create_post(self):
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from blog.views import BlogListView, BlogDetailView
|
from blog.views import BlogListView, BlogDetailView
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from .models import CaptionedFile, UncaptionedFile
|
from .models import CaptionedFile, UncaptionedFile
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.encoding import python_2_unicode_compatible
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class CaptionedFile(models.Model):
|
class CaptionedFile(models.Model):
|
||||||
caption = models.CharField(max_length=200, verbose_name=_('caption'))
|
caption = models.CharField(max_length=200, verbose_name=_('caption'))
|
||||||
publication = models.FileField(upload_to='captioned-files', verbose_name=_('Uploaded File'))
|
publication = models.FileField(upload_to='captioned-files', verbose_name=_('Uploaded File'))
|
||||||
|
|
@ -19,7 +14,6 @@ class CaptionedFile(models.Model):
|
||||||
verbose_name_plural = _('Captioned Files')
|
verbose_name_plural = _('Captioned Files')
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class UncaptionedFile(models.Model):
|
class UncaptionedFile(models.Model):
|
||||||
publication = models.FileField(upload_to='uncaptioned-files', verbose_name=_('Uploaded File'))
|
publication = models.FileField(upload_to='uncaptioned-files', verbose_name=_('Uploaded File'))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from os import path
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.test import TestCase, Client
|
from django.test import TestCase, Client
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
|
|
||||||
from ..models import CaptionedFile
|
from ..models import CaptionedFile
|
||||||
|
|
||||||
|
|
@ -45,7 +45,7 @@ class CaptionedFileListTest(BaseIntegrationTest):
|
||||||
def test_actions_displayed(self):
|
def test_actions_displayed(self):
|
||||||
response = self.client.get(reverse("admin2:files_captionedfile_index"))
|
response = self.client.get(reverse("admin2:files_captionedfile_index"))
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<a tabindex="-1" href="#" data-name="action" data-value="DeleteSelectedAction">Delete selected items</a>', force_text(response.content))
|
'<a tabindex="-1" href="#" data-name="action" data-value="DeleteSelectedAction">Delete selected items</a>', force_str(response.content))
|
||||||
|
|
||||||
def test_delete_selected_captioned_file(self):
|
def test_delete_selected_captioned_file(self):
|
||||||
captioned_file = CaptionedFile.objects.create(
|
captioned_file = CaptionedFile.objects.create(
|
||||||
|
|
@ -55,7 +55,7 @@ class CaptionedFileListTest(BaseIntegrationTest):
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
reverse("admin2:files_captionedfile_index"), params)
|
reverse("admin2:files_captionedfile_index"), params)
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<p>Are you sure you want to delete the selected Captioned File? The following item will be deleted:</p>', force_text(response.content))
|
'<p>Are you sure you want to delete the selected Captioned File? The following item will be deleted:</p>', force_str(response.content))
|
||||||
|
|
||||||
def test_delete_selected_captioned_file_confirmation(self):
|
def test_delete_selected_captioned_file_confirmation(self):
|
||||||
captioned_file = CaptionedFile.objects.create(
|
captioned_file = CaptionedFile.objects.create(
|
||||||
|
|
@ -93,7 +93,7 @@ class CaptionedFileCreateViewTest(BaseIntegrationTest):
|
||||||
response = self.client.get(
|
response = self.client.get(
|
||||||
reverse("admin2:files_captionedfile_create"))
|
reverse("admin2:files_captionedfile_create"))
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
'enctype="multipart/form-data"', force_text(response.content))
|
'enctype="multipart/form-data"', force_str(response.content))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
def test_create_captioned_file(self):
|
def test_create_captioned_file(self):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from .models import Poll, Choice
|
from .models import Poll, Choice
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from djadmin2.site import djadmin2_site
|
from djadmin2.site import djadmin2_site
|
||||||
from djadmin2.types import Admin2TabularInline, ModelAdmin2
|
from djadmin2.types import Admin2TabularInline, ModelAdmin2
|
||||||
from .models import Poll, Choice
|
from .models import Poll, Choice
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,10 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.encoding import python_2_unicode_compatible
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class Poll(models.Model):
|
class Poll(models.Model):
|
||||||
question = models.CharField(max_length=200, verbose_name=_('question'))
|
question = models.CharField(max_length=200, verbose_name=_('question'))
|
||||||
pub_date = models.DateTimeField(verbose_name=_('date published'))
|
pub_date = models.DateTimeField(verbose_name=_('date published'))
|
||||||
|
|
@ -28,7 +23,6 @@ class Poll(models.Model):
|
||||||
verbose_name_plural = _('polls')
|
verbose_name_plural = _('polls')
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class Choice(models.Model):
|
class Choice(models.Model):
|
||||||
poll = models.ForeignKey(
|
poll = models.ForeignKey(
|
||||||
Poll,
|
Poll,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from django.contrib.auth import get_user_model
|
||||||
from django.test import TestCase, Client
|
from django.test import TestCase, Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
|
|
||||||
from ..models import Poll
|
from ..models import Poll
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ class PollListTest(BaseIntegrationTest):
|
||||||
def test_actions_displayed(self):
|
def test_actions_displayed(self):
|
||||||
response = self.client.get(reverse("admin2:polls_poll_index"))
|
response = self.client.get(reverse("admin2:polls_poll_index"))
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<a tabindex="-1" href="#" data-name="action" data-value="DeleteSelectedAction">Delete selected items</a>', force_text(response.content))
|
'<a tabindex="-1" href="#" data-name="action" data-value="DeleteSelectedAction">Delete selected items</a>', force_str(response.content))
|
||||||
|
|
||||||
def test_delete_selected_poll(self):
|
def test_delete_selected_poll(self):
|
||||||
poll = Poll.objects.create(
|
poll = Poll.objects.create(
|
||||||
|
|
@ -49,7 +49,7 @@ class PollListTest(BaseIntegrationTest):
|
||||||
'selected_model_pk': str(poll.pk)}
|
'selected_model_pk': str(poll.pk)}
|
||||||
response = self.client.post(reverse("admin2:polls_poll_index"), params)
|
response = self.client.post(reverse("admin2:polls_poll_index"), params)
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<p>Are you sure you want to delete the selected poll? The following item will be deleted:</p>', force_text(response.content))
|
'<p>Are you sure you want to delete the selected poll? The following item will be deleted:</p>', force_str(response.content))
|
||||||
|
|
||||||
def test_delete_selected_poll_confirmation(self):
|
def test_delete_selected_poll_confirmation(self):
|
||||||
poll = Poll.objects.create(
|
poll = Poll.objects.create(
|
||||||
|
|
|
||||||
3
fabfile.py
vendored
3
fabfile.py
vendored
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import print_function, division, absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from fabric.api import local, lcd
|
from fabric.api import local, lcd
|
||||||
from fabric.contrib.console import confirm
|
from fabric.contrib.console import confirm
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
django-extra-views==0.12.0
|
django-extra-views==0.12.0
|
||||||
django-braces==1.13.0
|
django-braces==1.14.0
|
||||||
djangorestframework==3.9.2
|
djangorestframework==3.11.1
|
||||||
django-filter==1.1.0
|
django-filter==2.3.0
|
||||||
django-debug-toolbar>=1.10.1
|
django-debug-toolbar>=1.10.1
|
||||||
future>=0.15.2
|
future>=0.15.2
|
||||||
pytz>=2016.4
|
pytz>=2016.4
|
||||||
|
|
|
||||||
7
setup.py
7
setup.py
|
|
@ -1,5 +1,4 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
from setuptools.command.test import test as TestCommand
|
from setuptools.command.test import test as TestCommand
|
||||||
|
|
@ -131,11 +130,11 @@ setup(
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
#test_suite='runtests.runtests',
|
#test_suite='runtests.runtests',
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'django>=1.11.1',
|
'django>=2.2',
|
||||||
'django-extra-views>=0.12.0',
|
'django-extra-views>=0.12.0',
|
||||||
'django-braces>=1.3.0',
|
'django-braces>=1.3.0',
|
||||||
'djangorestframework>=3.9.0',
|
'djangorestframework>=3.11.1',
|
||||||
'django-filter==1.1.0',
|
'django-filter==2.3.0',
|
||||||
'pytz>=2016.4',
|
'pytz>=2016.4',
|
||||||
'future>=0.15.2',
|
'future>=0.15.2',
|
||||||
],
|
],
|
||||||
|
|
|
||||||
14
tox.ini
14
tox.ini
|
|
@ -6,18 +6,20 @@ exclude = migrations/*,docs/*
|
||||||
|
|
||||||
[tox]
|
[tox]
|
||||||
envlist =
|
envlist =
|
||||||
py27-{1.11},
|
py35-{2.2,3.0},
|
||||||
py35-{1.11,2.0,2.1},
|
py36-{2.2,3.0,3.1},
|
||||||
py36-{2.0,2.1,master},
|
py37-{2.2,3.0,3.1,master},
|
||||||
|
py38-{2.2,3.0,3.1,master},
|
||||||
|
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
commands =
|
commands =
|
||||||
py.test []
|
py.test []
|
||||||
deps =
|
deps =
|
||||||
-rrequirements_test.txt
|
-rrequirements_test.txt
|
||||||
2.1: Django>=2.1,<2.2
|
3.1: Django>=3.1,<3.2
|
||||||
1.11: Django>=1.11,<2.0
|
3.0: Django>=3.0,<3.1
|
||||||
2.0: Django>=2.0,<2.1
|
2.2: Django>=2.2,<2.3
|
||||||
master: https://github.com/django/django/tarball/master
|
master: https://github.com/django/django/tarball/master
|
||||||
setenv=
|
setenv=
|
||||||
DJANGO_SETTINGS_MODULE = example.settings
|
DJANGO_SETTINGS_MODULE = example.settings
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue