[Python-modules-commits] [python-django-adminsortable] 01/02: Imported Upstream version 2.0.10
Joost van Baal
joostvb at moszumanska.debian.org
Tue Mar 1 08:39:06 UTC 2016
This is an automated email from the git hooks/post-receive script.
joostvb pushed a commit to branch master
in repository python-django-adminsortable.
commit 1b06a38423274f8747dfb9fa04f2fe694a1497fd
Author: Joost van Baal-Ilić <joostvb at nusku.mdcc.cx>
Date: Tue Mar 1 09:38:30 2016 +0100
Imported Upstream version 2.0.10
---
MANIFEST.in | 4 +
PKG-INFO | 19 +
README.rst | 629 +++++++++++++++++++++
adminsortable/__init__.py | 17 +
adminsortable/admin.py | 371 ++++++++++++
adminsortable/fields.py | 20 +
adminsortable/locale/de/LC_MESSAGES/django.mo | Bin 0 -> 1597 bytes
adminsortable/locale/de/LC_MESSAGES/django.po | 105 ++++
adminsortable/locale/en/LC_MESSAGES/django.po | 46 ++
adminsortable/locale/es/LC_MESSAGES/django.mo | Bin 0 -> 1814 bytes
adminsortable/locale/es/LC_MESSAGES/django.po | 106 ++++
adminsortable/locale/nl/LC_MESSAGES/django.mo | Bin 0 -> 1009 bytes
adminsortable/locale/nl/LC_MESSAGES/django.po | 49 ++
adminsortable/locale/pl/LC_MESSAGES/django.mo | Bin 0 -> 1864 bytes
adminsortable/locale/pl/LC_MESSAGES/django.po | 109 ++++
adminsortable/locale/pt_BR/LC_MESSAGES/django.mo | Bin 0 -> 1511 bytes
adminsortable/locale/pt_BR/LC_MESSAGES/django.po | 98 ++++
adminsortable/locale/ru/LC_MESSAGES/django.mo | Bin 0 -> 2199 bytes
adminsortable/locale/ru/LC_MESSAGES/django.po | 107 ++++
adminsortable/models.py | 141 +++++
.../static/adminsortable/css/admin.sortable.css | 57 ++
.../adminsortable/css/admin.sortable.inline.css | 25 +
.../static/adminsortable/js/admin.sortable.js | 50 ++
.../js/admin.sortable.stacked.inlines.js | 70 +++
.../js/admin.sortable.tabular.inlines.js | 69 +++
.../adminsortable/js/jquery-ui-django-admin.min.js | 8 +
.../static/adminsortable/js/jquery.django-csrf.js | 32 ++
.../templates/adminsortable/change_form.html | 33 ++
.../templates/adminsortable/change_list.html | 72 +++
.../adminsortable/change_list_with_sort_link.html | 15 +
.../adminsortable/edit_inline/stacked-1.5.x.html | 86 +++
.../adminsortable/edit_inline/stacked.html | 35 ++
.../adminsortable/edit_inline/tabular-1.5.x.html | 134 +++++
.../adminsortable/edit_inline/tabular.html | 91 +++
.../templates/adminsortable/shared/fieldset.html | 35 ++
.../templates/adminsortable/shared/list_items.html | 12 +
.../adminsortable/shared/nested_objects.html | 26 +
.../templates/adminsortable/shared/object_rep.html | 6 +
.../templates/adminsortable/shared/objects.html | 7 +
adminsortable/templatetags/__init__.py | 0
adminsortable/templatetags/adminsortable_tags.py | 35 ++
.../templatetags/django_template_additions.py | 86 +++
adminsortable/utils.py | 35 ++
django_admin_sortable.egg-info/PKG-INFO | 19 +
django_admin_sortable.egg-info/SOURCES.txt | 51 ++
.../dependency_links.txt | 1 +
django_admin_sortable.egg-info/not-zip-safe | 1 +
django_admin_sortable.egg-info/pbr.json | 1 +
django_admin_sortable.egg-info/requires.txt | 1 +
django_admin_sortable.egg-info/top_level.txt | 1 +
setup.cfg | 5 +
setup.py | 30 +
52 files changed, 2950 insertions(+)
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..117a1b9
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,4 @@
+recursive-include adminsortable/static *
+recursive-include adminsortable/templates *
+recursive-include adminsortable/locale *
+prune sample_project
\ No newline at end of file
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..84cebe5
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,19 @@
+Metadata-Version: 1.1
+Name: django-admin-sortable
+Version: 2.0.10
+Summary: Drag and drop sorting for models and inline models in Django admin.
+Home-page: https://github.com/iambrandontaylor/django-admin-sortable
+Author: Brandon Taylor
+Author-email: alsoicode at gmail.com
+License: APL
+Description: UNKNOWN
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Web Environment
+Classifier: Framework :: Django
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: Apache Software License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Utilities
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..9aa2fd1
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,629 @@
+Django Admin Sortable
+=====================
+
+|Build Status|
+
+Current version: 2.0.10
+
+This project makes it easy to add drag-and-drop ordering to any model in
+Django admin. Inlines for a sortable model may also be made sortable,
+enabling individual items or groups of items to be sortable.
+
+Sorting model instances with a sortable parent:
+
+.. figure:: http://res.cloudinary.com/alsoicode/image/upload/v1451237555/django-admin-sortable/sortable-models.jpg
+ :alt: sortable-models
+
+ sortable-models
+
+Sorting inlines:
+
+.. figure:: http://res.cloudinary.com/alsoicode/image/upload/v1451237555/django-admin-sortable/sortable-inlines.jpg
+ :alt: sortable-inlines
+
+ sortable-inlines
+
+Supported Django Versions
+-------------------------
+
+If you're using Django 1.4.x, use django-admin-sortable 1.4.9 or below.
+For Django 1.5.x or higher, use the latest version of
+django-admin-sortable.
+
+django-admin-sortable 1.5.2 introduced backward-incompatible changes for
+Django 1.4.x
+
+django-admin-sortable 1.6.6 introduced a backward-incompatible change
+for the ``sorting_filters`` attribute. Please convert your attributes to
+the new tuple-based format.
+
+django-admin-sortable 1.7.1 and higher are compatible with Python 3.
+
+Installation
+------------
+
+1. ``$ pip install django-admin-sortable``
+
+--or--
+
+Download django-admin-sortable from
+`source <https://github.com/iambrandontaylor/django-admin-sortable/archive/master.zip>`__
+
+1. Unzip the directory and cd into the uncompressed project directory
+2.
+
+ - Optional: Enable your virtualenv
+
+3. Run ``$ python setup.py install`` or add ``adminsortable`` to your
+ PYTHONPATH.
+
+Configuration
+-------------
+
+1. Add ``adminsortable`` to your ``INSTALLED_APPS``.
+2. Ensure ``django.core.context_processors.static`` is in your
+ ``TEMPLATE_CONTEXT_PROCESSORS``.
+
+Static Media
+~~~~~~~~~~~~
+
+Preferred: Use the `staticfiles
+app <https://docs.djangoproject.com/en/1.6/ref/contrib/staticfiles/>`__
+
+Alternate: Copy the ``adminsortable`` folder from the ``static`` folder
+to the location you serve static files from.
+
+Testing
+~~~~~~~
+
+Have a look at the included sample\_project to see working examples. The
+login credentials for admin are: admin/admin
+
+When a model is sortable, a tool-area link will be added that says
+"Change Order". Click this link, and you will be taken to the custom
+view where you can drag-and-drop the records into order.
+
+Inlines may be drag-and-dropped into any order directly from the change
+form.
+
+Usage
+-----
+
+Models
+~~~~~~
+
+To add "sortability" to a model, you need to inherit ``SortableMixin``
+and at minimum, define:
+
+- The field which should be used for ``Meta.ordering``, which must
+ resolve to one of the integer fields defined in Django's ORM:
+- ``PositiveIntegerField``
+- ``IntegerField``
+- ``PositiveSmallIntegerField``
+- ``SmallIntegerField``
+- ``BigIntegerField``
+
+- ``Meta.ordering`` **must only contain one value**, otherwise, your
+ objects will not be sorted correctly.
+- It is recommended that you set ``editable=False`` and
+ ``db_index=True`` on the field defined in ``Meta.ordering`` for a
+ seamless Django admin experience and faster lookups on the objects.
+
+Sample Model:
+
+::
+
+ # models.py
+ from adminsortable.models import SortableMixin
+
+ class MySortableClass(SortableMixin):
+ class Meta:
+ verbose_name = 'My Sortable Class'
+ verbose_name_plural = 'My Sortable Classes'
+ ordering = ['the_order']
+
+ title = models.CharField(max_length=50)
+
+ # define the field the model should be ordered by
+ the_order = models.PositiveIntegerField(default=0, editable=False, db_index=True)
+
+ def __unicode__(self):
+ return self.title
+
+Common Use Case
+^^^^^^^^^^^^^^^
+
+A common use case is to have child objects that are sortable relative to
+a parent. If your parent object is also sortable, here's how you would
+set up your models and admin options:
+
+::
+
+ # models.py
+ from adminsortable.fields import SortableForeignKey
+
+ class Category(SortableMixin):
+ class Meta:
+ ordering = ['category_order']
+ verbose_name_plural = 'Categories'
+
+ title = models.CharField(max_length=50)
+
+ # ordering field
+ category_order = models.PositiveIntegerField(default=0, editable=False, db_index=True)
+
+ class Project(SortableMixin):
+ class Meta:
+ ordering = ['project_order']
+
+ category = SortableForeignKey(Category)
+ title = models.CharField(max_length=50)
+
+ # ordering field
+ project_order = models.PositiveIntegerField(default=0, editable=False, db_index=True)
+
+ def __unicode__(self):
+ return self.title
+
+ # admin.py
+ from adminsortable.admin import SortableAdmin
+
+ from your_app.models import Category, Project
+
+ admin.site.register(Category, SortableAdmin)
+ admin.site.register(Project, SortableAdmin)
+
+Sometimes you might have a parent model that is not sortable, but has
+child models that are. In that case define your models and admin options
+as such:
+
+::
+
+ from adminsortable.fields import SortableForeignKey
+
+ # models.py
+ class Category(models.Model):
+ class Meta:
+ verbose_name_plural = 'Categories'
+
+ title = models.CharField(max_length=50)
+ ...
+
+ class Project(SortableMixin):
+ class Meta:
+ ordering = ['project_order']
+
+ category = SortableForeignKey(Category)
+ title = models.CharField(max_length=50)
+
+ # ordering field
+ project_order = models.PositiveIntegerField(default=0, editable=False, db_index=True)
+
+ def __unicode__(self):
+ return self.title
+
+ # admin
+ from adminsortable.admin import NonSortableParentAdmin, SortableStackedInline
+
+ from your_app.models import Category, Project
+
+ class ProjectInline(SortableStackedInline):
+ model = Project
+ extra = 1
+
+ class CategoryAdmin(NonSortableParentAdmin):
+ inlines = [ProjectInline]
+
+ admin.site.register(Category, CategoryAdmin)
+
+The ``NonSortableParentAdmin`` class is necessary to wire up the
+additional URL patterns and JavaScript that Django Admin Sortable needs
+to make your models sortable. The child model does not have to be an
+inline model, it can be wired directly to Django admin and the objects
+will be grouped by the non-sortable foreign key when sorting.
+
+Backwards Compatibility
+~~~~~~~~~~~~~~~~~~~~~~~
+
+If you previously used Django Admin Sortable, **DON'T PANIC** -
+everything will still work exactly as before ***without any changes to
+your code***. Going forward, it is recommended that you use the new
+``SortableMixin`` on your models, as pre-2.0 compatibility might not be
+a permanent thing.
+
+Please note however that the ``Sortable`` class still contains the
+hard-coded ``order`` field, and meta inheritance requirements:
+
+::
+
+ # legacy model definition
+
+ from adminsortable.models import Sortable
+
+ class Project(Sortable):
+ class Meta(Sortable.Meta):
+ pass
+ title = models.CharField(max_length=50)
+
+ def __unicode__(self):
+ return self.title
+
+Model Instance Methods
+^^^^^^^^^^^^^^^^^^^^^^
+
+Each instance of a sortable model has two convenience methods to get the
+next or previous instance:
+
+::
+
+ .get_next()
+ .get_previous()
+
+By default, these methods will respect their order in relation to a
+``SortableForeignKey`` field, if present. Meaning, that given the
+following data:
+
+::
+
+ | Parent Model 1 | |
+ | | Child Model 1 |
+ | | Child Model 2 |
+ | Parent Model 2 | |
+ | | Child Model 3 |
+ | | Child Model 4 |
+ | | Child Model 5 |
+
+"Child Model 2" ``get_next()`` would return ``None`` "Child Model 3"
+``get_previous`` would return ``None``
+
+If you wish to override this behavior, pass in:
+``filter_on_sortable_fk=False``:
+
+::
+
+ your_instance.get_next(filter_on_sortable_fk=False)
+
+You may also pass in additional ORM "extra\_filters" as a dictionary,
+should you need to:
+
+::
+
+ your_instance.get_next(extra_filters={'title__icontains': 'blue'})
+
+Adding Sorting to an existing model
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Django 1.6.x or below
+^^^^^^^^^^^^^^^^^^^^^
+
+If you're adding Sorting to an existing model, it is recommended that
+you use `django-south <http://south.areacode.com/>`__ to create a schema
+migration to add the "order" field to your model. You will also need to
+create a data migration in order to add the appropriate values for the
+"order" column.
+
+Example assuming a model named "Category":
+
+::
+
+ def forwards(self, orm):
+ for index, category in enumerate(orm.Category.objects.all()):
+ category.order = index + 1
+ category.save()
+
+See: `this
+link <http://south.readthedocs.org/en/latest/tutorial/part3.html>`__ for
+more information on South Data Migrations.
+
+Django 1.7.x or higher
+^^^^^^^^^^^^^^^^^^^^^^
+
+Since schema migrations are built into Django 1.7, you don't have to use
+south, but the process of adding and running migrations is nearly
+identical. Take a look at the
+`Migrations <https://docs.djangoproject.com/en/1.7/topics/migrations/>`__
+documentation to get started.
+
+Django Admin Integration
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+To enable sorting in the admin, you need to inherit from
+``SortableAdmin``:
+
+::
+
+ from django.contrib import admin
+ from myapp.models import MySortableClass
+ from adminsortable.admin import SortableAdmin
+
+ class MySortableAdminClass(SortableAdmin):
+ """Any admin options you need go here"""
+
+ admin.site.register(MySortableClass, MySortableAdminClass)
+
+To enable sorting on TabularInline models, you need to inherit from
+SortableTabularInline:
+
+::
+
+ from adminsortable.admin import SortableTabularInline
+
+ class MySortableTabularInline(SortableTabularInline):
+ """Your inline options go here"""
+
+To enable sorting on StackedInline models, you need to inherit from
+SortableStackedInline:
+
+::
+
+ from adminsortable.admin import SortableStackedInline
+
+ class MySortableStackedInline(SortableStackedInline):
+ """Your inline options go here"""
+
+There are also generic equivalents that you can inherit from:
+
+::
+
+ from adminsortable.admin import (SortableGenericTabularInline,
+ SortableGenericStackedInline)
+ """Your generic inline options go here"""
+
+If your parent model is *not* sortable, but has child inlines that are,
+your parent model needs to inherit from ``NonSortableParentAdmin``:
+
+::
+
+ from adminsortable.admin import (NonSortableParentAdmin,
+ SortableTabularInline)
+
+ class ChildTabularInline(SortableTabularInline):
+ model = YourModel
+
+ class ParentAdmin(NonSortableParentAdmin):
+ inlines = [ChildTabularInline]
+
+Overriding ``queryset()``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+django-admin-sortable supports custom queryset overrides on admin models
+and inline models in Django admin!
+
+If you're providing an override of a SortableAdmin or Sortable inline
+model, you don't need to do anything extra. django-admin-sortable will
+automatically honor your queryset.
+
+Have a look at the WidgetAdmin class in the sample project for an
+example of an admin class with a custom ``queryset()`` override.
+
+Overriding ``queryset()`` for an inline model
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This is a special case, which requires a few lines of extra code to
+properly determine the sortability of your model. Example:
+
+::
+
+ # add this import to your admin.py
+ from adminsortable.utils import get_is_sortable
+
+
+ class ComponentInline(SortableStackedInline):
+ model = Component
+
+ def queryset(self, request):
+ qs = super(ComponentInline, self).queryset(request).filter(
+ title__icontains='foo')
+
+ # You'll need to add these lines to determine if your model
+ # is sortable once we hit the change_form() for the parent model.
+
+ if get_is_sortable(qs):
+ self.model.is_sortable = True
+ else:
+ self.model.is_sortable = False
+ return qs
+
+If you override the queryset of an inline, the number of objects present
+may change, and adminsortable won't be able to automatically determine
+if the inline model is sortable from here, which is why we have to set
+the ``is_sortable`` property of the model in this method.
+
+Sorting subsets of objects
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+It is also possible to sort a subset of objects in your model by adding
+a ``sorting_filters`` tuple. This works exactly the same as
+``.filter()`` on a QuerySet, and is applied *after* ``get_queryset()``
+on the admin class, allowing you to override the queryset as you would
+normally in admin but apply additional filters for sorting. The text
+"Change Order of" will appear before each filter in the Change List
+template, and the filter groups are displayed from left to right in the
+order listed. If no ``sorting_filters`` are specified, the text "Change
+Order" will be displayed for the link.
+
+Self-Referential SortableForeignKey
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can specify a self-referential SortableForeignKey field, however the
+admin interface will currently show a model that is a grandchild at the
+same level as a child. I'm working to resolve this issue.
+
+Important!
+''''''''''
+
+django-admin-sortable 1.6.6 introduced a backwards-incompatible change
+for ``sorting_filters``. Previously this attribute was defined as a
+dictionary, so you'll need to change your values over to the new
+tuple-based format.
+
+An example of sorting subsets would be a "Board of Directors". In this
+use case, you have a list of "People" objects. Some of these people are
+on the Board of Directors and some not, and you need to sort them
+independently.
+
+::
+
+ class Person(Sortable):
+ class Meta(Sortable.Meta):
+ verbose_name_plural = 'People'
+
+ first_name = models.CharField(max_length=50)
+ last_name = models.CharField(max_length=50)
+ is_board_member = models.BooleanField('Board Member', default=False)
+
+ sorting_filters = (
+ ('Board Members', {'is_board_member': True}),
+ ('Non-Board Members', {'is_board_member': False}),
+ )
+
+ def __unicode__(self):
+ return '{} {}'.format(self.first_name, self.last_name)
+
+Extending custom templates
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+By default, adminsortable's change form and change list views inherit
+from Django admin's standard templates. Sometimes you need to have a
+custom change form or change list, but also need adminsortable's CSS and
+JavaScript for inline models that are sortable for example.
+
+SortableAdmin has two attributes you can override for this use case:
+
+::
+
+ change_form_template_extends
+ change_list_template_extends
+
+These attributes have default values of:
+
+::
+
+ change_form_template_extends = 'admin/change_form.html'
+ change_list_template_extends = 'admin/change_list.html'
+
+If you need to extend the inline change form templates, you'll need to
+select the right one, depending on your version of Django. For Django
+1.5.x or below, you'll need to extend one of the following:
+
+::
+
+ templates/adminsortable/edit_inline/stacked-1.5.x.html
+ templates/adminsortable/edit_inline/tabular-inline-1.5.x.html
+
+For Django 1.6.x, extend:
+
+::
+
+ templates/adminsortable/edit_inline/stacked.html
+ templates/adminsortable/edit_inline/tabular.html
+
+A Special Note About Stacked Inlines...
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The height of a stacked inline model can dynamically increase, which can
+make them difficult to sort. If you anticipate the height of a stacked
+inline is going to be very tall, I would suggest using
+SortableTabularInline instead.
+
+Django-CMS integration
+~~~~~~~~~~~~~~~~~~~~~~
+
+Django-CMS plugins use their own change form, and thus won't
+automatically include the necessary JavaScript for django-admin-sortable
+to work. Fortunately, this is easy to resolve, as the ``CMSPlugin``
+class allows a change form template to be specified:
+
+::
+
+ # example plugin
+ from cms.plugin_base import CMSPluginBase
+
+ class CMSCarouselPlugin(CMSPluginBase):
+ admin_preview = False
+ change_form_template = 'cms/sortable-stacked-inline-change-form.html'
+ inlines = [SlideInline]
+ model = Carousel
+ name = _('Carousel')
+ render_template = 'carousels/carousel.html'
+
+ def render(self, context, instance, placeholder):
+ context.update({
+ 'carousel': instance,
+ 'placeholder': placeholder
+ })
+ return context
+
+ plugin_pool.register_plugin(CMSCarouselPlugin)
+
+The contents of ``sortable-stacked-inline-change-form.html`` at a
+minimum need to extend the extrahead block with:
+
+::
+
+ {% extends "admin/cms/page/plugin_change_form.html" %}
+ {% load static from staticfiles %}
+
+ {% block extrahead %}
+ {{ block.super }}
+ <script type="text/javascript" src="{% static 'adminsortable/js/jquery-ui-django-admin.min.js' %}"></script>
+ <script type="text/javascript" src="{% static 'adminsortable/js/jquery.django-csrf.js' %}"></script>
+ <script type="text/javascript" src="{% static 'adminsortable/js/admin.sortable.stacked.inlines.js' %}"></script>
+
+ <link rel="stylesheet" type="text/css" href="{% static 'adminsortable/css/admin.sortable.inline.css' %}" />
+ {% endblock extrahead %}
+
+Sorting within Django-CMS is really only feasible for inline models of a
+plugin as Django-CMS already includes sorting for plugin instances. For
+tabular inlines, just substitute:
+
+::
+
+ <script src="{% static 'adminsortable/js/admin.sortable.stacked.inlines.js' %}"></script>
+
+with:
+
+::
+
+ <script src="{% static 'adminsortable/js/admin.sortable.tabular.inlines.js' %}"></script>
+
+Rationale
+~~~~~~~~~
+
+Other projects have added drag-and-drop ordering to the ChangeList view,
+however this introduces a couple of problems...
+
+- The ChangeList view supports pagination, which makes drag-and-drop
+ ordering across pages impossible.
+- The ChangeList view by default, does not order records based on a
+ foreign key, nor distinguish between rows that are associated with a
+ foreign key. This makes ordering the records grouped by a foreign key
+ impossible.
+- The ChangeList supports in-line editing, and adding drag-and-drop
+ ordering on top of that just seemed a little much in my opinion.
+
+Status
+~~~~~~
+
+django-admin-sortable is currently used in production.
+
+What's new in 2.0.10?
+~~~~~~~~~~~~~~~~~~~~~
+
+- Bugfix for accessing custom ``order`` property of model. Thanks
+ [@theithec](https://github.com/theithec) for reporting the issue.
+
+Future
+~~~~~~
+
+- Better template support for foreign keys that are self referential.
+ If someone would like to take on rendering recursive sortables, that
+ would be super.
+
+License
+~~~~~~~
+
+django-admin-sortable is released under the Apache Public License v2.
+
+.. |Build Status| image:: https://travis-ci.org/iambrandontaylor/django-admin-sortable.svg?branch=master
+ :target: https://travis-ci.org/iambrandontaylor/django-admin-sortable
diff --git a/adminsortable/__init__.py b/adminsortable/__init__.py
new file mode 100644
index 0000000..25cbabc
--- /dev/null
+++ b/adminsortable/__init__.py
@@ -0,0 +1,17 @@
+VERSION = (2, 0, 10)
+DEV_N = None
+
+
+def get_version():
+ version = '{0}.{1}'.format(VERSION[0], VERSION[1])
+ if VERSION[2]:
+ version = '{0}.{1}'.format(version, VERSION[2])
+ try:
+ if VERSION[3]:
+ version = '{0}.{1}'.format(version, VERSION[3])
+ except IndexError:
+ pass
+ return version
+
+
+__version__ = get_version()
diff --git a/adminsortable/admin.py b/adminsortable/admin.py
new file mode 100755
index 0000000..123e9a7
--- /dev/null
+++ b/adminsortable/admin.py
@@ -0,0 +1,371 @@
+import json
+
+from django import VERSION
+
+from django.conf import settings
+
+if VERSION > (1, 7):
+ from django.conf.urls import url
+elif VERSION > (1, 5):
+ from django.conf.urls import patterns, url
+else:
+ from django.conf.urls.defaults import patterns, url
+
+from django.contrib.admin import ModelAdmin, TabularInline, StackedInline
+from django.contrib.admin.options import InlineModelAdmin
+
+if VERSION >= (1, 8):
+ from django.contrib.auth import get_permission_codename
+ from django.contrib.contenttypes.admin import (GenericStackedInline,
+ GenericTabularInline)
+else:
+ from django.contrib.contenttypes.generic import (GenericStackedInline,
+ GenericTabularInline)
+
+from django.contrib.contenttypes.models import ContentType
+from django.http import HttpResponse
+from django.shortcuts import render
+from django.template.defaultfilters import capfirst
+
+from adminsortable.fields import SortableForeignKey
+from adminsortable.models import SortableMixin
+from adminsortable.utils import get_is_sortable
+
+STATIC_URL = settings.STATIC_URL
+
+
+class SortableAdminBase(object):
+ sortable_change_list_with_sort_link_template = \
+ 'adminsortable/change_list_with_sort_link.html'
+ sortable_change_form_template = 'adminsortable/change_form.html'
+ sortable_change_list_template = 'adminsortable/change_list.html'
+
+ change_form_template_extends = 'admin/change_form.html'
+ change_list_template_extends = 'admin/change_list.html'
+
+ def changelist_view(self, request, extra_context=None):
+ """
+ If the model that inherits Sortable has more than one object,
+ its sort order can be changed. This view adds a link to the
+ object_tools block to take people to the view to change the sorting.
+ """
+
+ try:
+ qs_method = getattr(self, 'get_queryset', self.queryset)
+ except AttributeError:
+ qs_method = self.get_queryset
+
+ if get_is_sortable(qs_method(request)):
+ self.change_list_template = \
+ self.sortable_change_list_with_sort_link_template
+ self.is_sortable = True
+
+ if extra_context is None:
+ extra_context = {}
+
+ extra_context.update({
+ 'change_list_template_extends': self.change_list_template_extends,
+ 'sorting_filters': [sort_filter[0] for sort_filter
+ in getattr(self.model, 'sorting_filters', [])]
+ })
+ return super(SortableAdminBase, self).changelist_view(request,
+ extra_context=extra_context)
+
+
+class SortableAdmin(SortableAdminBase, ModelAdmin):
+ """
+ Admin class to add template overrides and context objects to enable
+ drag-and-drop ordering.
+ """
+
+ class Meta:
+ abstract = True
+
+ def get_urls(self):
+ urls = super(SortableAdmin, self).get_urls()
+
+ # this ajax view changes the order
+ admin_do_sorting_url = url(r'^sorting/do-sorting/(?P<model_type_id>\d+)/$',
+ self.admin_site.admin_view(self.do_sorting_view),
+ name='admin_do_sorting')
+
+ # this view displays the sortable objects
+ admin_sort_url = url(r'^sort/$',
+ self.admin_site.admin_view(self.sort_view),
+ name='admin_sort')
+
+ if VERSION > (1, 7):
+ admin_urls = [
+ admin_do_sorting_url,
+ admin_sort_url
+ ]
+ else:
+ admin_urls = patterns('',
+ admin_do_sorting_url,
+ admin_sort_url,)
+
+ return admin_urls + urls
+
+ def sort_view(self, request):
+ """
+ Custom admin view that displays the objects as a list whose sort
+ order can be changed via drag-and-drop.
+ """
+
+ opts = self.model._meta
+ if VERSION >= (1, 8):
+ codename = get_permission_codename('change', opts)
+ has_perm = request.user.has_perm('{0}.{1}'.format(opts.app_label,
+ codename))
+ else:
+ has_perm = request.user.has_perm('{0}.{1}'.format(opts.app_label,
+ opts.get_change_permission()))
+
+ jquery_lib_path = 'admin/js/jquery.js' if VERSION < (1, 9) \
+ else 'admin/js/vendor/jquery/jquery.js'
+
+ # get sort group index from querystring if present
+ sort_filter_index = request.GET.get('sort_filter')
+
+ filters = {}
+ if sort_filter_index:
+ try:
+ filters = self.model.sorting_filters[int(sort_filter_index)][1]
+ except (IndexError, ValueError):
+ pass
+
+ # Apply any sort filters to create a subset of sortable objects
+ try:
+ qs_method = getattr(self, 'get_queryset', self.queryset)
+ except AttributeError:
+ qs_method = self.get_queryset
+ objects = qs_method(request).filter(**filters)
+
+ # Determine if we need to regroup objects relative to a
+ # foreign key specified on the model class that is extending Sortable.
+ # Legacy support for 'sortable_by' defined as a model property
+ sortable_by_property = getattr(self.model, 'sortable_by', None)
+
+ # see if our model is sortable by a SortableForeignKey field
+ # and that the number of objects available is >= 2
+ sortable_by_fk = None
+ sortable_by_field_name = None
+ sortable_by_class_is_sortable = False
+
+ for field in self.model._meta.fields:
+ if isinstance(field, SortableForeignKey):
+ sortable_by_fk = field.rel.to
+ sortable_by_field_name = field.name.lower()
+ sortable_by_class_is_sortable = sortable_by_fk.objects.count() >= 2
+
+ 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_expression = sortable_by_class.__name__.lower()
+
+ sortable_by_class_display_name = sortable_by_class._meta \
+ .verbose_name_plural
+
+ elif sortable_by_fk:
+ # get sortable by properties from the SortableForeignKey
+ # field - supported in 1.3+
+ sortable_by_class_display_name = sortable_by_fk._meta.verbose_name_plural
+ sortable_by_class = sortable_by_fk
+ sortable_by_expression = sortable_by_field_name
+
+ else:
+ # model is not sortable by another model
+ sortable_by_class = sortable_by_expression = \
+ sortable_by_class_display_name = \
+ sortable_by_class_is_sortable = None
+
+ if sortable_by_property or sortable_by_fk:
+ # Order the objects by the property they are sortable by,
+ # then by the order, otherwise the regroup
+ # template tag will not show the objects correctly
+
+ try:
+ order_field_name = opts.model._meta.ordering[0]
+ except (AttributeError, IndexError):
+ # for Django 1.5.x
+ order_field_name = opts.ordering[0]
+ finally:
+ order_field_name = 'order'
+
+ objects = objects.order_by(sortable_by_expression, order_field_name)
+
+ try:
+ verbose_name_plural = opts.verbose_name_plural.__unicode__()
+ except AttributeError:
+ verbose_name_plural = opts.verbose_name_plural
+
+ context = {
+ 'title': u'Drag and drop {0} to change display order'.format(
+ capfirst(verbose_name_plural)),
+ 'opts': opts,
+ 'app_label': opts.app_label,
+ 'has_perm': has_perm,
+ 'objects': objects,
+ 'group_expression': sortable_by_expression,
+ 'sortable_by_class': sortable_by_class,
+ 'sortable_by_class_is_sortable': sortable_by_class_is_sortable,
+ 'sortable_by_class_display_name': sortable_by_class_display_name,
+ 'jquery_lib_path': jquery_lib_path
+ }
+ return render(request, self.sortable_change_list_template, context)
+
+ def add_view(self, request, form_url='', extra_context=None):
+ if extra_context is None:
+ extra_context = {}
+
+ extra_context.update({
+ 'change_form_template_extends': self.change_form_template_extends
+ })
+ return super(SortableAdmin, self).add_view(request, form_url,
+ extra_context=extra_context)
+
+ def change_view(self, request, object_id, form_url='', extra_context=None):
+ self.has_sortable_tabular_inlines = False
+ self.has_sortable_stacked_inlines = False
+
+ if extra_context is None:
+ extra_context = {}
+
+ extra_context.update({
+ 'change_form_template_extends': self.change_form_template_extends
... 2312 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-django-adminsortable.git
More information about the Python-modules-commits
mailing list