chore: cleanup and add support for Python 3.9
parent
b56ded8f0f
commit
51f850f04b
10
.travis.yml
10
.travis.yml
|
|
@ -3,22 +3,18 @@ arch:
|
||||||
- ppc64le
|
- ppc64le
|
||||||
language: python
|
language: python
|
||||||
python:
|
python:
|
||||||
- "3.5"
|
|
||||||
- "3.6"
|
- "3.6"
|
||||||
- "3.7"
|
- "3.7"
|
||||||
- "3.8"
|
- "3.8"
|
||||||
|
- "3.9"
|
||||||
env:
|
env:
|
||||||
- DJANGO_VERSION=2.2 SAMPLE_PROJECT=sample_project
|
- DJANGO_VERSION=2.2 SAMPLE_PROJECT=sample_project
|
||||||
- DJANGO_VERSION=3.0 SAMPLE_PROJECT=sample_project
|
- DJANGO_VERSION=3.1 SAMPLE_PROJECT=sample_project
|
||||||
|
- DJANGO_VERSION=3.2 SAMPLE_PROJECT=sample_project
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- develop
|
- develop
|
||||||
matrix:
|
|
||||||
exclude:
|
|
||||||
-
|
|
||||||
python: "3.5"
|
|
||||||
env: DJANGO_VERSION=3.0 SAMPLE_PROJECT=sample_project
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- pip install django==$DJANGO_VERSION
|
- pip install django==$DJANGO_VERSION
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
VERSION = (2, 2, 3)
|
VERSION = (2, 2, 4)
|
||||||
DEV_N = None
|
DEV_N = None
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
import json
|
import json
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
from django import VERSION
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import url
|
from django.conf.urls import re_path
|
||||||
from django.contrib.admin import ModelAdmin, TabularInline, StackedInline
|
from django.contrib.admin import ModelAdmin, TabularInline, StackedInline
|
||||||
from django.contrib.admin.options import InlineModelAdmin
|
from django.contrib.admin.options import InlineModelAdmin
|
||||||
from django.contrib.admin.views.main import IGNORED_PARAMS, PAGE_VAR
|
from django.contrib.admin.views.main import IGNORED_PARAMS, PAGE_VAR
|
||||||
|
|
@ -13,7 +11,7 @@ from django.contrib.contenttypes.admin import (GenericStackedInline,
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.http import HttpResponse, HttpResponseBadRequest
|
from django.http import JsonResponse
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.template.defaultfilters import capfirst
|
from django.template.defaultfilters import capfirst
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
|
|
@ -116,13 +114,13 @@ class SortableAdmin(SortableAdminBase, ModelAdmin):
|
||||||
info = self.model._meta.app_label, self.model._meta.model_name
|
info = self.model._meta.app_label, self.model._meta.model_name
|
||||||
|
|
||||||
# this ajax view changes the order of instances of the model type
|
# this ajax view changes the order of instances of the model type
|
||||||
admin_do_sorting_url = url(
|
admin_do_sorting_url = re_path(
|
||||||
r'^sort/do-sorting/(?P<model_type_id>\d+)/$',
|
r'^sort/do-sorting/(?P<model_type_id>\d+)/$',
|
||||||
self.admin_site.admin_view(self.do_sorting_view),
|
self.admin_site.admin_view(self.do_sorting_view),
|
||||||
name='%s_%s_do_sorting' % info)
|
name='%s_%s_do_sorting' % info)
|
||||||
|
|
||||||
# this view displays the sortable objects
|
# this view displays the sortable objects
|
||||||
admin_sort_url = url(
|
admin_sort_url = re_path(
|
||||||
r'^sort/$',
|
r'^sort/$',
|
||||||
self.admin_site.admin_view(self.sort_view),
|
self.admin_site.admin_view(self.sort_view),
|
||||||
name='%s_%s_sort' % info)
|
name='%s_%s_sort' % info)
|
||||||
|
|
@ -163,8 +161,7 @@ class SortableAdmin(SortableAdminBase, ModelAdmin):
|
||||||
|
|
||||||
opts = self.model._meta
|
opts = self.model._meta
|
||||||
|
|
||||||
jquery_lib_path = 'admin/js/jquery.js' if VERSION < (1, 9) \
|
jquery_lib_path = 'admin/js/vendor/jquery/jquery.js'
|
||||||
else 'admin/js/vendor/jquery/jquery.js'
|
|
||||||
|
|
||||||
# Determine if we need to regroup objects relative to a
|
# Determine if we need to regroup objects relative to a
|
||||||
# foreign key specified on the model class that is extending Sortable.
|
# foreign key specified on the model class that is extending Sortable.
|
||||||
|
|
@ -179,23 +176,13 @@ class SortableAdmin(SortableAdminBase, ModelAdmin):
|
||||||
|
|
||||||
for field in self.model._meta.fields:
|
for field in self.model._meta.fields:
|
||||||
if isinstance(field, SortableForeignKey):
|
if isinstance(field, SortableForeignKey):
|
||||||
try:
|
|
||||||
sortable_by_fk = field.remote_field.model
|
sortable_by_fk = field.remote_field.model
|
||||||
except AttributeError:
|
|
||||||
# Django < 1.9
|
|
||||||
sortable_by_fk = field.rel.to
|
|
||||||
sortable_by_field_name = field.name.lower()
|
sortable_by_field_name = field.name.lower()
|
||||||
sortable_by_class_is_sortable = \
|
sortable_by_class_is_sortable = \
|
||||||
isinstance(sortable_by_fk, SortableMixin) and \
|
isinstance(sortable_by_fk, SortableMixin) and \
|
||||||
sortable_by_fk.objects.count() >= 2
|
sortable_by_fk.objects.count() >= 2
|
||||||
|
|
||||||
if sortable_by_property:
|
if sortable_by_property:
|
||||||
# backwards compatibility for < 1.1.1, where sortable_by was a
|
|
||||||
# classmethod instead of a property
|
|
||||||
try:
|
|
||||||
sortable_by_class, sortable_by_expression = \
|
|
||||||
sortable_by_property()
|
|
||||||
except (TypeError, ValueError):
|
|
||||||
sortable_by_class = self.model.sortable_by
|
sortable_by_class = self.model.sortable_by
|
||||||
sortable_by_expression = sortable_by_class.__name__.lower()
|
sortable_by_expression = sortable_by_class.__name__.lower()
|
||||||
|
|
||||||
|
|
@ -234,9 +221,6 @@ class SortableAdmin(SortableAdminBase, ModelAdmin):
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
verbose_name_plural = opts.verbose_name_plural
|
verbose_name_plural = opts.verbose_name_plural
|
||||||
|
|
||||||
if VERSION <= (1, 7):
|
|
||||||
context = {}
|
|
||||||
else:
|
|
||||||
context = self.admin_site.each_context(request)
|
context = self.admin_site.each_context(request)
|
||||||
|
|
||||||
filters = urlencode(self.get_querystring_filters(request))
|
filters = urlencode(self.get_querystring_filters(request))
|
||||||
|
|
@ -297,7 +281,7 @@ class SortableAdmin(SortableAdminBase, ModelAdmin):
|
||||||
|
|
||||||
response = {'objects_sorted': False}
|
response = {'objects_sorted': False}
|
||||||
|
|
||||||
if request.is_ajax():
|
if request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
|
||||||
klass = ContentType.objects.get(id=model_type_id).model_class()
|
klass = ContentType.objects.get(id=model_type_id).model_class()
|
||||||
|
|
||||||
indexes = [str(idx) for idx in request.POST.get('indexes', []).split(',')]
|
indexes = [str(idx) for idx in request.POST.get('indexes', []).split(',')]
|
||||||
|
|
@ -311,25 +295,15 @@ class SortableAdmin(SortableAdminBase, ModelAdmin):
|
||||||
qs = klass.objects.select_for_update().filter(**filters)
|
qs = klass.objects.select_for_update().filter(**filters)
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
objects_dict = {str(obj.pk): obj for obj in qs}
|
||||||
# Python 3.6+ only
|
objects_list = [*objects_dict.keys()]
|
||||||
# objects_dict = {str(obj.pk): obj for obj in qs}
|
|
||||||
# objects_list = list(objects_dict.keys())
|
|
||||||
objects_dict = {}
|
|
||||||
objects_list = []
|
|
||||||
for obj in qs:
|
|
||||||
key = str(obj.pk)
|
|
||||||
objects_dict[key] = obj
|
|
||||||
objects_list.append(key)
|
|
||||||
if len(indexes) != len(objects_dict):
|
if len(indexes) != len(objects_dict):
|
||||||
return HttpResponseBadRequest(
|
return JsonResponse({
|
||||||
json.dumps({
|
|
||||||
'objects_sorted': False,
|
'objects_sorted': False,
|
||||||
'reason': _("An object has been added or removed "
|
'reason': _("An object has been added or removed "
|
||||||
"since the last load. Please refresh "
|
"since the last load. Please refresh "
|
||||||
"the page and try reordering again."),
|
"the page and try reordering again."),
|
||||||
}, ensure_ascii=False),
|
}, status_code=400)
|
||||||
content_type='application/json')
|
|
||||||
order_field_name = klass._meta.ordering[0]
|
order_field_name = klass._meta.ordering[0]
|
||||||
|
|
||||||
if order_field_name.startswith('-'):
|
if order_field_name.startswith('-'):
|
||||||
|
|
@ -357,8 +331,7 @@ class SortableAdmin(SortableAdminBase, ModelAdmin):
|
||||||
|
|
||||||
self.after_sorting()
|
self.after_sorting()
|
||||||
|
|
||||||
return HttpResponse(json.dumps(response, ensure_ascii=False),
|
return JsonResponse(response)
|
||||||
content_type='application/json')
|
|
||||||
|
|
||||||
|
|
||||||
class NonSortableParentAdmin(SortableAdmin):
|
class NonSortableParentAdmin(SortableAdmin):
|
||||||
|
|
@ -387,31 +360,19 @@ class SortableInlineBase(SortableAdminBase, InlineModelAdmin):
|
||||||
|
|
||||||
class SortableTabularInline(TabularInline, SortableInlineBase):
|
class SortableTabularInline(TabularInline, SortableInlineBase):
|
||||||
"""Custom template that enables sorting for tabular inlines"""
|
"""Custom template that enables sorting for tabular inlines"""
|
||||||
if VERSION >= (2, 0):
|
|
||||||
template = 'adminsortable/edit_inline/tabular-1.10.x.html'
|
|
||||||
else:
|
|
||||||
template = 'adminsortable/edit_inline/tabular.html'
|
template = 'adminsortable/edit_inline/tabular.html'
|
||||||
|
|
||||||
|
|
||||||
class SortableStackedInline(StackedInline, SortableInlineBase):
|
class SortableStackedInline(StackedInline, SortableInlineBase):
|
||||||
"""Custom template that enables sorting for stacked inlines"""
|
"""Custom template that enables sorting for stacked inlines"""
|
||||||
if VERSION >= (2, 0):
|
|
||||||
template = 'adminsortable/edit_inline/stacked-1.10.x.html'
|
|
||||||
else:
|
|
||||||
template = 'adminsortable/edit_inline/stacked.html'
|
template = 'adminsortable/edit_inline/stacked.html'
|
||||||
|
|
||||||
|
|
||||||
class SortableGenericTabularInline(GenericTabularInline, SortableInlineBase):
|
class SortableGenericTabularInline(GenericTabularInline, SortableInlineBase):
|
||||||
"""Custom template that enables sorting for tabular inlines"""
|
"""Custom template that enables sorting for tabular inlines"""
|
||||||
if VERSION >= (2, 0):
|
|
||||||
template = 'adminsortable/edit_inline/tabular-1.10.x.html'
|
|
||||||
else:
|
|
||||||
template = 'adminsortable/edit_inline/tabular.html'
|
template = 'adminsortable/edit_inline/tabular.html'
|
||||||
|
|
||||||
|
|
||||||
class SortableGenericStackedInline(GenericStackedInline, SortableInlineBase):
|
class SortableGenericStackedInline(GenericStackedInline, SortableInlineBase):
|
||||||
"""Custom template that enables sorting for stacked inlines"""
|
"""Custom template that enables sorting for stacked inlines"""
|
||||||
if VERSION >= (2, 0):
|
|
||||||
template = 'adminsortable/edit_inline/stacked-1.10.x.html'
|
|
||||||
else:
|
|
||||||
template = 'adminsortable/edit_inline/stacked.html'
|
template = 'adminsortable/edit_inline/stacked.html'
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
{% load i18n admin_urls static %}
|
|
||||||
<div class="js-inline-admin-formset inline-group"
|
|
||||||
id="{{ inline_admin_formset.formset.prefix }}-group"
|
|
||||||
data-inline-type="stacked"
|
|
||||||
data-inline-formset="{{ inline_admin_formset.inline_formset_data }}">
|
|
||||||
<fieldset class="module {{ inline_admin_formset.classes }}">
|
|
||||||
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
|
|
||||||
{{ inline_admin_formset.formset.management_form }}
|
|
||||||
{{ inline_admin_formset.formset.non_form_errors }}
|
|
||||||
|
|
||||||
{% for inline_admin_form in inline_admin_formset %}<div class="inline-related{% if inline_admin_form.original or inline_admin_form.show_url %} has_original{% endif %}{% if forloop.last %} empty-form last-related{% endif %}" id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
|
|
||||||
<h3>
|
|
||||||
{% if inline_admin_form.original %}
|
|
||||||
{% with initial_forms_count=inline_admin_formset.formset.management_form.INITIAL_FORMS.value %}
|
|
||||||
<i class="fa fa-{% if forloop.first %}sort-desc{% elif forloop.counter == initial_forms_count %}sort-asc{% else %}sort{% endif %}"></i>
|
|
||||||
{% endwith %}
|
|
||||||
{% endif %}
|
|
||||||
<b>{{ inline_admin_formset.opts.verbose_name|capfirst }}:</b> <span class="inline_label">{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %} <a href="{% url inline_admin_form.model_admin.opts|admin_urlname:'change' inline_admin_form.original.pk|admin_urlquote %}" class="inlinechangelink">{% trans "Change" %}</a>{% endif %}
|
|
||||||
{% else %}#{{ forloop.counter }}{% endif %}</span>
|
|
||||||
{% if inline_admin_form.show_url %}<a href="{{ inline_admin_form.absolute_url }}">{% trans "View on site" %}</a>{% endif %}
|
|
||||||
{% if inline_admin_formset.formset.can_delete and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %}
|
|
||||||
</h3>
|
|
||||||
{% if inline_admin_form.form.non_field_errors %}{{ inline_admin_form.form.non_field_errors }}{% endif %}
|
|
||||||
{% for fieldset in inline_admin_form %}
|
|
||||||
{% include "admin/includes/fieldset.html" %}
|
|
||||||
{% endfor %}
|
|
||||||
{% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
|
|
||||||
{{ inline_admin_form.fk_field.field }}
|
|
||||||
{% if inline_admin_form.original %}
|
|
||||||
<input type="hidden" name="admin_sorting_url" value="{% url opts|admin_urlname:'do_sorting' inline_admin_form.original.model_type_id %}" />
|
|
||||||
{% endif %}
|
|
||||||
</div>{% endfor %}
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,41 +1,34 @@
|
||||||
{% load i18n admin_urls static django_template_additions %}
|
{% load i18n admin_urls static %}
|
||||||
{% get_django_version as django_version %}
|
<div class="js-inline-admin-formset inline-group"
|
||||||
<div class="inline-group" id="{{ inline_admin_formset.formset.prefix }}-group">
|
id="{{ inline_admin_formset.formset.prefix }}-group"
|
||||||
<h2>{{ inline_admin_formset.opts.verbose_name_plural|title }} {% if inline_admin_formset.formset.initial_form_count > 1 %} - {% trans "drag and drop to change order" %}{% endif %}</h2>
|
data-inline-type="stacked"
|
||||||
|
data-inline-formset="{{ inline_admin_formset.inline_formset_data }}">
|
||||||
|
<fieldset class="module {{ inline_admin_formset.classes }}">
|
||||||
|
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
|
||||||
{{ inline_admin_formset.formset.management_form }}
|
{{ inline_admin_formset.formset.management_form }}
|
||||||
{{ inline_admin_formset.formset.non_form_errors }}
|
{{ inline_admin_formset.formset.non_form_errors }}
|
||||||
|
|
||||||
{% for inline_admin_form in inline_admin_formset %}<div class="inline-related {% if django_version.major >= 1 and django_version.minor >= 9 %}flat-admin{% endif %} {% if forloop.last %} empty-form last-related{% endif %} {% if inline_admin_form.original %} has_original{% endif %}" id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
|
{% for inline_admin_form in inline_admin_formset %}<div class="inline-related{% if inline_admin_form.original or inline_admin_form.show_url %} has_original{% endif %}{% if forloop.last %} empty-form last-related{% endif %}" id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
|
||||||
<h3>
|
<h3>
|
||||||
{% if inline_admin_form.original %}
|
{% if inline_admin_form.original %}
|
||||||
{% with initial_forms_count=inline_admin_formset.formset.management_form.INITIAL_FORMS.value %}
|
{% with initial_forms_count=inline_admin_formset.formset.management_form.INITIAL_FORMS.value %}
|
||||||
<i class="fa fa-{% if forloop.first %}sort-desc{% elif forloop.counter == initial_forms_count %}sort-asc{% else %}sort{% endif %}"></i>
|
<i class="fa fa-{% if forloop.first %}sort-desc{% elif forloop.counter == initial_forms_count %}sort-asc{% else %}sort{% endif %}"></i>
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<b>{{ inline_admin_formset.opts.verbose_name|title }}:</b> <span class="inline_label">{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %} <a href="{% url inline_admin_form.model_admin.opts|admin_urlname:'change' inline_admin_form.original.pk|admin_urlquote %}" class="inlinechangelink">{% trans "Change" %}</a>{% endif %}
|
<b>{{ inline_admin_formset.opts.verbose_name|capfirst }}:</b> <span class="inline_label">{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %} <a href="{% url inline_admin_form.model_admin.opts|admin_urlname:'change' inline_admin_form.original.pk|admin_urlquote %}" class="inlinechangelink">{% trans "Change" %}</a>{% endif %}
|
||||||
{% else %}#{{ forloop.counter }}{% endif %}</span>
|
{% else %}#{{ forloop.counter }}{% endif %}</span>
|
||||||
{% if inline_admin_form.show_url %}<a href="{% url 'admin:view_on_site' inline_admin_form.original_content_type_id inline_admin_form.original.pk %}">{% trans "View on site" %}</a>{% endif %}
|
{% if inline_admin_form.show_url %}<a href="{{ inline_admin_form.absolute_url }}">{% trans "View on site" %}</a>{% endif %}
|
||||||
{% if inline_admin_formset.formset.can_delete and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %}
|
{% if inline_admin_formset.formset.can_delete and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %}
|
||||||
</h3>
|
</h3>
|
||||||
{% if inline_admin_form.form.non_field_errors %}{{ inline_admin_form.form.non_field_errors }}{% endif %}
|
{% if inline_admin_form.form.non_field_errors %}{{ inline_admin_form.form.non_field_errors }}{% endif %}
|
||||||
{% for fieldset in inline_admin_form %}
|
{% for fieldset in inline_admin_form %}
|
||||||
{% include "admin/includes/fieldset.html" %}
|
{% include "admin/includes/fieldset.html" %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
|
||||||
|
{{ inline_admin_form.fk_field.field }}
|
||||||
{% if inline_admin_form.original %}
|
{% if inline_admin_form.original %}
|
||||||
<input type="hidden" name="admin_sorting_url" value="{% url opts|admin_urlname:'do_sorting' inline_admin_form.original.model_type_id %}" />
|
<input type="hidden" name="admin_sorting_url" value="{% url opts|admin_urlname:'do_sorting' inline_admin_form.original.model_type_id %}" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
|
|
||||||
{{ inline_admin_form.fk_field.field }}
|
|
||||||
</div>{% endfor %}
|
</div>{% endfor %}
|
||||||
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
(function($) {
|
|
||||||
$("#{{ inline_admin_formset.formset.prefix }}-group .inline-related").stackedFormset({
|
|
||||||
prefix: '{{ inline_admin_formset.formset.prefix }}',
|
|
||||||
adminStaticPrefix: '{% static "admin/" %}',
|
|
||||||
deleteText: "{% trans "Remove" %}",
|
|
||||||
addText: "{% blocktrans with verbose_name=inline_admin_formset.opts.verbose_name|title %}Add another {{ verbose_name }}{% endblocktrans %}"
|
|
||||||
});
|
|
||||||
})(django.jQuery);
|
|
||||||
</script>
|
|
||||||
|
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
{% load i18n admin_urls static admin_modify django_template_additions %}
|
|
||||||
<div class="js-inline-admin-formset inline-group" id="{{ inline_admin_formset.formset.prefix }}-group"
|
|
||||||
data-inline-type="tabular"
|
|
||||||
data-inline-formset="{{ inline_admin_formset.inline_formset_data }}">
|
|
||||||
<div class="tabular inline-related {% if forloop.last %}last-related{% endif %}">
|
|
||||||
{{ inline_admin_formset.formset.management_form }}
|
|
||||||
<fieldset class="module {{ inline_admin_formset.classes }}">
|
|
||||||
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
|
|
||||||
{{ inline_admin_formset.formset.non_form_errors }}
|
|
||||||
<table>
|
|
||||||
<thead><tr>
|
|
||||||
<th class="original"></th>
|
|
||||||
{% for field in inline_admin_formset.fields %}
|
|
||||||
{% if not field.widget.is_hidden %}
|
|
||||||
<th{% if field.required %} class="required"{% endif %}>{{ field.label|capfirst }}
|
|
||||||
{% if field.help_text %} <img src="{% static "admin/img/icon-unknown.svg" %}" class="help help-tooltip" width="10" height="10" alt="({{ field.help_text|striptags }})" title="{{ field.help_text|striptags }}" />{% endif %}
|
|
||||||
</th>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% if inline_admin_formset.formset.can_delete %}<th>{% trans "Delete?" %}</th>{% endif %}
|
|
||||||
</tr></thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
{% for inline_admin_form in inline_admin_formset %}
|
|
||||||
{% if inline_admin_form.form.non_field_errors %}
|
|
||||||
<tr><td colspan="{{ inline_admin_form|cell_count }}">{{ inline_admin_form.form.non_field_errors }}</td></tr>
|
|
||||||
{% endif %}
|
|
||||||
<tr class="form-row {% cycle "row1" "row2" %} {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}{% if forloop.last %} empty-form{% endif %}"
|
|
||||||
id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
|
|
||||||
<td class="original">
|
|
||||||
{% if inline_admin_form.original or inline_admin_form.show_url %}<p>
|
|
||||||
{% with initial_forms_count=inline_admin_form.formset.management_form.INITIAL_FORMS.value %}
|
|
||||||
<i class="fa fa-{% if forloop.first %}sort-desc{% elif forloop.counter == initial_forms_count %}sort-asc{% else %}sort{% endif %}"></i>
|
|
||||||
{% endwith %}
|
|
||||||
{% if inline_admin_form.original %}
|
|
||||||
{{ inline_admin_form.original }}
|
|
||||||
{% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %}<a href="{% url inline_admin_form.model_admin.opts|admin_urlname:'change' inline_admin_form.original.pk|admin_urlquote %}" class="inlinechangelink">{% trans "Change" %}</a>{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
{% if inline_admin_form.show_url %}<a href="{{ inline_admin_form.absolute_url }}">{% trans "View on site" %}</a>{% endif %}
|
|
||||||
</p>{% endif %}
|
|
||||||
{% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
|
|
||||||
{{ inline_admin_form.fk_field.field }}
|
|
||||||
{% spaceless %}
|
|
||||||
{% for fieldset in inline_admin_form %}
|
|
||||||
{% for line in fieldset %}
|
|
||||||
{% for field in line %}
|
|
||||||
{% if field.field.is_hidden %} {{ field.field }} {% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endspaceless %}
|
|
||||||
{% if inline_admin_form.original %}
|
|
||||||
<input type="hidden" name="admin_sorting_url" value="{% url opts|admin_urlname:'do_sorting' inline_admin_form.original.model_type_id %}" />
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
{% for fieldset in inline_admin_form %}
|
|
||||||
{% for line in fieldset %}
|
|
||||||
{% for field in line %}
|
|
||||||
{% if not field.field.is_hidden %}
|
|
||||||
<td{% if field.field.name %} class="field-{{ field.field.name }}"{% endif %}>
|
|
||||||
{% if field.is_readonly %}
|
|
||||||
<p>{{ field.contents }}</p>
|
|
||||||
{% else %}
|
|
||||||
{{ field.field.errors.as_ul }}
|
|
||||||
{{ field.field }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
{% if inline_admin_formset.formset.can_delete %}
|
|
||||||
<td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,17 +1,19 @@
|
||||||
{% load i18n admin_urls static admin_modify django_template_additions %}{% load cycle from future %}
|
{% load i18n admin_urls static admin_modify django_template_additions %}
|
||||||
{% get_django_version as django_version %}
|
<div class="js-inline-admin-formset inline-group" id="{{ inline_admin_formset.formset.prefix }}-group"
|
||||||
<div class="inline-group {% if django_version.major >= 1 and django_version.minor >= 9 %}flat-admin{% endif %}" id="{{ inline_admin_formset.formset.prefix }}-group">
|
data-inline-type="tabular"
|
||||||
|
data-inline-formset="{{ inline_admin_formset.inline_formset_data }}">
|
||||||
<div class="tabular inline-related {% if forloop.last %}last-related{% endif %}">
|
<div class="tabular inline-related {% if forloop.last %}last-related{% endif %}">
|
||||||
{{ inline_admin_formset.formset.management_form }}
|
{{ inline_admin_formset.formset.management_form }}
|
||||||
<fieldset class="module">
|
<fieldset class="module {{ inline_admin_formset.classes }}">
|
||||||
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }} {% if inline_admin_formset.formset.initial_form_count > 1 %} - {% trans "drag and drop to change order" %}{% endif %}</h2>
|
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
|
||||||
{{ inline_admin_formset.formset.non_form_errors }}
|
{{ inline_admin_formset.formset.non_form_errors }}
|
||||||
<table>
|
<table>
|
||||||
<thead><tr>
|
<thead><tr>
|
||||||
|
<th class="original"></th>
|
||||||
{% for field in inline_admin_formset.fields %}
|
{% for field in inline_admin_formset.fields %}
|
||||||
{% if not field.widget.is_hidden %}
|
{% if not field.widget.is_hidden %}
|
||||||
<th{% if forloop.first %} colspan="2"{% endif %}{% if field.required %} class="required"{% endif %}>{{ field.label|capfirst }}
|
<th{% if field.required %} class="required"{% endif %}>{{ field.label|capfirst }}
|
||||||
{% if field.help_text %} <img src="{% if django_version.major >= 1 and django_version.minor >= 9 %}{% static "admin/img/icon-unknown.svg" %}{% else %}{% static "admin/img/icon-unknown.gif" %}{% endif %}" class="help help-tooltip" width="10" height="10" alt="({{ field.help_text|striptags }})" title="{{ field.help_text|striptags }}" />{% endif %}
|
{% if field.help_text %} <img src="{% static "admin/img/icon-unknown.svg" %}" class="help help-tooltip" width="10" height="10" alt="({{ field.help_text|striptags }})" title="{{ field.help_text|striptags }}" />{% endif %}
|
||||||
</th>
|
</th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
@ -34,7 +36,7 @@
|
||||||
{{ inline_admin_form.original }}
|
{{ inline_admin_form.original }}
|
||||||
{% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %}<a href="{% url inline_admin_form.model_admin.opts|admin_urlname:'change' inline_admin_form.original.pk|admin_urlquote %}" class="inlinechangelink">{% trans "Change" %}</a>{% endif %}
|
{% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %}<a href="{% url inline_admin_form.model_admin.opts|admin_urlname:'change' inline_admin_form.original.pk|admin_urlquote %}" class="inlinechangelink">{% trans "Change" %}</a>{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if inline_admin_form.show_url %}<a href="{% url 'admin:view_on_site' inline_admin_form.original_content_type_id inline_admin_form.original.pk %}">{% trans "View on site" %}</a>{% endif %}
|
{% if inline_admin_form.show_url %}<a href="{{ inline_admin_form.absolute_url }}">{% trans "View on site" %}</a>{% endif %}
|
||||||
</p>{% endif %}
|
</p>{% endif %}
|
||||||
{% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
|
{% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
|
||||||
{{ inline_admin_form.fk_field.field }}
|
{{ inline_admin_form.fk_field.field }}
|
||||||
|
|
@ -42,7 +44,7 @@
|
||||||
{% for fieldset in inline_admin_form %}
|
{% for fieldset in inline_admin_form %}
|
||||||
{% for line in fieldset %}
|
{% for line in fieldset %}
|
||||||
{% for field in line %}
|
{% for field in line %}
|
||||||
{% if field.is_hidden %} {{ field.field }} {% endif %}
|
{% if field.field.is_hidden %} {{ field.field }} {% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
@ -54,14 +56,16 @@
|
||||||
{% for fieldset in inline_admin_form %}
|
{% for fieldset in inline_admin_form %}
|
||||||
{% for line in fieldset %}
|
{% for line in fieldset %}
|
||||||
{% for field in line %}
|
{% for field in line %}
|
||||||
|
{% if not field.field.is_hidden %}
|
||||||
<td{% if field.field.name %} class="field-{{ field.field.name }}"{% endif %}>
|
<td{% if field.field.name %} class="field-{{ field.field.name }}"{% endif %}>
|
||||||
{% if field.is_readonly %}
|
{% if field.is_readonly %}
|
||||||
<p>{{ field.contents|linebreaksbr }}</p>
|
<p>{{ field.contents }}</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ field.field.errors.as_ul }}
|
{{ field.field.errors.as_ul }}
|
||||||
{{ field.field }}
|
{{ field.field }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
@ -75,15 +79,3 @@
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
(function($) {
|
|
||||||
$("#{{ inline_admin_formset.formset.prefix }}-group .tabular.inline-related tbody tr").tabularFormset({
|
|
||||||
prefix: "{{ inline_admin_formset.formset.prefix }}",
|
|
||||||
adminStaticPrefix: '{% static "admin/" %}',
|
|
||||||
addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}",
|
|
||||||
deleteText: "{% trans 'Remove' %}"
|
|
||||||
});
|
|
||||||
})(django.jQuery);
|
|
||||||
</script>
|
|
||||||
|
|
|
||||||
|
|
@ -188,3 +188,5 @@ AUTH_PASSWORD_VALIDATORS = [
|
||||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
|
||||||
1
setup.py
1
setup.py
|
|
@ -12,7 +12,6 @@ setup(
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'License :: OSI Approved :: Apache Software License',
|
'License :: OSI Approved :: Apache Software License',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
'Programming Language :: Python :: 2',
|
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Topic :: Utilities'],
|
'Topic :: Utilities'],
|
||||||
description='Drag and drop sorting for models and inline models in Django admin.',
|
description='Drag and drop sorting for models and inline models in Django admin.',
|
||||||
|
|
|
||||||
5
tox.ini
5
tox.ini
|
|
@ -1,11 +1,12 @@
|
||||||
[tox]
|
[tox]
|
||||||
envlist = django{2.2,3.0}-{py36,py37,py38},coverage
|
envlist = django{2.2,3.1,3.2}-{py36,py37,py38,py39},coverage
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
deps =
|
deps =
|
||||||
coverage
|
coverage
|
||||||
django2.2: Django>=2.2
|
django2.2: Django>=2.2
|
||||||
django3.0: Django>=3.0
|
django3.1: Django>=3.1
|
||||||
|
django3.2: Django>=3.2
|
||||||
whitelist_externals = cd
|
whitelist_externals = cd
|
||||||
setenv =
|
setenv =
|
||||||
PYTHONPATH = {toxinidir}/sample_project
|
PYTHONPATH = {toxinidir}/sample_project
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue