Select2 widget for django admin

Contents:

Installation

  1. install this package as usual, using python setup.py install, pip install django-easy-select2 or download sources and install to your python path.
  2. add easy_select2 to INSTALLED_APPS in your settings.py
  3. Use python manage.py collectstatic or manually copy easy_select2’s static directory to your project’s static directory (if you serve your static with nginx, for example).
  4. Modify your admin.py.
  5. Check out admin in browser.

Quickstart

In your admin.py:

from django.contrib import admin
from easy_select2 import select2_modelform
from polls.models import Poll

PollForm = select2_modelform(Poll, attrs={'width': '250px'})

class PollAdmin(admin.ModelAdmin):
    form = PollForm

Thats all. All your choice widgets are select2 widgets 250px wide.

Configuration

django-easy-select2 bundles jQuery and Select2 static files. You can use them, or specify your own files to include in widget.

To use bundled static, just install an application.

To use your custom static files, you can specify next settings in your settings.py:

  • SELECT2_JS - path to select2.js file. Specify path without static directory, because full URL will be interpolated using static function from staticfiles application. Default: easy_select2/vendor/select2/select2.min.js
  • SELECT2_CSS - path to select2.css file. Default: easy_select2/vendor/select2/select2.min.css
  • SELECT2_USE_BUNDLED_JQUERY - default is True. Set to False if you want to use jQuery of Django Admin, instead.
  • SELECT2_USE_BUNDLED_SELECT2 - default is True. Set to False if you want to use Select2 of Django Admin, instead.

Usage

There are Select2 and Select2Multiple widget classes for choice fields.

You can use Select2 and Select2Multiple on any form field, as usual django widget:

class Form(forms.Form):
    field = forms.ModelChoiceField(queryset=qs, widget=Select2())

or:

class Form(forms.Form):
    field = forms.ModelMultipleChoiceField(queryset=qs, widget=Select2Multiple(
        select2attrs={'width': 'auto'}
    ))

Select2 and Select2Multiple is simple classes build with Select2Mixin:

class Select2Multiple(Select2Mixin, forms.SelectMultiple):
    pass

class Select2(Select2Mixin, forms.Select):
    pass

Select2Mixin is a simple widget mixin with predefined Media class and custom render method, which applies $.fn.select2() method on html input.

Warning

Since version 1.2.9 select2attrs should be of type dict or AssertionError will be raised.

If you want to use it with all form fields automatically, without specifying each field, you can create your ModelForm class with Meta class constructed by custom Meta factory:

from easy_select2 import select2_modelform_meta

class SomeModelForm(forms.ModelForm):
    Meta = select2_modelform_meta(SomeModel)

select2_modelform_meta() is a simple factory, that produces a Meta class with model attribute set to specified model and widgets attribute set to dictionary, containing all selectable fields on model. Every selectable field will be converted from standard widget to Select2 or Select2Multiple widget.

If you are lazy, you can use ModelForm factory to build ready-to-use ModelForm for model with select2_modelform():

from easy_select2 import select2_modelform

MyModelForm = select2_modelform(MyModel)

is the same like:

class MyModelForm(forms.ModelForm):
    Meta = select2_modelform_meta(models.SomeModelForm)

You can also specify your base form class instead of default forms.ModelForm:

from easy_select2 import select2_modelform

MyModelForm = select2_modelform(MyModel, form_class=forms.ModelForm)

MyModelForm is an instance of ModelForm with model attribute set to MyModel, and appropriate Meta class.

There is also an apply_select2() function that dynamically creates new widget class mixed with Select2Mixin.

Usage, for example:

class SomeModelForm(admin.ModelForm):
    class Meta:
        widgets = {
            'field': apply_select2(forms.Select),
        }

So, apply_select2(forms.Select) will return new class, named Select2Select, mixed with Select2Mixin.

Reference

Widgets

class easy_select2.widgets.Select2(select2attrs=None, *args, **kwargs)[source]

Implement single-valued select widget with Select2.

class easy_select2.widgets.Select2Mixin(select2attrs=None, *args, **kwargs)[source]

This mixin provides a mechanism to construct custom widget class, that will be rendered using Select2 input.

Generally should be mixed with widgets that render select input.

get_options()[source]

Return dictionary of options to be used by Select2.

render(name, value, attrs=None, **kwargs)[source]

Extend base class’s render method by appending javascript inline text to html output.

render_js_code(id_, *args, **kwargs)[source]

Render html container for Select2 widget with options.

render_select2_options_code(options, id_)[source]

Render options for select2.

class easy_select2.widgets.Select2Multiple(select2attrs=None, *args, **kwargs)[source]

Implement multiple select widget with Select2.

Utils

easy_select2.utils.apply_select2(widget_cls)[source]

Dynamically create new widget class mixed with Select2Mixin.

Args:
widget_cls: class of source widget.

Usage, for example:

class SomeModelForm(admin.ModelForm):
    class Meta:
        widgets = {
            'field': apply_select2(forms.Select),
        }

So, apply_select2(forms.Select) will return new class, named Select2Select.

easy_select2.utils.select2_modelform(model, attrs=None, form_class=<class 'easy_select2.forms.FixedModelForm'>)[source]

Return ModelForm class for model with select2 widgets.

Arguments:
attrs: select2 widget attributes (width, for example) of type dict. form_class: modelform base class, forms.ModelForm by default.
SomeModelForm = select2_modelform(models.SomeModelBanner)

is the same like:

class SomeModelForm(forms.ModelForm):
    Meta = select2_modelform_meta(models.SomeModelForm)
easy_select2.utils.select2_modelform_meta(model, meta_fields=None, widgets=None, attrs=None, **kwargs)[source]

Return Meta class with Select2-enabled widgets for fields with choices (e.g. ForeignKey, CharField, etc) for use with ModelForm.

Arguments:

model - a model class to create Meta class for. meta_fields - dictionary with Meta class fields, for

example, {‘fields’: [‘id’, ‘name’]}
attrs - select2 widget attributes (width, for example),
must be of type dict.

**kwargs - will be merged with meta_fields.

Sampleproject

Sample project useful for testing django applications and other utility needs.

Installation

git clone https://github.com/asyncee/django-easy-select2.git
cd django-easy-select2/sampleproject
./bootstrap.sh  # creates virtualenv and installs django (from requirements.txt)
source env/bin/activate
./manage.py migrate
./manage.py createsuperuser
./manage.py runserver

Configuration

Project ships with sane defaults (settings are pretty verbose):

  • sqlite3 database
  • filebased cache in /tmp
  • cached sessions
  • console email backend
  • non-cached template loaders
  • css/js/img default static dirs
  • default templates directory
  • nice default loggers

Usage

After you bootstrapped a project, you can fill it with some data and play with Note model admin.

Changelog

Version ?.?.?

Bugs Fixed

  • setup.py: Drop leftover classifiers (#98)

Version 1.5.8

Bugs Fixed

  • setup.py: Stop installing package tests (#85)
  • Added Django 4.0 support (#86, #87, #88)

Enhancements

  • Update bundled Select2 to 4.0.13 (#65, #67)
  • Update bundled jQuery to 3.1.5 (#67)
  • Activate support for Python 3.8 (#69)
  • Drop dummy files of little value (#70)
  • Remove unused imports (#72)
  • Improve sample project (#73)
  • Support using Select2 assets of Django Admin (#74); this introduces a a new setting SELECT2_USE_BUNDLED_SELECT2. Default is True, set to False if you want to use Select2 of Django Admin.
  • Demo use outside of Django Admin (#76)
  • Bump Django from 2.2.10 to 2.2.25 in /sampleproject (#91)
  • Drop end-of-life Django 2.0/2.1/3.0 and Python 3.5/3.6 (#94, #95)

Infrastructure

  • Introduce pre-commit (#75)
  • Actions: Get off deprecated ::set-env (#78)
  • Actions: Make GitHub Dependabot keep our GitHub Actions up to date (#89)
  • Actions: Bump actions/setup-python from 1.1.1 to 2.3.1 (#90)
  • Improve pre-commit GitHub Action + enable cron mode (#92)
  • Execute tox on GitHub Actions rather than Travis CI (#93)
  • Actions: Restore coveralls (#96)
  • coveralls: Stop using discouraged --service=github (#97)

Version 1.5.7

  • Merged #64, thanks to leibowitz. Fixed situation when widget were not displayed on django 2.2+.

Version 1.5.6

  • Fixed #57, thanks to jaikanthjay46

Version 1.5.5

  • Fixed cascading issue-52 bug
  • Introducing django’s Jquery to easy-select2 for accessing django’s JQuery

Version 1.5.4

  • Work with jQuery instead of depending on $, thanks to leibowitz
  • Fixed a problem with django admin tabularinline (#52), thanks to leibowitz

Version 1.5.3

Warning

Version 1.5.3 changes, read below.

  • Fixed #50 (partly remaining bug in v 1.5.2) - 1st record addition fixed for “Doesn’t work for dynamically added forms in inline admins”
  • updated easy_select js to fail case when easy-select2.js[line#65]($(e.target).find(‘div.field-easy-select2:not([id*=”__prefix__”])’)) is not able to find elements while in DomNodeInserted corresponding to other node insertion than select2 widgets.

Version 1.5.2

Warning

Version 1.5.2 changes, read below.

  • Fixed #45 (remaining bug in v 1.5.0) - 1st record addition fixed for “Doesn’t work for dynamically added forms in inline admins”
  • updated easy_select js to handle DomNodeInserted Event for select2() dynamic initialization for all instances

Version 1.5.1

Warning

Version 1.5.1 changes, read below.

  • Fixed #45 - “Doesn’t work for dynamically added forms in inline admins”
  • updated easy_select js to handle DomNodeInserted Event for select2() dynamic initialization

Version 1.5.0

Warning

Version 1.5.0 major changes, read below.

  • Fixed #44 - “mark_safe problem”
  • Support for select2 constructor argument injection, within separate initialization block with for select2.
  • updated easy-select2 wrapper initialization. Updated to JQuery plugin code design for JS code injection, allowing direct injection of select2 constructor arguments.

Version 1.4.0

Warning

Version 1.4.0 introduced backward incompatible changes, read below.

  • Fixed #38 - “Related model combobox doesn’t update after add in Django 2”
  • Dropping support for Python 2.x
  • Django 2.0+ support. Demoapp updated to reflect the needed changes.
  • Python 3.x+ support (recommended Python3.4 and above)

Version 1.3.4

  • Django 1.11 support

Version 1.3.3

  • Fixed #29 — “Application breaks dumpdata command”

Version 1.3.2

  • Fixed #24, big thanks to Andrzej Mateja

Version 1.3.1

  • support for django staticfiles storage, thanks to martolini for idea

Version 1.3

Warning

Version 1.3 introduced backward incompatible changes, read below.

  • Select2 updated to 4.0.0
  • updated jQuery to 2.1.3
  • removed deprecated select2_meta_factory, Select2TextMixin and Select2TextInput.

Version 1.2

1.2.13

  • fixed issue #22, thanks to zeta83

1.2.12

  • fixed issue#2

1.2.11

  • fixed issue#15 - “RemovedInDjango18Warning”

1.2.10

  • fixed issue#14 - README.rst is not included in MANIFEST.in

1.2.9

  • fixed issue#12 “Inline relations: “Add another <Model>” breaks dropdown boxes”

Warning

Version 1.2.9 introduced backward incompatible change: select2attrs argument of Select2Mixin.__init__ must be of type dict

1.2.8

  • fixed incorrect instructions in help_text of ManyToMany fields #2, thanks to bashu.

1.2.7

  • setup.py fixes (issue #11), thanks to JensTimmerman.

1.2.6

  • Extended select2_modelform function with form_class argument to specify form base class explicitly (issue #10).

1.2.5

  • Fixed issue #9 “apply_select2 not imported in __init__” thanks to ocZio for bug report.

1.2.4

  • Fixed issue #6 “Select will not update selection after adding a new option”, thanks to ismaelbej for bug report.

1.2.3

  • Python 3.3 support, thanks to dzerrenner

1.2.2

  • Rendering select2attrs as unicode or json based on type

Now, if select2attrs is instance of basestring (str or unicode), it will be casted to unicode, else it will be turned to json string.

1.2.1

  • Extended package-level imports with Select2TextInput

1.2.0

  • added Select2TextInput, thanks to mkoistinen

Version 1.1

1.1.1

  • issue#1 fix (django-admin-sortable compatibility), thanks to @mkoistinen

Introduction

This is django application that brings select2 widget to select inputs in admin.

How it looks

Select one of existing values with single-valued choice field (ForeignKeyField, for example):

https://github.com/asyncee/django-easy-select2/raw/master/screenshots/select2_single.png

Easily select 1 or more “categories” for your project, you can also add a new one in the normal, Django-Admin manner by using the green + button with multiple-valued choice field (ManyToManyField):

https://github.com/asyncee/django-easy-select2/raw/master/screenshots/select2_multiple.png

Continue to Installation.

Indices and tables