Skip to content

Commit e1f8c0a

Browse files
committed
Initial commit
Add everything
0 parents  commit e1f8c0a

File tree

14 files changed

+955
-0
lines changed

14 files changed

+955
-0
lines changed

.gitignore

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
*,cover
2+
*.egg
3+
*.egg-info/
4+
*.log
5+
*.manifest
6+
*.pot
7+
*.py[cod]
8+
*.so
9+
*.spec
10+
.cache
11+
.coverage
12+
.coverage.*
13+
.eggs/
14+
.idea
15+
.installed.cfg
16+
.Python
17+
.tox/
18+
__pycache__/
19+
build/
20+
coverage.xml
21+
develop-eggs/
22+
dist/
23+
docs/_build/
24+
downloads/
25+
eggs/
26+
env/
27+
htmlcov/
28+
lib/
29+
lib64/
30+
nosetests.xml
31+
parts/
32+
pip-delete-this-directory.txt
33+
pip-log.txt
34+
sdist/
35+
target/
36+
var/

LICENSE

Lines changed: 661 additions & 0 deletions
Large diffs are not rendered by default.

MANIFEST.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
include README.rst
2+
include LICENSE
3+
4+
recursive-include django_sorting_field *.css *.html *.js

README.rst

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
Django Sorting Field
2+
====================
3+
4+
* This package implements a Django form field + widget for drag & drog sorting of items
5+
* Sorting any item with a field called ``id`` is supported
6+
* The drag and drop feature has been implemented with `html5sortable <https://lukasoppermann.github.io/html5sortable/index.html>`_.
7+
8+
Example of the widget
9+
---------------------
10+
11+
.. image:: readme-media/example.gif
12+
13+
Usage
14+
-----
15+
16+
The sort order field should be implemented on the model containing the sorted objects.
17+
This allows ordering of different instances of the same item set differently.
18+
19+
Let's say you have image CarouselPlugin, Carousel, and Picture models, and you wish to be able to
20+
sort the same Carousel instance differently on each CarouselPlugin.
21+
22+
You also have a CMSPlugin object for the carousel.
23+
24+
.. code-block:: python
25+
26+
class Carousel(models.Model):
27+
pass
28+
29+
30+
class Picture(models.Model):
31+
carousel = models.ForeignKey(Carousel, related_name="pictures")
32+
image = SomeImageField()
33+
name = models.CharField()
34+
35+
36+
class CarouselPlugin(CMSPlugin):
37+
carousel = models.ForeignKey(Carousel, related_name="x")
38+
39+
40+
class CMSCarouselPlugin(CMSPluginBase):
41+
model = CarouselPlugin
42+
43+
def render(self, context, instance, placeholder):
44+
context.update({
45+
"pictures": self.instance.carousel.pictures.all(),
46+
})
47+
return context
48+
49+
50+
Achieving the wanted behavior can be done in the following steps:
51+
52+
Add a (nullable) TextField to the model containing the order information
53+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54+
55+
.. code-block:: python
56+
57+
class CarouselPlugin(CMSPlugin):
58+
carousel = models.ForeignKey(Carousel, related_name="x")
59+
carousel_order = models.TextField(null=True)
60+
61+
62+
Add the SortingFormField to the CMS Plugin and populate it
63+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
64+
65+
.. code-block:: python
66+
67+
from django_sorting_field.fields import SortingFormField
68+
69+
class CarouselPluginForm(forms.ModelForm):
70+
carousel_order = SortingFormField()
71+
72+
def __init__(self, *args, **kwargs):
73+
super(CarouselPluginForm, self).__init__(*args, **kwargs)
74+
self.fields["carousel_order"].populate(
75+
items=self.instance.carousel.pictures.all(),
76+
)
77+
78+
class CMSCarouselPlugin(CMSPluginBase):
79+
model = CarouselPlugin
80+
form = CarouselPluginForm
81+
82+
def render(self, context, instance, placeholder):
83+
context.update({
84+
"pictures": self.instance.carousel.pictures.all(),
85+
})
86+
return context
87+
88+
Finally, sort the items passed to the context data
89+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
90+
91+
.. code-block:: python
92+
93+
from django_sorting_field.utils import iterate_in_order
94+
95+
class CMSCarouselPlugin(CMSPluginBase):
96+
model = CarouselPlugin
97+
form = CarouselPluginForm
98+
99+
def render(self, context, instance, placeholder):
100+
context.update({
101+
"pictures": iterate_in_order(
102+
self.instance.carousel.pictures.all(),
103+
self.instance.carousel_order
104+
),
105+
})
106+
return context

django_sorting_field/__init__.py

Whitespace-only changes.

django_sorting_field/fields.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from django import forms
2+
import json
3+
4+
from widgets import SortingWidget
5+
from utils import iterate_in_order, clean_order_json
6+
7+
8+
class SortedItem(object):
9+
10+
def __init__(self, identifier, label):
11+
self.id = identifier
12+
self.label = label
13+
14+
15+
class SortingFormField(forms.CharField):
16+
17+
def __init__(self, *args, **kwargs):
18+
kwargs.update({
19+
"widget": SortingWidget(),
20+
"required": False,
21+
})
22+
self.items = ()
23+
super(SortingFormField, self).__init__(*args, **kwargs)
24+
25+
def populate(self, items):
26+
self.items = (SortedItem(item.pk, unicode(item)) for item in items)
27+
28+
def prepare_value(self, value):
29+
value = clean_order_json(value)
30+
return iterate_in_order(self.items, value)
31+
32+
def to_python(self, value):
33+
value = clean_order_json(value)
34+
return json.dumps(value)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.sortable-widget-list {
2+
}
3+
4+
.sortable-widget-list .sortable-widget-placeholder,
5+
.sortable-widget-list .sortable-widget-item {
6+
padding: 10px;
7+
margin-bottom: 5px;
8+
margin-top: 5px;
9+
color: rgb(255, 255, 255);
10+
background-color: #0bf;
11+
border: 1px solid #0bf;
12+
border-radius: 3px;
13+
cursor: pointer;
14+
}
15+
16+
.sortable-widget-list .sortable-widget-placeholder {
17+
border: 1px dashed #0bf;
18+
background-color: inherit;
19+
}

django_sorting_field/static/sorting/js/html.sortable.min.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const CreateSortableWidget = function(sortable_id) {
2+
var sortable_list_id = "#" + sortable_id + "_list";
3+
4+
var refreshInputValue = function() {
5+
result = [];
6+
$(sortable_list_id).children(".sortable-widget-item").each(function(index, element) {
7+
result.push($(element).data("id"));
8+
});
9+
$("input#" + sortable_id).val(JSON.stringify(result));
10+
}
11+
12+
sortable(sortable_list_id, {
13+
placeholder: '<div class="sortable-widget-placeholder">&nbsp;</div>'
14+
})[0].addEventListener("sortstop", function() {
15+
refreshInputValue();
16+
});
17+
18+
refreshInputValue();
19+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<div class="sortable-widget-list" id="{{ id }}_list">
2+
{% for item in items %}
3+
<div class="sortable-widget-item" data-id="{{ item.id }}">{{ item.label }}</div>
4+
{% endfor %}
5+
</div>
6+
<input type="hidden" id="{{ id }}" name="{{ name }}" value="">
7+
<script type="text/javascript">
8+
$(document).ready(function() {
9+
CreateSortableWidget("{{ id }}");
10+
});
11+
</script>

0 commit comments

Comments
 (0)