Weapons. Migrations.

This commit is contained in:
tcaxle 2020-04-11 14:01:52 +01:00
parent 54ab35444e
commit 7b76481d1d
30 changed files with 988 additions and 3 deletions

View File

@ -0,0 +1,34 @@
# Generated by Django 3.0.5 on 2020-04-11 13:01
import app.models
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('app', '0008_auto_20200411_1255'),
]
operations = [
migrations.AddField(
model_name='itemweaponmelee',
name='category',
field=app.models.SingleChoiceField(blank=True, choices=[('L', 'Light'), ('M', 'Medium'), ('H', 'Heavy')], max_length=100, verbose_name='Category'),
),
migrations.AddField(
model_name='itemweaponmelee',
name='tags',
field=app.models.MultiChoiceField(blank=True, choices=[('General', (('ONE HANDED', 'One Handed'), ('TWO HANDED', 'Two Handed'), ('BASHING', 'Bashing'), ('CONCEALABLE', 'Concealable'), ('LETHAL', 'Lethal'), ('MOUNTED', 'Mounted'), ('PIERCING', 'Piercing'), ('SPECIAL', 'Special'))), ('Melee', (('MELEE', 'Melee'), ('BALANCED', 'Balanced'), ('BRAWL', 'Brawl'), ('CHOPPING', 'Chopping'), ('DISARMING', 'Disarming'), ('FLEXIBLE', 'Flexible'), ('IMPROVISED', 'Improvised'), ('GRAPPLING', 'Grappling'), ('MARTIAL ARTS', 'Martial Arts'), ('NATURAL', 'Natural'), ('REACHING', 'Reaching'), ('SHIELD', 'Shield'), ('SMASHING', 'Smashing'), ('WORN', 'Worn'))), ('Thrown', (('THROWN', 'Occult'), ('CUTTING', 'Cutting'), ('POISONABLE', 'Poisonable'), ('SUBTLE', 'Subtle'))), ('Archery', (('ARCHERY', 'Archery'), ('CROSSBOW', 'Crossbow'), ('FLAME', 'Flame'), ('POWERFUL', 'Powerful'), ('SLOW', 'Slow')))], max_length=100, verbose_name='Tags'),
),
migrations.AddField(
model_name='itemweaponranged',
name='category',
field=app.models.SingleChoiceField(blank=True, choices=[('L', 'Light'), ('M', 'Medium'), ('H', 'Heavy')], max_length=100, verbose_name='Category'),
),
migrations.AddField(
model_name='itemweaponranged',
name='tags',
field=app.models.MultiChoiceField(blank=True, choices=[('General', (('ONE HANDED', 'One Handed'), ('TWO HANDED', 'Two Handed'), ('BASHING', 'Bashing'), ('CONCEALABLE', 'Concealable'), ('LETHAL', 'Lethal'), ('MOUNTED', 'Mounted'), ('PIERCING', 'Piercing'), ('SPECIAL', 'Special'))), ('Melee', (('MELEE', 'Melee'), ('BALANCED', 'Balanced'), ('BRAWL', 'Brawl'), ('CHOPPING', 'Chopping'), ('DISARMING', 'Disarming'), ('FLEXIBLE', 'Flexible'), ('IMPROVISED', 'Improvised'), ('GRAPPLING', 'Grappling'), ('MARTIAL ARTS', 'Martial Arts'), ('NATURAL', 'Natural'), ('REACHING', 'Reaching'), ('SHIELD', 'Shield'), ('SMASHING', 'Smashing'), ('WORN', 'Worn'))), ('Thrown', (('THROWN', 'Occult'), ('CUTTING', 'Cutting'), ('POISONABLE', 'Poisonable'), ('SUBTLE', 'Subtle'))), ('Archery', (('ARCHERY', 'Archery'), ('CROSSBOW', 'Crossbow'), ('FLAME', 'Flame'), ('POWERFUL', 'Powerful'), ('SLOW', 'Slow')))], max_length=100, verbose_name='Tags'),
),
]

View File

@ -1,4 +1,5 @@
from django.db import models from django.db import models
import multiselectfield
#==============================================================================# #==============================================================================#
#-------------------------------- OPTION LISTS --------------------------------# #-------------------------------- OPTION LISTS --------------------------------#
@ -87,7 +88,7 @@ CATEGORIES = [
("H", "Heavy"), ("H", "Heavy"),
] ]
TAGS_WEAPON = [ TAGS_WEAPONS = [
( (
"General", ( "General", (
("ONE HANDED", "One Handed"), ("ONE HANDED", "One Handed"),
@ -181,6 +182,14 @@ class SingleChoiceField(models.CharField):
kwargs['max_length'] = 100 kwargs['max_length'] = 100
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
class MultiChoiceField(multiselectfield.MultiSelectField):
def __init__(self, verbose_name, choices, *args, **kwargs):
kwargs['verbose_name'] = verbose_name
kwargs['choices'] = choices
kwargs['blank'] = True
kwargs['max_length'] = 100
super().__init__(*args, **kwargs)
class NamedIntegerField(models.IntegerField): class NamedIntegerField(models.IntegerField):
def __init__(self, verbose_name, desc=None, *args, **kwargs): def __init__(self, verbose_name, desc=None, *args, **kwargs):
kwargs['verbose_name'] = verbose_name kwargs['verbose_name'] = verbose_name
@ -196,6 +205,7 @@ class NamedCharField(models.CharField):
kwargs['max_length'] = 100 kwargs['max_length'] = 100
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
#==============================================================================# #==============================================================================#
#--------------------------------- MODIFIERS ----------------------------------# #--------------------------------- MODIFIERS ----------------------------------#
#==============================================================================# #==============================================================================#
@ -233,8 +243,8 @@ class itemWeaponBase(itemBase):
class Meta: class Meta:
abstract = True abstract = True
# category category = SingleChoiceField("Category", CATEGORIES)
# tags tags = MultiChoiceField("Tags", TAGS_WEAPONS)
accuracy = NamedIntegerField("Accuracy") accuracy = NamedIntegerField("Accuracy")
damage = NamedIntegerField("Damage") damage = NamedIntegerField("Damage")
defense = NamedIntegerField("Defense") defense = NamedIntegerField("Defense")

View File

@ -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/>`_

View File

@ -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/>`_

View File

@ -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

View File

@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.30.0)
Root-Is-Purelib: true
Tag: py3-none-any

View File

@ -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"}

View File

@ -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'

View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class MultiSelectFieldConfig(AppConfig):
name = 'multiselectfield'
verbose_name = 'Multiselect Field'

View 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

View File

@ -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))

View File

@ -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."

View 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

View File

@ -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'