Django-Select2: Select2 for Django

Select2

Select2 is an excellent Javascript framework which transforms mundane <select> fields to cool looking and searchable. This is a very handy when there are quite a number of options to select from.

Basic Select2 options field.

Select2 also allows dynamic fetching of options from server via Ajax. Select2’s webpage has a neat demo of this.

Select2 fetching data via Ajax. In the above screenshot it is using RottenTomatoes’ API to get them.

Django-Select2

Django includes basic select widget, which just generates <select><option>...</option>...</select> tags.  Although their ‘looks’ can be improved using basic CSS, but we hit a usability problem when there are too many options to select from. This is where Django-Select2 comes into picture.

Light Components

Django-Select2 includes many widgets suited to various use-cases. Select2Widget and Select2MultipleWidget widgets are suited for scenarios where we have a static list of choices which may not may not be large. They are not meant to be used when the options are too many, say, in thousands. This is because all those options would have to be pre-rendered onto the page and Javascript would be used to search through them. Said that, they are also one the most easiest to use. They are almost drop-in-replacement for Django’s default select widgets, and they look much much better.

Heavy Components

HeavySelect2Widget and HeavySelect2MultipleWidget widgets are suited for scenarios when the number of options are large and need complex queries (from maybe different data sources) to get the options. This dynamic fetching of options undoubtably requires Ajax communication with the server. Django-Select2 includes a helper JS file which is included automatically, so you need not worry about writing any Ajax related JS code. Although on the server side you do need to create a view specifically to respond to the queries. The format of the response is decided by the JS code being used on the client side. The included abstract view – Select2View, will make sure to format the response into the format expected by the helper JS code. Below is a example on how to use it.

#!python
from django.db.models import Q
from django_select2 import Select2View, NO_ERR_RESP
from .models import Employee

class EmployeeSelect2View(Select2View):
    def check_all_permissions(self, request, *args, **kwargs):
        user = request.user if not (user.is_authenticated() and user.has_perms('emp.view_employees')):
            raise PermissionDenied

    def get_results(self, request, term, page, context):
        emps = Employee.objects.filter( Q(first_name__icontains=term) | Q(last_name__icontains=term) | Q(emp_no__icontains=term))
        res = [ (emp.id, "%s %s" % (emp.first_name, emp.last_name),) for emp in emps ]
        return (NO_ERR_RESP, False, res) # Any error response, Has more results, options list

How many such views you will need depends totally on your use-case. From Django-Select2 there is no restriction on their reuse. If you feel that writing these views are too much of a hassle then you have an alternate option – sub-class AutoSelect2Field field. In your sub-classed field you need to override security_check(self, request, *args, **kwargs) and get_results(self, request, term, page, context) methods. When your field will be instantiated for the first time, it will register its own instance with AutoResponseView. When the related field is used in the browser, the queries would be directed to AutoResponseView which will direct it to your ‘auto’ field instance. For ‘auto’ fields to work you must use the following code in your urls.py to register the url for AutoResponseView.

#!python
urlpatterns += patterns("", url(r"^select2/", include("django_select2.urls")), )

Django-Select2 Fields

The following fields are available in Django-Select2.

  • Select2ChoiceField – Uses Select2Widget.
  • Select2MultipleChoiceField – Uses Select2MultipleWidget.
  • HeavySelect2ChoiceField – Uses HeavySelect2Widget.
  • HeavySelect2MultipleChoiceField – Uses HeavySelect2MultipleWidget.
  • ModelSelect2Field – Uses Select2ChoiceField. It additionally requires queryset argument. It similar to Django’s ModelChoiceField.
  • AutoSelect2Field – Uses HeavySelect2ChoiceField. Auto register’s itself with AutoResponseView.
  • AutoModelSelect2Field – Similar to AutoSelect2Field, but like ModelSelect2Field, normalizes values to Django model objects.

Download Django-Select2

You can download it or fork it from https://github.com/applegrew/django-select2. You can also add this to you pip requirement files as:-

-e git+https://github.com/applegrew/django-select2.git#egg=django-select2

Update: Now can simply add django_select2 to your pip requirement. If you want to install it manually then you can simply run:-

pip install django_select2

Update: Now you can install beta version of django_select2 compatible with Python3.

pip install Django-Select2-Py3

Closing Statement

It is recommended that you go through the codes to familiarize yourself with how to efficiently use Django-Select2. The code is not very complex so you should not face much problem in understanding it.


Posted

in

, , , , ,

by

Tags:

Comments

16 responses to “Django-Select2: Select2 for Django”

  1. Francisco Avatar
    Francisco

    Thanks for this great package! How can I give the field an initial value? Thanks

    1. Apple Grew Avatar

      Replied to your github issue.

      1. Smon Avatar
        Smon

        Had to apply some Google-Foo to find the mention github issue. So if others have the same Problem:
        https://github.com/applegrew/django-select2/issues/4

        Anyhow, thanks for the great work.

        1. Nirupam Biswas Avatar

          Thanks. Of late I get little time to spend on this project, so will appreciate all pull requests to fix its bugs and improve its documentation.

  2. James Avatar
    James

    Is there a simple way to use such widgets in the admin?

    1. Nirupam Biswas Avatar

      I am not sure if it will be simple, but if you want to use a custom widget in Admin then see https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_overrides for help. I would suggest that you use the Light fields as they are drop in replacements for their Django counterparts.

      1. Holger Karl Avatar
        Holger Karl

        Hi,

        The formfield_overrides does indeed work, in principle. E.g., add :

        formfield_overrides = {
        models.ManyToManyField: {‘widget’: Select2MultipleWidget}
        }

        to the corresponding ModelAdmin-derived class. (So I am a bit surprised by the answer on March 16, 2013?)

        However, what does not work is the automatic updating of the widget’s list of choices when the “green cross” is used to add a value.

        There is some info on a related stckexchange post: http://stackoverflow.com/questions/5744480/django-admin-relatedobjectlookups-how-does-it-refresh-and-set-the-select-on
        but that didnt get me any further.

        Is there any chance to get this javascript updated connected to the Select2 widget?

        Thanks a lot,

        Holger

  3. hackdan Avatar
    hackdan

    Super o_O!!! im new in django how is possible use it in django admin ?

    1. Nirupam Biswas Avatar

      Unfortunately no, not right now. One user has already filed one issue regarding this, but current design of admin site makes it very hard to solve.

  4. Hobbestigrou Avatar

    Hi,

    Thank you for your project is really handy. It is used in a project to my work, for managements tags. So now we use like this:

    tags = ModelSelect2MultipleField(queryset=Tag.objects, required=False)

    So it only works for existing tags, But it would be closer to the model stackoverflow and if the tag does not exist it adds, I found this link http://stackoverflow.com/questions/14229768/tagging-with-ajax-in-select2 which allows to manage side js, I’d like to know if there is an option in django-select2 to add it to the generated js. I would also like to know if instead of using the id it is possible to use a different field and side views in a get_form_kwargs I make a get_or_create.

    Thanks

      1. Nirupam Biswas Avatar

        This is actually on the TODO list – https://github.com/applegrew/django-select2/issues/33.

        Unfortunately I am unable to spend much time on this project. I would really appreciate if anyone could help me regarding this.

  5. Nosbielcs Avatar
    Nosbielcs

    You have a solution for inline models with django admin?

  6. Leandro Severino Avatar
    Leandro Severino

    heavy_data.js:134 Uncaught TypeError: e.select2 is not a function

    Any Idea ?

    1. Nirupam Biswas Avatar

      Please look for existing questions at https://github.com/applegrew/django-select2/issues. If not found then file an issue there.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.