Skip to content

How I use HeavySelect2MultipleWidget

Micha Hulsbosch edited this page Feb 25, 2021 · 1 revision

General info

A Django-select2 HeavySelect2 widget needs an Ajax based view that returns a list of results in JSON format when a user starts typing to search for things.

I this case the list contains combinations of two models: Person and PersonItemRelationRole (the role a person has played for an item (e.g. book), e.g. author, illustrator, publisher, owner, seller).

Note that the code below may not use the latest version of Django and Django-select2

The widget in the filter form

https://github.com/Mediate18/Mediate/blob/dd2f8b879cec25ce971899d42023afa20c4e2b53/items/filters.py#L245-L248

        widget=HeavySelect2MultipleWidget(
            attrs={'data-placeholder': "Select multiple"},
            data_view='personroleautoresponse'
        )

The personroleautoresponse path in urls.py

https://github.com/Mediate18/Mediate/blob/dd2f8b879cec25ce971899d42023afa20c4e2b53/items/urls.py#L231-L232

    path(r'personroleautoresponse', permission_required('global.view_all')(PersonAndRoleAutocompleteView.as_view()),
         name='personroleautoresponse'),

PersonAndRoleAutocompleteView

https://github.com/Mediate18/Mediate/blob/dd2f8b879cec25ce971899d42023afa20c4e2b53/items/views/views.py#L213-L242

class PersonAndRoleAutocompleteView(AutoResponseView):
    page_size = 10


    def get(self, request, *args, **kwargs):
        term = request.GET.get('term', '')
        page = int(request.GET.get('page', 1))
        begin = (page - 1) * self.page_size
        end = page * self.page_size
        person_query = Q(person__short_name__icontains=term)
        role_query = Q(role__name__icontains=term)


        person_item_relations = PersonItemRelation.objects.filter(person_query | role_query)\
                                    .values('person', 'person__short_name', 'role', 'role__name')\
                                    .distinct().order_by('person__short_name')[begin:end]


        more = True
        if len(person_item_relations) != self.page_size:
            more = False


        person_roles = [
            {
                'id': "{}|{}".format(rel['person'], rel['role']),
                'text': "{} - {}".format(rel['person__short_name'], rel['role__name'])
            }
            for rel in person_item_relations
        ]
        return JsonResponse({
            'results': person_roles,
            'more': more
        })
Clone this wiki locally