Weapons. Migrations.
This commit is contained in:
@@ -0,0 +1,269 @@
|
||||
django-multiselectfield
|
||||
=======================
|
||||
|
||||
.. image:: https://travis-ci.org/goinnn/django-multiselectfield.png?branch=master
|
||||
:target: https://travis-ci.org/goinnn/django-multiselectfield
|
||||
|
||||
.. image:: https://coveralls.io/repos/goinnn/django-multiselectfield/badge.png?branch=master
|
||||
:target: https://coveralls.io/r/goinnn/django-multiselectfield
|
||||
|
||||
.. image:: https://badge.fury.io/py/django-multiselectfield.png
|
||||
:target: https://badge.fury.io/py/django-multiselectfield
|
||||
|
||||
A new model field and form field. With this you can get a multiple select from a choices. Stores to the database as a CharField of comma-separated values.
|
||||
|
||||
This egg is inspired by this `snippet <http://djangosnippets.org/snippets/1200/>`_.
|
||||
|
||||
Supported Python versions: 2.7, 3.4+
|
||||
|
||||
Supported Django versions: 1.4-2.0+
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
|
||||
Install with pip
|
||||
----------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install django-multiselectfield
|
||||
|
||||
Configure your models.py
|
||||
------------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from multiselectfield import MultiSelectField
|
||||
|
||||
# ...
|
||||
|
||||
MY_CHOICES = (('item_key1', 'Item title 1.1'),
|
||||
('item_key2', 'Item title 1.2'),
|
||||
('item_key3', 'Item title 1.3'),
|
||||
('item_key4', 'Item title 1.4'),
|
||||
('item_key5', 'Item title 1.5'))
|
||||
|
||||
MY_CHOICES2 = ((1, 'Item title 2.1'),
|
||||
(2, 'Item title 2.2'),
|
||||
(3, 'Item title 2.3'),
|
||||
(4, 'Item title 2.4'),
|
||||
(5, 'Item title 2.5'))
|
||||
|
||||
class MyModel(models.Model):
|
||||
|
||||
# .....
|
||||
|
||||
my_field = MultiSelectField(choices=MY_CHOICES)
|
||||
my_field2 = MultiSelectField(choices=MY_CHOICES2,
|
||||
max_choices=3,
|
||||
max_length=3)
|
||||
|
||||
|
||||
In your settings.py
|
||||
-------------------
|
||||
|
||||
Only you need it, if you want the translation of django-multiselectfield
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.admin',
|
||||
|
||||
#.....................#
|
||||
|
||||
'multiselectfield',
|
||||
)
|
||||
|
||||
|
||||
Customizing templates
|
||||
---------------------
|
||||
|
||||
It is possible to customize the HTML of this widget in your form template. To do so, you will need to loop through ``form.{field}.field.choices``. Here is an example that displays the field label underneath/after the checkbox for a ``MultiSelectField`` called ``providers``:
|
||||
|
||||
.. code-block:: HTML+Django
|
||||
|
||||
{% for value, text in form.providers.field.choices %}
|
||||
<div class="ui slider checkbox">
|
||||
<input id="id_providers_{{ forloop.counter0 }}" name="{{ form.providers.name }}" type="checkbox" value="{{ value }}"{% if value in checked_providers %} checked="checked"{% endif %}>
|
||||
<label>{{ text }}</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
|
||||
Django REST Framework
|
||||
---------------------
|
||||
|
||||
Django REST Framework comes with a ``MultipleChoiceField`` that works perfectly with this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from rest_framework import fields, serializers
|
||||
|
||||
from myapp.models import MY_CHOICES, MY_CHOICES2
|
||||
|
||||
class MyModelSerializer(serializers.HyperlinkedModelSerializer):
|
||||
# ...
|
||||
my_field = fields.MultipleChoiceField(choices=MY_CHOICES)
|
||||
my_field2 = fields.MultipleChoiceField(choices=MY_CHOICES2)
|
||||
# ...
|
||||
|
||||
|
||||
Known Bugs and Limitations
|
||||
==========================
|
||||
|
||||
All tests pass on Django 1.4, 1.5, and 1.8+, so if you can, use a modern version of Django. However, if you must use Django 1.6 or 1.7 there are two known issues you will need to be aware of:
|
||||
|
||||
1. `Named groups <https://github.com/goinnn/django-multiselectfield/pull/30#issue-52149983>`_ do not render properly in Django 1.6. The workaround is to manually render the field in your form or use a custom widget. If your workaround is suitably generic, please submit a pull request with it.
|
||||
|
||||
2. Only in Django 1.6 and 1.7, due to `Django bug #9619 <https://code.djangoproject.com/ticket/9619>`_, passing a MultiSelectField to ``values()`` or ``values_list()`` will return the database representation of the field (a string of comma-separated values). The workaround is to manually call ``.split(',')`` on the result.
|
||||
|
||||
The Django bug was introduced in Django 1.6 and is fixed in Django 1.8 and onward, so ``values()`` and ``values_list()`` return a vanilla Python list of values for Django <= 1.5 and Django >= 1.8.
|
||||
|
||||
See `issue #40 <https://github.com/goinnn/django-multiselectfield/issues/40>`_ for discussion about this bug.
|
||||
|
||||
|
||||
Development
|
||||
===========
|
||||
|
||||
You can get the last bleeding edge version of django-multiselectfield by doing a clone
|
||||
of its git repository:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/goinnn/django-multiselectfield
|
||||
|
||||
|
||||
Example project
|
||||
===============
|
||||
|
||||
There is a fully configured example project in the `example directory <https://github.com/goinnn/django-multiselectfield/tree/master/example/>`_. You can run it as usual:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python manage.py migrate # or python manage.py syncdb --noinput
|
||||
python manage.py loaddata app_data
|
||||
python manage.py runserver
|
||||
|
||||
|
||||
0.1.12 (2020-02-20)
|
||||
-------------------
|
||||
|
||||
* Optimize multiselectfield to_python method
|
||||
* Thanks to:
|
||||
* `daimon99 <https://github.com/daimon99>`_
|
||||
|
||||
0.1.11 (2019-12-19)
|
||||
-------------------
|
||||
|
||||
* Added support for Django 3
|
||||
* Added support for Python 3.8
|
||||
* Thanks to:
|
||||
* `thijsBoehme <https://github.com/thijsBoehme>`_
|
||||
|
||||
0.1.9 (2019-10-02)
|
||||
------------------
|
||||
|
||||
* Added support for Django 2
|
||||
* Added support for Python 3.6
|
||||
* Drop support for Python (2.6, 3.3)
|
||||
* Thanks to:
|
||||
* `hirokinko <https://github.com/hirokinko>`_
|
||||
|
||||
0.1.6 (2017-05-10)
|
||||
------------------
|
||||
|
||||
* Added support for Django 1.11
|
||||
* Added support for Python 3.6
|
||||
* Improved rendering in Django admin
|
||||
* Improved documentation
|
||||
* Thanks to:
|
||||
* `atten <https://github.com/atten>`_
|
||||
* `ixc <https://github.comixc>`_
|
||||
* `LeilaniAnn <https://github.comLeilaniAnn>`_
|
||||
|
||||
0.1.5 (2017-01-02)
|
||||
------------------
|
||||
|
||||
* Added support for Django 1.8-1.10
|
||||
* Added support for named groups in choices
|
||||
* Added support for min_choices argument
|
||||
* Various fixes
|
||||
* More tests
|
||||
* Thanks to:
|
||||
* `danilogbotelho <https://github.comdanilogbotelho>`_
|
||||
* `dmitry-krasilnikov <https://github.comdmitry-krasilnikov>`_
|
||||
* `Kamil Dębowski <https://github.comkdebowski>`_
|
||||
|
||||
0.1.4 (2016-02-23)
|
||||
------------------
|
||||
|
||||
* Fixed warning about SubfieldBase
|
||||
* Added support for Django 1.8+
|
||||
* Added support for named groups
|
||||
* We now play nice with django-dynamic-fixture
|
||||
* More tests
|
||||
|
||||
0.1.3 (2014-10-13)
|
||||
------------------
|
||||
|
||||
* Support to Django 1.7 (I'm sorry to the delay)
|
||||
* Adding get_FIELD_list function
|
||||
* Fix an error when a MultiSelectField was reandonly at the admin site
|
||||
* Thanks to:
|
||||
* `Hernil <https://github.com/hernil>`_
|
||||
* `Vasyl Stanislavchuk <https://github.com/vasyabigi>`_
|
||||
* `Litchfield <https://github.com/litchfield/>`_
|
||||
* `Chris-erickson <https://github.com/chris-erickson>`_
|
||||
|
||||
0.1.2 (2014-04-04)
|
||||
------------------
|
||||
|
||||
* Include the spanish translations to the pypi egg
|
||||
* Improvements in the readme file
|
||||
* Windows OS compatibility
|
||||
* Thanks to:
|
||||
* `StillNewb <https://github.com/StillNewb>`_
|
||||
* `Diego Yungh <https://github.com/DiegoYungh>`_
|
||||
|
||||
0.1.1 (2013-12-04)
|
||||
------------------
|
||||
* Move the multiselectfield app to parent folder
|
||||
* Details
|
||||
|
||||
0.1.0 (2013-11-30)
|
||||
------------------
|
||||
|
||||
* Test/example project
|
||||
* Now works if the first composant of the list of tuple is an integer
|
||||
* Now max_length is not required, the Multiselect field calculate it automatically.
|
||||
* The max_choices attr can be a attr in the model field
|
||||
* Refactor the code
|
||||
* Spanish translations
|
||||
* Support to python2.6
|
||||
* Thanks to:
|
||||
* `Daniele Procida <https://github.com/evildmp>`_
|
||||
|
||||
0.0.3 (2013-09-11)
|
||||
------------------
|
||||
|
||||
* Python 3 compatible
|
||||
* Fix an error, the snippet had another error when the choices were translatables
|
||||
* Improvements in the README file
|
||||
|
||||
|
||||
0.0.2 (2012-09-28)
|
||||
------------------
|
||||
|
||||
* Fix an error, the snippet had an error.
|
||||
|
||||
0.0.1 (2012-09-27)
|
||||
------------------
|
||||
|
||||
* Initial version from the next `snippet <http://djangosnippets.org/snippets/1200/>`_
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
pip
|
||||
@@ -0,0 +1,294 @@
|
||||
Metadata-Version: 2.0
|
||||
Name: django-multiselectfield
|
||||
Version: 0.1.12
|
||||
Summary: Django multiple select field
|
||||
Home-page: https://github.com/goinnn/django-multiselectfield
|
||||
Author: Pablo Martin
|
||||
Author-email: goinnn@gmail.com
|
||||
License: LGPL 3
|
||||
Keywords: django,multiple,select,field,choices
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 4 - Beta
|
||||
Classifier: Framework :: Django
|
||||
Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Requires-Dist: django (>=1.4)
|
||||
|
||||
django-multiselectfield
|
||||
=======================
|
||||
|
||||
.. image:: https://travis-ci.org/goinnn/django-multiselectfield.png?branch=master
|
||||
:target: https://travis-ci.org/goinnn/django-multiselectfield
|
||||
|
||||
.. image:: https://coveralls.io/repos/goinnn/django-multiselectfield/badge.png?branch=master
|
||||
:target: https://coveralls.io/r/goinnn/django-multiselectfield
|
||||
|
||||
.. image:: https://badge.fury.io/py/django-multiselectfield.png
|
||||
:target: https://badge.fury.io/py/django-multiselectfield
|
||||
|
||||
A new model field and form field. With this you can get a multiple select from a choices. Stores to the database as a CharField of comma-separated values.
|
||||
|
||||
This egg is inspired by this `snippet <http://djangosnippets.org/snippets/1200/>`_.
|
||||
|
||||
Supported Python versions: 2.7, 3.4+
|
||||
|
||||
Supported Django versions: 1.4-2.0+
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
|
||||
Install with pip
|
||||
----------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install django-multiselectfield
|
||||
|
||||
Configure your models.py
|
||||
------------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from multiselectfield import MultiSelectField
|
||||
|
||||
# ...
|
||||
|
||||
MY_CHOICES = (('item_key1', 'Item title 1.1'),
|
||||
('item_key2', 'Item title 1.2'),
|
||||
('item_key3', 'Item title 1.3'),
|
||||
('item_key4', 'Item title 1.4'),
|
||||
('item_key5', 'Item title 1.5'))
|
||||
|
||||
MY_CHOICES2 = ((1, 'Item title 2.1'),
|
||||
(2, 'Item title 2.2'),
|
||||
(3, 'Item title 2.3'),
|
||||
(4, 'Item title 2.4'),
|
||||
(5, 'Item title 2.5'))
|
||||
|
||||
class MyModel(models.Model):
|
||||
|
||||
# .....
|
||||
|
||||
my_field = MultiSelectField(choices=MY_CHOICES)
|
||||
my_field2 = MultiSelectField(choices=MY_CHOICES2,
|
||||
max_choices=3,
|
||||
max_length=3)
|
||||
|
||||
|
||||
In your settings.py
|
||||
-------------------
|
||||
|
||||
Only you need it, if you want the translation of django-multiselectfield
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.admin',
|
||||
|
||||
#.....................#
|
||||
|
||||
'multiselectfield',
|
||||
)
|
||||
|
||||
|
||||
Customizing templates
|
||||
---------------------
|
||||
|
||||
It is possible to customize the HTML of this widget in your form template. To do so, you will need to loop through ``form.{field}.field.choices``. Here is an example that displays the field label underneath/after the checkbox for a ``MultiSelectField`` called ``providers``:
|
||||
|
||||
.. code-block:: HTML+Django
|
||||
|
||||
{% for value, text in form.providers.field.choices %}
|
||||
<div class="ui slider checkbox">
|
||||
<input id="id_providers_{{ forloop.counter0 }}" name="{{ form.providers.name }}" type="checkbox" value="{{ value }}"{% if value in checked_providers %} checked="checked"{% endif %}>
|
||||
<label>{{ text }}</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
|
||||
Django REST Framework
|
||||
---------------------
|
||||
|
||||
Django REST Framework comes with a ``MultipleChoiceField`` that works perfectly with this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from rest_framework import fields, serializers
|
||||
|
||||
from myapp.models import MY_CHOICES, MY_CHOICES2
|
||||
|
||||
class MyModelSerializer(serializers.HyperlinkedModelSerializer):
|
||||
# ...
|
||||
my_field = fields.MultipleChoiceField(choices=MY_CHOICES)
|
||||
my_field2 = fields.MultipleChoiceField(choices=MY_CHOICES2)
|
||||
# ...
|
||||
|
||||
|
||||
Known Bugs and Limitations
|
||||
==========================
|
||||
|
||||
All tests pass on Django 1.4, 1.5, and 1.8+, so if you can, use a modern version of Django. However, if you must use Django 1.6 or 1.7 there are two known issues you will need to be aware of:
|
||||
|
||||
1. `Named groups <https://github.com/goinnn/django-multiselectfield/pull/30#issue-52149983>`_ do not render properly in Django 1.6. The workaround is to manually render the field in your form or use a custom widget. If your workaround is suitably generic, please submit a pull request with it.
|
||||
|
||||
2. Only in Django 1.6 and 1.7, due to `Django bug #9619 <https://code.djangoproject.com/ticket/9619>`_, passing a MultiSelectField to ``values()`` or ``values_list()`` will return the database representation of the field (a string of comma-separated values). The workaround is to manually call ``.split(',')`` on the result.
|
||||
|
||||
The Django bug was introduced in Django 1.6 and is fixed in Django 1.8 and onward, so ``values()`` and ``values_list()`` return a vanilla Python list of values for Django <= 1.5 and Django >= 1.8.
|
||||
|
||||
See `issue #40 <https://github.com/goinnn/django-multiselectfield/issues/40>`_ for discussion about this bug.
|
||||
|
||||
|
||||
Development
|
||||
===========
|
||||
|
||||
You can get the last bleeding edge version of django-multiselectfield by doing a clone
|
||||
of its git repository:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/goinnn/django-multiselectfield
|
||||
|
||||
|
||||
Example project
|
||||
===============
|
||||
|
||||
There is a fully configured example project in the `example directory <https://github.com/goinnn/django-multiselectfield/tree/master/example/>`_. You can run it as usual:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python manage.py migrate # or python manage.py syncdb --noinput
|
||||
python manage.py loaddata app_data
|
||||
python manage.py runserver
|
||||
|
||||
|
||||
0.1.12 (2020-02-20)
|
||||
-------------------
|
||||
|
||||
* Optimize multiselectfield to_python method
|
||||
* Thanks to:
|
||||
* `daimon99 <https://github.com/daimon99>`_
|
||||
|
||||
0.1.11 (2019-12-19)
|
||||
-------------------
|
||||
|
||||
* Added support for Django 3
|
||||
* Added support for Python 3.8
|
||||
* Thanks to:
|
||||
* `thijsBoehme <https://github.com/thijsBoehme>`_
|
||||
|
||||
0.1.9 (2019-10-02)
|
||||
------------------
|
||||
|
||||
* Added support for Django 2
|
||||
* Added support for Python 3.6
|
||||
* Drop support for Python (2.6, 3.3)
|
||||
* Thanks to:
|
||||
* `hirokinko <https://github.com/hirokinko>`_
|
||||
|
||||
0.1.6 (2017-05-10)
|
||||
------------------
|
||||
|
||||
* Added support for Django 1.11
|
||||
* Added support for Python 3.6
|
||||
* Improved rendering in Django admin
|
||||
* Improved documentation
|
||||
* Thanks to:
|
||||
* `atten <https://github.com/atten>`_
|
||||
* `ixc <https://github.comixc>`_
|
||||
* `LeilaniAnn <https://github.comLeilaniAnn>`_
|
||||
|
||||
0.1.5 (2017-01-02)
|
||||
------------------
|
||||
|
||||
* Added support for Django 1.8-1.10
|
||||
* Added support for named groups in choices
|
||||
* Added support for min_choices argument
|
||||
* Various fixes
|
||||
* More tests
|
||||
* Thanks to:
|
||||
* `danilogbotelho <https://github.comdanilogbotelho>`_
|
||||
* `dmitry-krasilnikov <https://github.comdmitry-krasilnikov>`_
|
||||
* `Kamil Dębowski <https://github.comkdebowski>`_
|
||||
|
||||
0.1.4 (2016-02-23)
|
||||
------------------
|
||||
|
||||
* Fixed warning about SubfieldBase
|
||||
* Added support for Django 1.8+
|
||||
* Added support for named groups
|
||||
* We now play nice with django-dynamic-fixture
|
||||
* More tests
|
||||
|
||||
0.1.3 (2014-10-13)
|
||||
------------------
|
||||
|
||||
* Support to Django 1.7 (I'm sorry to the delay)
|
||||
* Adding get_FIELD_list function
|
||||
* Fix an error when a MultiSelectField was reandonly at the admin site
|
||||
* Thanks to:
|
||||
* `Hernil <https://github.com/hernil>`_
|
||||
* `Vasyl Stanislavchuk <https://github.com/vasyabigi>`_
|
||||
* `Litchfield <https://github.com/litchfield/>`_
|
||||
* `Chris-erickson <https://github.com/chris-erickson>`_
|
||||
|
||||
0.1.2 (2014-04-04)
|
||||
------------------
|
||||
|
||||
* Include the spanish translations to the pypi egg
|
||||
* Improvements in the readme file
|
||||
* Windows OS compatibility
|
||||
* Thanks to:
|
||||
* `StillNewb <https://github.com/StillNewb>`_
|
||||
* `Diego Yungh <https://github.com/DiegoYungh>`_
|
||||
|
||||
0.1.1 (2013-12-04)
|
||||
------------------
|
||||
* Move the multiselectfield app to parent folder
|
||||
* Details
|
||||
|
||||
0.1.0 (2013-11-30)
|
||||
------------------
|
||||
|
||||
* Test/example project
|
||||
* Now works if the first composant of the list of tuple is an integer
|
||||
* Now max_length is not required, the Multiselect field calculate it automatically.
|
||||
* The max_choices attr can be a attr in the model field
|
||||
* Refactor the code
|
||||
* Spanish translations
|
||||
* Support to python2.6
|
||||
* Thanks to:
|
||||
* `Daniele Procida <https://github.com/evildmp>`_
|
||||
|
||||
0.0.3 (2013-09-11)
|
||||
------------------
|
||||
|
||||
* Python 3 compatible
|
||||
* Fix an error, the snippet had another error when the choices were translatables
|
||||
* Improvements in the README file
|
||||
|
||||
|
||||
0.0.2 (2012-09-28)
|
||||
------------------
|
||||
|
||||
* Fix an error, the snippet had an error.
|
||||
|
||||
0.0.1 (2012-09-27)
|
||||
------------------
|
||||
|
||||
* Initial version from the next `snippet <http://djangosnippets.org/snippets/1200/>`_
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
django_multiselectfield-0.1.12.dist-info/DESCRIPTION.rst,sha256=QjtRluOTQmWzudG8mNHhBKQb7foYzHq7ZxCs3PAx1bM,8179
|
||||
django_multiselectfield-0.1.12.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
django_multiselectfield-0.1.12.dist-info/METADATA,sha256=PF35_c0b7aDHBn_nVLS8Hs63e_S6wRZTs0khOvADJ4Q,9172
|
||||
django_multiselectfield-0.1.12.dist-info/RECORD,,
|
||||
django_multiselectfield-0.1.12.dist-info/WHEEL,sha256=8Lm45v9gcYRm70DrgFGVe4WsUtUMi1_0Tso1hqPGMjA,92
|
||||
django_multiselectfield-0.1.12.dist-info/metadata.json,sha256=1R2BnZqhvSNaPVMsgYuBM9Hn50w_spOvHiwh7IdYYfk,1216
|
||||
django_multiselectfield-0.1.12.dist-info/top_level.txt,sha256=Y5vMmoRWcEEnorayclFbrq60Hy-7-EM5TAhBEw-rlec,17
|
||||
multiselectfield/__init__.py,sha256=YhzWaV3qo676EhtgUXuwWZBggKuLuls_8G2ytQqHBmY,217
|
||||
multiselectfield/__pycache__/__init__.cpython-38.pyc,,
|
||||
multiselectfield/__pycache__/apps.cpython-38.pyc,,
|
||||
multiselectfield/__pycache__/utils.cpython-38.pyc,,
|
||||
multiselectfield/__pycache__/validators.cpython-38.pyc,,
|
||||
multiselectfield/apps.py,sha256=qcW5RvrLleieNOz4swZ1QA5SCvX7zDHwY4QcoNr9y30,146
|
||||
multiselectfield/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
multiselectfield/db/__pycache__/__init__.cpython-38.pyc,,
|
||||
multiselectfield/db/__pycache__/fields.cpython-38.pyc,,
|
||||
multiselectfield/db/fields.py,sha256=tRm8Ux8aJZJ3Oacr7AYpnN6c88b1u7MgmP0lg-KPi10,7959
|
||||
multiselectfield/forms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
multiselectfield/forms/__pycache__/__init__.cpython-38.pyc,,
|
||||
multiselectfield/forms/__pycache__/fields.cpython-38.pyc,,
|
||||
multiselectfield/forms/fields.py,sha256=dqaqK9bWwuRpJKBE1DcmsydcqU0OH0RGK3XXrOF-9XA,1659
|
||||
multiselectfield/locale/es/LC_MESSAGES/django.mo,sha256=xqKsXhCPHi0YJI_s5ug4syKyoDGdQ_TEwuZzRZoiWNM,564
|
||||
multiselectfield/locale/es/LC_MESSAGES/django.po,sha256=5uPlVcG897BqGXxBk-pPleMWUAypNVsZsf8s6JlERVk,770
|
||||
multiselectfield/utils.py,sha256=Ojf4Iomw9dheF3ZaHQ_oNB3RsA-d-X3uHtZX95HfDJo,1153
|
||||
multiselectfield/validators.py,sha256=E4xwHf56W_WtQ3nE_6WUPUl_DDLrMKjBB9ZKSSvbQfM,1310
|
||||
@@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.30.0)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"classifiers": ["Development Status :: 4 - Beta", "Framework :: Django", "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8"], "extensions": {"python.details": {"contacts": [{"email": "goinnn@gmail.com", "name": "Pablo Martin", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/goinnn/django-multiselectfield"}}}, "extras": [], "generator": "bdist_wheel (0.30.0)", "keywords": ["django", "multiple", "select", "field", "choices"], "license": "LGPL 3", "metadata_version": "2.0", "name": "django-multiselectfield", "run_requires": [{"requires": ["django (>=1.4)"]}], "summary": "Django multiple select field", "test_requires": [{"requires": ["coverage", "django (>=1.4)", "flake8", "tox"]}], "version": "0.1.12"}
|
||||
@@ -0,0 +1 @@
|
||||
multiselectfield
|
||||
@@ -0,0 +1,5 @@
|
||||
from multiselectfield.db.fields import MultiSelectField # noqa: F401
|
||||
from multiselectfield.forms.fields import MultiSelectFormField # noqa: F401
|
||||
|
||||
|
||||
default_app_config = 'multiselectfield.apps.MultiSelectFieldConfig'
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MultiSelectFieldConfig(AppConfig):
|
||||
name = 'multiselectfield'
|
||||
verbose_name = 'Multiselect Field'
|
||||
Binary file not shown.
Binary file not shown.
205
venv/lib/python3.8/site-packages/multiselectfield/db/fields.py
Normal file
205
venv/lib/python3.8/site-packages/multiselectfield/db/fields.py
Normal file
@@ -0,0 +1,205 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2012 by Pablo Martín <goinnn@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this programe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
|
||||
from django import VERSION
|
||||
|
||||
from django.db import models
|
||||
from django.utils.text import capfirst
|
||||
from django.core import exceptions
|
||||
|
||||
from ..forms.fields import MultiSelectFormField, MinChoicesValidator, MaxChoicesValidator
|
||||
from ..utils import get_max_length
|
||||
from ..validators import MaxValueMultiFieldValidator
|
||||
|
||||
if sys.version_info < (3,):
|
||||
string_type = unicode # noqa: F821
|
||||
else:
|
||||
string_type = str
|
||||
|
||||
# Code from six egg https://bitbucket.org/gutworth/six/src/a3641cb211cc360848f1e2dd92e9ae6cd1de55dd/six.py?at=default
|
||||
|
||||
|
||||
def add_metaclass(metaclass):
|
||||
"""Class decorator for creating a class with a metaclass."""
|
||||
def wrapper(cls):
|
||||
orig_vars = cls.__dict__.copy()
|
||||
orig_vars.pop('__dict__', None)
|
||||
orig_vars.pop('__weakref__', None)
|
||||
for slots_var in orig_vars.get('__slots__', ()):
|
||||
orig_vars.pop(slots_var)
|
||||
return metaclass(cls.__name__, cls.__bases__, orig_vars)
|
||||
return wrapper
|
||||
|
||||
|
||||
class MSFList(list):
|
||||
|
||||
def __init__(self, choices, *args, **kwargs):
|
||||
self.choices = choices
|
||||
super(MSFList, self).__init__(*args, **kwargs)
|
||||
|
||||
def __str__(msgl):
|
||||
msg_list = [msgl.choices.get(int(i)) if i.isdigit() else msgl.choices.get(i) for i in msgl]
|
||||
return u', '.join([string_type(s) for s in msg_list])
|
||||
|
||||
if sys.version_info < (3,):
|
||||
def __unicode__(self, msgl):
|
||||
return self.__str__(msgl)
|
||||
|
||||
|
||||
class MultiSelectField(models.CharField):
|
||||
""" Choice values can not contain commas. """
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.min_choices = kwargs.pop('min_choices', None)
|
||||
self.max_choices = kwargs.pop('max_choices', None)
|
||||
super(MultiSelectField, self).__init__(*args, **kwargs)
|
||||
self.max_length = get_max_length(self.choices, self.max_length)
|
||||
self.validators[0] = MaxValueMultiFieldValidator(self.max_length)
|
||||
if self.min_choices is not None:
|
||||
self.validators.append(MinChoicesValidator(self.min_choices))
|
||||
if self.max_choices is not None:
|
||||
self.validators.append(MaxChoicesValidator(self.max_choices))
|
||||
|
||||
def _get_flatchoices(self):
|
||||
flat_choices = super(MultiSelectField, self)._get_flatchoices()
|
||||
|
||||
class MSFFlatchoices(list):
|
||||
# Used to trick django.contrib.admin.utils.display_for_field into
|
||||
# not treating the list of values as a dictionary key (which errors
|
||||
# out)
|
||||
def __bool__(self):
|
||||
return False
|
||||
__nonzero__ = __bool__
|
||||
return MSFFlatchoices(flat_choices)
|
||||
flatchoices = property(_get_flatchoices)
|
||||
|
||||
def get_choices_default(self):
|
||||
return self.get_choices(include_blank=False)
|
||||
|
||||
def get_choices_selected(self, arr_choices):
|
||||
named_groups = arr_choices and isinstance(arr_choices[0][1], (list, tuple))
|
||||
choices_selected = []
|
||||
if named_groups:
|
||||
for choice_group_selected in arr_choices:
|
||||
for choice_selected in choice_group_selected[1]:
|
||||
choices_selected.append(string_type(choice_selected[0]))
|
||||
else:
|
||||
for choice_selected in arr_choices:
|
||||
choices_selected.append(string_type(choice_selected[0]))
|
||||
return choices_selected
|
||||
|
||||
def value_to_string(self, obj):
|
||||
try:
|
||||
value = self._get_val_from_obj(obj)
|
||||
except AttributeError:
|
||||
value = super(MultiSelectField, self).value_from_object(obj)
|
||||
return self.get_prep_value(value)
|
||||
|
||||
def validate(self, value, model_instance):
|
||||
arr_choices = self.get_choices_selected(self.get_choices_default())
|
||||
for opt_select in value:
|
||||
if (opt_select not in arr_choices):
|
||||
if VERSION >= (1, 6):
|
||||
raise exceptions.ValidationError(self.error_messages['invalid_choice'] % {"value": value})
|
||||
else:
|
||||
raise exceptions.ValidationError(self.error_messages['invalid_choice'] % value)
|
||||
|
||||
def get_default(self):
|
||||
default = super(MultiSelectField, self).get_default()
|
||||
if isinstance(default, int):
|
||||
default = string_type(default)
|
||||
return default
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
defaults = {'required': not self.blank,
|
||||
'label': capfirst(self.verbose_name),
|
||||
'help_text': self.help_text,
|
||||
'choices': self.choices,
|
||||
'max_length': self.max_length,
|
||||
'max_choices': self.max_choices}
|
||||
if self.has_default():
|
||||
defaults['initial'] = self.get_default()
|
||||
defaults.update(kwargs)
|
||||
return MultiSelectFormField(**defaults)
|
||||
|
||||
def get_prep_value(self, value):
|
||||
return '' if value is None else ",".join(map(str, value))
|
||||
|
||||
def get_db_prep_value(self, value, connection, prepared=False):
|
||||
if not prepared and not isinstance(value, string_type):
|
||||
value = self.get_prep_value(value)
|
||||
return value
|
||||
|
||||
def to_python(self, value):
|
||||
choices = dict(self.flatchoices)
|
||||
|
||||
if value:
|
||||
if isinstance(value, list):
|
||||
return value
|
||||
elif isinstance(value, string_type):
|
||||
value_list = map(lambda x: x.strip(), value.replace(u',', ',').split(','))
|
||||
return MSFList(choices, value_list)
|
||||
elif isinstance(value, (set, dict)):
|
||||
return MSFList(choices, list(value))
|
||||
return MSFList(choices, [])
|
||||
|
||||
if VERSION < (2, ):
|
||||
def from_db_value(self, value, expression, connection, context):
|
||||
if value is None:
|
||||
return value
|
||||
return self.to_python(value)
|
||||
else:
|
||||
def from_db_value(self, value, expression, connection):
|
||||
if value is None:
|
||||
return value
|
||||
return self.to_python(value)
|
||||
|
||||
def contribute_to_class(self, cls, name):
|
||||
super(MultiSelectField, self).contribute_to_class(cls, name)
|
||||
if self.choices:
|
||||
def get_list(obj):
|
||||
fieldname = name
|
||||
choicedict = dict(self.choices)
|
||||
display = []
|
||||
if getattr(obj, fieldname):
|
||||
for value in getattr(obj, fieldname):
|
||||
item_display = choicedict.get(value, None)
|
||||
if item_display is None:
|
||||
try:
|
||||
item_display = choicedict.get(int(value), value)
|
||||
except (ValueError, TypeError):
|
||||
item_display = value
|
||||
display.append(string_type(item_display))
|
||||
return display
|
||||
|
||||
def get_display(obj):
|
||||
return ", ".join(get_list(obj))
|
||||
get_display.short_description = self.verbose_name
|
||||
|
||||
setattr(cls, 'get_%s_list' % self.name, get_list)
|
||||
setattr(cls, 'get_%s_display' % self.name, get_display)
|
||||
|
||||
|
||||
if VERSION < (1, 8):
|
||||
MultiSelectField = add_metaclass(models.SubfieldBase)(MultiSelectField)
|
||||
|
||||
try:
|
||||
from south.modelsinspector import add_introspection_rules
|
||||
add_introspection_rules([], ['^multiselectfield\.db.fields\.MultiSelectField'])
|
||||
except ImportError:
|
||||
pass
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2012 by Pablo Martín <goinnn@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this programe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django import forms
|
||||
|
||||
from ..utils import get_max_length
|
||||
from ..validators import MaxValueMultiFieldValidator, MinChoicesValidator, MaxChoicesValidator
|
||||
|
||||
|
||||
class MultiSelectFormField(forms.MultipleChoiceField):
|
||||
widget = forms.CheckboxSelectMultiple
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.min_choices = kwargs.pop('min_choices', None)
|
||||
self.max_choices = kwargs.pop('max_choices', None)
|
||||
self.max_length = kwargs.pop('max_length', None)
|
||||
super(MultiSelectFormField, self).__init__(*args, **kwargs)
|
||||
self.max_length = get_max_length(self.choices, self.max_length)
|
||||
self.validators.append(MaxValueMultiFieldValidator(self.max_length))
|
||||
if self.max_choices is not None:
|
||||
self.validators.append(MaxChoicesValidator(self.max_choices))
|
||||
if self.min_choices is not None:
|
||||
self.validators.append(MinChoicesValidator(self.min_choices))
|
||||
Binary file not shown.
@@ -0,0 +1,23 @@
|
||||
# django-multiselectfield.
|
||||
# Copyright (C) 2012-2013
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <goinnn@gmail.com>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 1.0.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-11-30 20:06-0500\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Pablo Martín <goinnn@gmail.com>\n"
|
||||
"Language-Team: Es <goinnn@gmail.com>\n"
|
||||
"Language: Es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: validators.py:28
|
||||
#, python-format
|
||||
msgid "You must select a maximum of %(limit_value)d choices."
|
||||
msgstr "Tu debes de seleccionar un máximo de %(limit_value)d opciones."
|
||||
34
venv/lib/python3.8/site-packages/multiselectfield/utils.py
Normal file
34
venv/lib/python3.8/site-packages/multiselectfield/utils.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2013 by Pablo Martín <goinnn@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this programe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
if sys.version_info[0] == 2:
|
||||
string = basestring # noqa: F821
|
||||
string_type = unicode # noqa: F821
|
||||
else:
|
||||
string = str
|
||||
string_type = string
|
||||
|
||||
|
||||
def get_max_length(choices, max_length, default=200):
|
||||
if max_length is None:
|
||||
if choices:
|
||||
return len(','.join([string_type(key) for key, label in choices]))
|
||||
else:
|
||||
return default
|
||||
return max_length
|
||||
@@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2013 by Pablo Martín <goinnn@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this programe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from django.core import validators
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class MaxValueMultiFieldValidator(validators.MaxLengthValidator):
|
||||
code = 'max_multifield_value'
|
||||
|
||||
def clean(self, x):
|
||||
return len(','.join(x))
|
||||
|
||||
|
||||
class MinChoicesValidator(validators.MinLengthValidator):
|
||||
message = _(u'You must select a minimum of %(limit_value)d choices.')
|
||||
code = 'min_choices'
|
||||
|
||||
|
||||
class MaxChoicesValidator(validators.MaxLengthValidator):
|
||||
message = _(u'You must select a maximum of %(limit_value)d choices.')
|
||||
code = 'max_choices'
|
||||
Binary file not shown.
Reference in New Issue
Block a user