686 lines
25 KiB
Text
686 lines
25 KiB
Text
Metadata-Version: 2.4
|
||
Name: django-multiselectfield
|
||
Version: 1.0.1
|
||
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
|
||
Classifier: Development Status :: 4 - Beta
|
||
Classifier: Framework :: Django
|
||
Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
|
||
Classifier: Programming Language :: Python :: 3.8
|
||
Classifier: Programming Language :: Python :: 3.9
|
||
Classifier: Programming Language :: Python :: 3.10
|
||
Classifier: Programming Language :: Python :: 3.11
|
||
Classifier: Programming Language :: Python :: 3.12
|
||
Classifier: Framework :: Django :: 3.2
|
||
Classifier: Framework :: Django :: 4.2
|
||
Classifier: Framework :: Django :: 5.0
|
||
Classifier: Framework :: Django :: 5.1
|
||
License-File: COPYING.LGPLv3
|
||
Requires-Dist: django>=3.2
|
||
Dynamic: author
|
||
Dynamic: author-email
|
||
Dynamic: classifier
|
||
Dynamic: description
|
||
Dynamic: home-page
|
||
Dynamic: keywords
|
||
Dynamic: license
|
||
Dynamic: license-file
|
||
Dynamic: requires-dist
|
||
Dynamic: summary
|
||
|
||
=======================
|
||
django-multiselectfield
|
||
=======================
|
||
|
||
.. image:: https://github.com/goinnn/django-multiselectfield/actions/workflows/tests.yaml/badge.svg
|
||
:target: https://github.com/goinnn/django-multiselectfield/actions/workflows/tests.yaml
|
||
|
||
.. 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
|
||
|
||
|
||
-------------------
|
||
|
||
|
||
Support this package by donating here! ➡️
|
||
=========================================
|
||
|
||
If you find this package useful, consider supporting it:
|
||
|
||
.. image:: https://raw.githubusercontent.com/goinnn/django-multiselectfield/master/assets/arial-yellow.png
|
||
:target: https://www.buymeacoffee.com/goinnn
|
||
:alt: Buy Me a Coffee
|
||
:height: 40px
|
||
|
||
.. image:: https://img.shields.io/badge/PayPal-badge?style=plastic&logo=paypal&color=white
|
||
:target: https://www.paypal.com/paypalme/goinnn
|
||
:alt: Paypal
|
||
:height: 40px
|
||
|
||
|
||
-------------------
|
||
|
||
django-multiselectfield provides new model and form fields for Django models, allowing multiple selections from a list of choices. The selected values are stored in the database as a CharField containing a comma-separated values.
|
||
|
||
This package is inspired by this `snippet <https://djangosnippets.org/snippets/1200/>`_.
|
||
|
||
*Note: This snippet is from 2008, and a lot has changed since then.*
|
||
|
||
**Supported Python versions**: 3.8+
|
||
|
||
**Supported Django versions**: 3.2+
|
||
|
||
1. Installation
|
||
================
|
||
|
||
|
||
1.1 Install with pip
|
||
---------------------
|
||
|
||
.. code-block:: bash
|
||
|
||
$ pip install django-multiselectfield
|
||
|
||
1.2 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, default=['item_key1', 'item_key5'])
|
||
my_field2 = MultiSelectField(choices=MY_CHOICES2, min_choices=2, max_choices=3, max_length=3)
|
||
|
||
|
||
# Do not use integer choices like this:
|
||
|
||
MY_INTEGER_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'))
|
||
|
||
# Because when MultiSelectField retrieves data from db, it cannot know if the values are integers or strings.
|
||
# In other words, MultiSelectField save the same data for MY_CHOICES2 and MY_INTEGER_CHOICES2
|
||
# Or in practice it should be the same MY_CHOICES2 and MY_INTEGER_CHOICES2
|
||
|
||
|
||
1.3 In your settings.py
|
||
-----------------------
|
||
|
||
Only required if you want the translation of django-multiselectfield or need its static files.
|
||
|
||
.. code-block:: python
|
||
|
||
INSTALLED_APPS = (
|
||
'django.contrib.auth',
|
||
'django.contrib.contenttypes',
|
||
'django.contrib.sessions',
|
||
'django.contrib.sites',
|
||
'django.contrib.admin',
|
||
|
||
#.....................#
|
||
|
||
'multiselectfield',
|
||
)
|
||
|
||
1.4 SortMultiSelectField
|
||
------------------------
|
||
|
||
Since version 1.0.0 (2025-06-12), this package also includes a another field type called: SortMultiSelectField.
|
||
|
||
For this field to work, you need to include `jQuery <https://jquery.com/download/>`_ (already included in the Django admin) and `jQuery UI <https://jqueryui.com/download/>`_.
|
||
|
||
You can include them by updating the ModelAdmin’s form or directly in change_form.html (less efficient but faster), as shown in the `example project: change_form.html line 11 <https://github.com/goinnn/django-multiselectfield/blob/b7d113a4a1ad6b35698126729264942e30e30039/example/templates/admin/change_form.html#L11>`_.
|
||
|
||
1.5 Other recommendations
|
||
-------------------------
|
||
|
||
`As django recommended: <https://docs.djangoproject.com/en/5.2/ref/models/fields/#django.db.models.Field.null>`_ Avoid using null on string-based fields such as CharField and TextField.
|
||
|
||
MultiSelectField is based on CharField (MultiSelectField inheritances of CharField). So, if the field is not required, use only blank=True (null=False by default):
|
||
|
||
.. code-block:: python
|
||
|
||
class MyModel(models.Model):
|
||
|
||
# .....
|
||
|
||
my_field = MultiSelectField(choices=MY_CHOICES, blank=True)
|
||
|
||
|
||
2. Custom and integrations
|
||
===========================
|
||
|
||
2.1 Customizing templates
|
||
--------------------------
|
||
|
||
You can 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 %}
|
||
|
||
|
||
2.2 Fixing CSS alignment in the Django administration
|
||
------------------------------------------------------
|
||
|
||
This fixes alignment. The labels appear slightly lower than the checkboxes, and the label width is very small.
|
||
|
||
Include the following CSS file: multiselectfield/css/admin-multiselectfield.css
|
||
|
||
You can include it by updating the ModelAdmin’s form or directly in change_form.html (less efficient but faster), as shown in the `example project: change_form.html line 7 <https://github.com/goinnn/django-multiselectfield/blob/b7d113a4a1ad6b35698126729264942e30e30039/example/templates/admin/change_form.html#L7>`_.
|
||
|
||
2.3 Add a filter to the Django administration
|
||
----------------------------------------------
|
||
|
||
You can see it in `example project: admin.py line 23 <https://github.com/goinnn/django-multiselectfield/blob/4ee111e11e2f3a51aa693c0863ee64d93b4a097d/example/app/admin.py#L23>`_
|
||
|
||
.. code-block:: python
|
||
|
||
from django.contrib import admin
|
||
|
||
|
||
def _multiple_choice_filter(field_name, label):
|
||
|
||
class MultiSelectFilter(admin.SimpleListFilter):
|
||
title = label
|
||
parameter_name = field_name
|
||
|
||
def lookups(self, request, model_admin):
|
||
return model_admin.model._meta.get_field(field_name).flatchoices
|
||
|
||
def queryset(self, request, queryset):
|
||
value = self.value()
|
||
if value:
|
||
queryset = queryset.filter(Q(**{
|
||
f'{self.parameter_name}__exact': value,
|
||
}) | Q(**{
|
||
f'{self.parameter_name}__startswith': f'{value},',
|
||
}) | Q(**{
|
||
f'{self.parameter_name}__endswith': f',{value}'
|
||
}) | Q(**{
|
||
f'{self.parameter_name}__icontains': f',{value},'
|
||
}))
|
||
|
||
return queryset
|
||
return MultiSelectFilter
|
||
|
||
class BookAdmin(admin.ModelAdmin):
|
||
list_display = ('title', 'categories', 'tags', 'published_in')
|
||
list_filter = (
|
||
_multiple_choice_filter('categories', _('categories')),
|
||
_multiple_choice_filter('tags', _('tags')),
|
||
_multiple_choice_filter('favorite_tags', _('favourite tags')),
|
||
_multiple_choice_filter('published_in', _('province or state')),
|
||
_multiple_choice_filter('chapters', _('chapters')),
|
||
)
|
||
|
||
2.4 Add a django multiselect field to list_display in Django administration
|
||
----------------------------------------------------------------------------
|
||
|
||
Django doesn't provide built-in support for custom fields.
|
||
|
||
|
||
2.4.1 Option 1. Use get_FOO_display
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
Change them individually
|
||
|
||
.. code-block:: python
|
||
|
||
|
||
@admin.register(Book)
|
||
class BookAdmin(admin.ModelAdmin):
|
||
list_display = ('title', 'get_categories_display',)
|
||
|
||
@admin.display(description=_('categories'), ordering='categories')
|
||
def get_categories_display(self, obj):
|
||
return obj.get_categories_display()
|
||
|
||
2.4.2 Option 2. Monkey patching Django
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
If you have many django multiselect fields in list_display, the previous option can be much work.
|
||
|
||
You can see it in the `example project: apps.py line 34 <https://github.com/goinnn/django-multiselectfield/blob/65376239ae7491414f896adb4d314349ff7c2667/example/app/apps.py#L34>`_.
|
||
|
||
This code is inspired by django code. It is possible that for other versions of Django you may need to adapt it.
|
||
|
||
.. code-block:: python
|
||
|
||
from django.apps import AppConfig
|
||
from django import VERSION
|
||
from django.contrib.admin import utils
|
||
from django.utils.hashable import make_hashable
|
||
|
||
from multiselectfield.db.fields import MultiSelectField
|
||
|
||
|
||
class AppAppConfig(AppConfig):
|
||
name = 'app'
|
||
verbose_name = 'app'
|
||
|
||
def ready(self):
|
||
if not hasattr(utils, '_original_display_for_field'):
|
||
utils._original_display_for_field = utils.display_for_field
|
||
utils.display_for_field = patched_display_for_field
|
||
|
||
|
||
# Monkey patching for use multiselect field in list_display
|
||
|
||
def patched_display_for_field(value, field, empty_value_display, avoid_link=False):
|
||
if isinstance(field, MultiSelectField) and getattr(field, "flatchoices", None):
|
||
try:
|
||
flatchoices = dict(field.flatchoices)
|
||
return ', '.join([str(flatchoices.get(v, empty_value_display)) for v in value]) or empty_value_display
|
||
except TypeError:
|
||
# Allow list-like choices.
|
||
flatchoices = dict(make_hashable(field.flatchoices))
|
||
value = make_hashable(value)
|
||
return ', '.join([str(flatchoices.get(v, empty_value_display)) for v in value]) or empty_value_display
|
||
|
||
if VERSION < (5, 2):
|
||
return utils._original_display_for_field(value, field, empty_value_display)
|
||
return utils._original_display_for_field(value, field, empty_value_display, avoid_link=avoid_link)
|
||
|
||
2.5 Add support for read-only fields in the Django administration
|
||
-----------------------------------------------------------------
|
||
|
||
Django doesn't provide built-in support for custom fields.
|
||
|
||
You can see it in the `example project: apps.py line 52 <https://github.com/goinnn/django-multiselectfield/blob/65376239ae7491414f896adb4d314349ff7c2667/example/app/apps.py#L52>`_. Log in to the Django admin in the sample project using the following credentials: user-readonly / DMF-123.
|
||
|
||
This code is inspired by django code. It is possible that for other versions of Django you may need to adapt it.
|
||
|
||
.. code-block:: python
|
||
|
||
from django.apps import AppConfig
|
||
from django.contrib.admin.helpers import AdminReadonlyField
|
||
from django.contrib.admin.utils import display_for_field, lookup_field
|
||
from django.core.exceptions import ObjectDoesNotExist
|
||
from django.db.models.fields.related import (
|
||
ForeignObjectRel,
|
||
ManyToManyRel,
|
||
OneToOneField,
|
||
)
|
||
from django.template.defaultfilters import linebreaksbr
|
||
from django.utils.html import conditional_escape
|
||
from django.utils.translation import gettext_lazy as _
|
||
|
||
from multiselectfield.db.fields import MultiSelectField
|
||
|
||
|
||
class AppAppConfig(AppConfig):
|
||
name = 'app'
|
||
verbose_name = 'app'
|
||
|
||
def ready(self):
|
||
if not hasattr(AdminReadonlyField, '_original_contents'):
|
||
AdminReadonlyField._original_contents = AdminReadonlyField.contents
|
||
AdminReadonlyField.contents = patched_contents
|
||
|
||
def patched_contents(self):
|
||
from django.contrib.admin.templatetags.admin_list import _boolean_icon
|
||
|
||
field, obj, model_admin = (
|
||
self.field["field"],
|
||
self.form.instance,
|
||
self.model_admin,
|
||
)
|
||
try:
|
||
f, attr, value = lookup_field(field, obj, model_admin)
|
||
except (AttributeError, ValueError, ObjectDoesNotExist):
|
||
result_repr = self.empty_value_display
|
||
else:
|
||
if field in self.form.fields:
|
||
widget = self.form[field].field.widget
|
||
# This isn't elegant but suffices for contrib.auth's
|
||
# ReadOnlyPasswordHashWidget.
|
||
if getattr(widget, "read_only", False):
|
||
return widget.render(field, value)
|
||
if f is None:
|
||
if getattr(attr, "boolean", False):
|
||
result_repr = _boolean_icon(value)
|
||
else:
|
||
if hasattr(value, "__html__"):
|
||
result_repr = value
|
||
else:
|
||
result_repr = linebreaksbr(value)
|
||
else:
|
||
if isinstance(f.remote_field, ManyToManyRel) and value is not None:
|
||
result_repr = ", ".join(map(str, value.all()))
|
||
elif (
|
||
isinstance(f.remote_field, (ForeignObjectRel, OneToOneField))
|
||
and value is not None
|
||
):
|
||
result_repr = self.get_admin_url(f.remote_field, value)
|
||
# Custom: start
|
||
elif isinstance(f, MultiSelectField):
|
||
if value in f.empty_values:
|
||
result_repr = self.empty_value_display
|
||
else:
|
||
result_repr = getattr(obj, f'get_{f.name}_display')()
|
||
# Custom: end
|
||
else:
|
||
result_repr = display_for_field(value, f, self.empty_value_display)
|
||
result_repr = linebreaksbr(result_repr)
|
||
return conditional_escape(result_repr)
|
||
|
||
|
||
2.6 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)
|
||
# ...
|
||
|
||
3. Tests
|
||
========
|
||
|
||
All tests pass on Django 3.2.0, 4.0.0, 4.1.0, 4.2.0, 5.0.0 and 5.1.0
|
||
|
||
|
||
4. 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
|
||
|
||
|
||
5. 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
|
||
python manage.py loaddata app_data
|
||
python manage.py runserver
|
||
# And go to http://localhost:8000. You will be automatically authenticated as a superuser.
|
||
|
||
|
||
1.0.1 (2025-06-12)
|
||
-------------------
|
||
|
||
* Badge image worked on GitHub but was broken on PyPI — fixed it.
|
||
|
||
1.0.0 (2025-06-12)
|
||
-------------------
|
||
|
||
This release introduces multiple changes that are incompatible with previous versions.
|
||
|
||
The major version number has been incremented following `Semantic Versioning (SemVer) <https://semver.org/>`_, as several components of the package have changed in ways that may require updates in client code.
|
||
|
||
The internal codebase has been significantly cleaned up and reorganized, making it more maintainable and consistent.
|
||
|
||
This version contains **40% fewer lines of code** compared to the previous release.
|
||
|
||
Less code means fewer bugs, easier maintenance, and better long-term sustainability.
|
||
|
||
|
||
* Breaking changes
|
||
|
||
* Remove MSFList (`01dcad230dc368b88a39bfc36f90ddd145f381a2 <https://github.com/goinnn/django-multiselectfield/commit/01dcad230dc368b88a39bfc36f90ddd145f381a2>`_):
|
||
|
||
* Removed: (`50d3f785883e0a314f2dc89950e3fe1e88a7ede6 <https://github.com/goinnn/django-multiselectfield/commit/50d3f785883e0a314f2dc89950e3fe1e88a7ede6>`_)
|
||
* It was created to support MultiSelectFields in admin.list_display, but it never actually worked. If you add a multiselect field to list_display, Django does not call to __str__ method of MSGList (renamed to MSFList)
|
||
* It was created for integer choices too and it is a misconception. This is explained in the README file.
|
||
|
||
* Remove MSFFlatchoices (`01dcad230dc368b88a39bfc36f90ddd145f381a2 <https://github.com/goinnn/django-multiselectfield/commit/01dcad230dc368b88a39bfc36f90ddd145f381a2>`_):
|
||
|
||
* Removed: (`5638247c1d70670d4f81adf35143ef17a7d7575e <https://github.com/goinnn/django-multiselectfield/commit/5638247c1d70670d4f81adf35143ef17a7d7575e>`_)
|
||
* In list_display, labels for the choices are now shown (comma-separated) instead of the values of the choices (comma-separated).
|
||
|
||
* In to_python method, value is a list or a string. (`c4579138dda2833cbce26afbf57da5353aa45690 <https://github.com/goinnn/django-multiselectfield/commit/c4579138dda2833cbce26afbf57da5353aa45690>`_)
|
||
|
||
* Remove set case and dict case
|
||
* If this breaks something, please create a test to help understand the use case.
|
||
|
||
* Removing integer choices:
|
||
|
||
* It was a mistake. MultiSelectField inherits of CharField, not IntegerField.
|
||
* It is impossible knows if original choice is (1, 'Item title 2.1') or ('1', 'Item title 2.1')
|
||
|
||
|
||
* Fix: Form instance generated twice since Django (`#168 <https://github.com/goinnn/django-multiselectfield/pull/168>`_)
|
||
|
||
* Fix CSS admin:
|
||
|
||
* (`#173 <https://github.com/goinnn/django-multiselectfield/pull/173>`_)
|
||
* (`7711f4aa755c81d00f07ce8a6ff0fd9240061f9c <https://github.com/goinnn/django-multiselectfield/commit/7711f4aa755c81d00f07ce8a6ff0fd9240061f9c>`_)
|
||
|
||
* Fix Properly Display Categorized Choices in get_FOO_display (`#169 <https://github.com/goinnn/django-multiselectfield/pull/169>`_)
|
||
|
||
* SortMultiSelectField: (`#172 <https://github.com/goinnn/django-multiselectfield/pull/172>`_)
|
||
|
||
* Documentation:
|
||
|
||
* How to add a filter to the Django administration:
|
||
|
||
* (`e36cbae4c3b39dac4a3fee03fdda9622a101f22d <https://github.com/goinnn/django-multiselectfield/commit/e36cbae4c3b39dac4a3fee03fdda9622a101f22d>`_)
|
||
* Inspired by (`#116 <https://github.com/goinnn/django-multiselectfield/issues/116>`_)
|
||
|
||
* How add a django multiselect field to list_display in Django administration
|
||
|
||
* (`5638247c1d70670d4f81adf35143ef17a7d7575e <https://github.com/goinnn/django-multiselectfield/commit/5638247c1d70670d4f81adf35143ef17a7d7575e>`_)
|
||
|
||
|
||
* How to add support for read-only fields in the Django administration:
|
||
|
||
* (`65376239ae7491414f896adb4d314349ff7c2667 <https://github.com/goinnn/django-multiselectfield/commit/65376239ae7491414f896adb4d314349ff7c2667>`_)
|
||
|
||
* Cleanup: Removed outdated code and updated compatibility:
|
||
|
||
* Updated syntax for the targeted Python and Django versions. (`#161 <https://github.com/goinnn/django-multiselectfield/pull/161>`_)
|
||
|
||
* Add pre-commit hooks (`#161 <https://github.com/goinnn/django-multiselectfield/pull/161>`_)
|
||
|
||
* Fixed GitHub Actions workflow.
|
||
|
||
* Removed Travis CI configuration.
|
||
|
||
* Fix Coveralls integrations
|
||
|
||
* Improved the README: clarified the correct versions of Python and Django.
|
||
|
||
|
||
Thanks to:
|
||
|
||
* `mikemanger <https://github.com/mikemanger>`_
|
||
* `piranhaphish <https://github.com/piranhaphish>`_
|
||
* `kunalgrover05 <https://github.com/kunalgrover05>`_
|
||
* `royatkup <https://github.com/royatkup>`_
|
||
* `qasimgulzar <https://github.com/qasimgulzar>`_
|
||
* `austin-schick <https://github.com/austin-schick>`_
|
||
* `Pfizer-BradleyBare <https://github.com/Pfizer-BradleyBare>`_
|
||
* `SuperSandro2000 <https://github.com/SuperSandro2000>`_
|
||
* `jucajuca <https://github.com/jucajuca>`_
|
||
* `filipefigcorreia <https://github.com/filipefigcorreia>`_
|
||
* `ZippoLag <https://github.com/ZippoLag>`_
|
||
* `leifdenby <https://github.com/leifdenby>`_
|
||
* `jordanvs <https://github.com/jordanvs>`_
|
||
* `hetdev <https://github.com/hetdev>`_
|
||
* `blag <https://github.com/blag>`_
|
||
|
||
Special thanks to:
|
||
|
||
* `ccalero <https://github.com/ccalero>`_ for fighting and updating django-multiselectfield
|
||
* `Joinup Green Intelligence <https://joinup.es>`_ for believing in free (libre) software
|
||
|
||
0.1.13 (2024-06-30)
|
||
-------------------
|
||
|
||
* Return MSFList instead of a plain list from form fields (`#118 <https://github.com/goinnn/django-multiselectfield/pull/118>`_, `#135 <https://github.com/goinnn/django-multiselectfield/pull/135>`_)
|
||
* Fix CI (`#122 <https://github.com/goinnn/django-multiselectfield/pull/122>`_, `#147 <https://github.com/goinnn/django-multiselectfield/pull/147>`_, `#148 <https://github.com/goinnn/django-multiselectfield/pull/148>`_, `#151 <https://github.com/goinnn/django-multiselectfield/pull/151>`_)
|
||
* Add ``min_choices`` to defaults when converting to form field (`#123 <https://github.com/goinnn/django-multiselectfield/pull/123>`_)
|
||
* Django 5.0 support and remove old compatibility (`#148 <https://github.com/goinnn/django-multiselectfield/pull/148>`_)
|
||
|
||
Thanks to:
|
||
|
||
* `tomasgarzon <https://github.com/tomasgarzon>`_
|
||
* `aleh-rymasheuski <https://github.com/aleh-rymasheuski>`_
|
||
* `nametkin <https://github.com/nametkin>`_
|
||
* `karolyi <https://github.com/karolyi>`_
|
||
* `olivierdalang <https://github.com/olivierdalang>`_
|
||
* `PetrDlouhy <https://github.com/PetrDlouhy>`_
|
||
|
||
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 <https://djangosnippets.org/snippets/1200/>`_
|