Giter Club home page Giter Club logo

django-select2's Introduction

django-select2's People

Contributors

annefly avatar apalazon avatar applegrew avatar bcail avatar bubenkoff avatar cleitondelima avatar codingjoe avatar crccheck avatar darbula avatar dependabot[bot] avatar emorozov avatar ewjoachim avatar fjcapdevila avatar geyser avatar graingert avatar hartwork avatar hotet avatar jieter avatar jsenecal avatar mardukbp avatar mfrasca avatar mociepka avatar predatell avatar pyup-bot avatar rizumu avatar scotteadams avatar stephane avatar superqwer avatar tisdall avatar vanschelven avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-select2's Issues

Support for to_field_name

Hello,

Describe the bug
ModelSelect2Widget is not compatible with/does not fully respect to_field_name attribute of ModelChoiceField.

Code Snippet

locality = django_filters.ModelChoiceFilter(
        label=_('Locality'),
        queryset=Locality.objects.all(),
        to_field_name='slug',
        widget=ModelSelect2Widget(
            model=Locality,
            queryset=Locality.objects.all(),
            search_fields=['title__icontains'],
            attrs={'data-minimum-input-length': 0}
        )
    )

To Reproduce
Steps to reproduce the behavior:

  1. I actually use django-filter to create form but the you can see the point
  2. use form field
  3. the autocomplete search works correctly, you can see fetched options in the select
  4. submit form
  5. the submitted value is not valid in the form, you can see the error message under the select "Select a valid choice. That choice is not one of the available choices."

It is because it expects "slug" from the "to_field_name" but get always "id" from AutoResponseView instead.

Expected behavior
to_field_name (slug in my case) should be sent as value and valid choice in the select is expected.

Screenshots
Current error state:
image

Expected:
image

Current fix:
My current workaround works with custom data_view which returns obj.slug instead of obj.pk:

class AutoSlugResponseView(AutoResponseView):
    def get(self, request, *args, **kwargs):
        """
        Return a :class:`.django.http.JsonResponse`.

        Example::

            {
                'results': [
                    {
                        'text': "foo",
                        'id': "bar"
                    }
                ],
                'more': true
            }

        """
        self.widget = self.get_widget_or_404()
        self.term = kwargs.get("term", request.GET.get("term", ""))
        self.object_list = self.get_queryset()
        context = self.get_context_data()
        return JsonResponse(
            {
                "results": [
                    {"text": self.widget.label_from_instance(obj), "id": obj.slug}
                    for obj in context["object_list"]
                ],
                "more": context["page_obj"].has_next(),
            }
        )

but I expect it to be automatic.

Thank you.

I cannot set a value to django-select2 ModelSelect2Widget using val() function

In my django app I have a CenterModel and a ProvinceModel, each center has a province_id field. I have define a form for Center using ModelSelect2Widget (django_select2) for province_id. I want to set the selected value to the province_id field in the template using javascript but the following code is not working:

$("#id_province_id").val(response.province_id)
$('#id_province_id').trigger('change'); 

but these lines are not working, they are NOT setting the value to the province_id field. Instead if the field has some previosly selected value the '.val()' funtion clears that value. I double checked and the response.province_id is storing a valid province id. Why I cannot set a value to the selct field? I am working with django-select2==7.7.1


class CenterModel(models.Model):

    name = models.CharField(verbose_name=_("Nombre"), max_length=50, unique=True,blank=False, null=False)

    province_id = models.ForeignKey("ProvinceModel", verbose_name=_("Provincia"),
                                                 blank=True, null=True, on_delete=models.SET_NULL,
                                                 related_name="centers")

    municipality_id = models.ForeignKey("MunicipalityModel", verbose_name=_("Municipio"),
                                                 blank=True, null=True, on_delete=models.SET_NULL,
                                                 related_name="centers")



   
from django_select2.forms import ModelSelect2Widget

class CenterForm(forms.ModelForm):

    class Meta:
        model = CenterModel
        exclude = ("id",)
        widgets = {
            'name':forms.TextInput(attrs={'class': 'form-control'}),
            'province_id' : ModelSelect2Widget(model=ProvinceModel, queryset=ProvinceModel.objects.filter(),
                                            search_fields=['des_prov__icontains'],
                                            attrs={'style': 'width: 100%;'}),
            'municipality_id' : ModelSelect2Widget(model=MunicipalityModel, queryset=MunicipalityModel.objects.filter(),
                                            search_fields=['municipio__icontains'],
                                            dependent_fields={'province_id': 'cod_prov'},
                                            attrs={'style': 'width: 100%;'}),
            }


Django-select2 doesn't work on inlineformset_factory?

Hi,

Thanks for sharing the project.

The select2 works perfectly on just a standalone model form but if its with inlineform, it doesn't work expected.
Is there an additional code (not coverred in the documention) for using Django-select2 for inlineform_factory?

Weird behaviour when generating a random id

Describe the bug
If I try to give a Select2Widget a random id using a generator function, the input's id is ok but the label's for attribute is generated with the function's name and memory address.

I don't even know if I'm doing something wrong, or if it's a django-select2 issue or a django issue.
Is this normal behaviour?

################### FORM
def generate_random_id():
    import random
    import string
    letters = string.ascii_lowercase
    return ''.join(random.choice(letters) for i in range(10))

class DestinationForm(forms.Form):
    destination = forms.ModelChoiceField(
        label="Destination", 
        queryset=City.objects.all().order_by('-population'),
        required=False,
        widget=BootstrapModelSelect2Widget(
            attrs={'style': 'width:100%', 'data-minimum-input-length': 2, 'data-placeholder': 'Enter your destination location', 'id': generate_random_id},
            queryset=City.objects.all().order_by('-population'),
            search_fields=['cityName__unaccent__icontains'],
            
    ))

################### WIDGET:

from django_select2.forms import ModelSelect2Widget
from django import forms

class BootstrapModelSelect2Widget(ModelSelect2Widget):
    def build_attrs(self, *args, **kwargs):
        attrs = super(BootstrapModelSelect2Widget, self).build_attrs(*args, **kwargs)
        attrs.setdefault('data-theme', 'bootstrap')
        return attrs

    @property
    def media(self):
        return super(BootstrapModelSelect2Widget, self).media + forms.Media(css={
            'screen': ('//cdnjs.cloudflare.com/ajax/libs/select2-bootstrap-theme/'
                       '0.1.0-beta.10/select2-bootstrap.min.css',)})



Screenshots
image

Empty Dropdown Using ModelSelect2Widget

Hello, thank you for the opensource, this is my first time using django-select2.

I don't know why my dropdown won't show anything. This is the frontend. I want those 4 fields chained. But they dont even show any data.
image'

Seems like I have similar problem like this issue. I've tried the solution but it doesn't work for me. If I remove the widgets=ModelSelect2Widget, my dropdown is populated with data from the DB, so I guess the problem lies with the ModelSelect2Widget. I use django-select2==7.4.2 and django==3.0.7

This is my forms.py

class FormSekolah(ModelForm):
          provinsi = ModelChoiceField(
                          queryset=Provinsi.objects.all(),
                          widget=ModelSelect2Widget(
                                              attrs={
                                                       'class': 'form-control form-control-sm',
                                                       'data-placeholder': '-- Pilih Provinsi --',
                                                       'data-minimum-input-length': 0
                                                },
                           model=Provinsi,
                           search_fields=['nama__icontains'],
                           dependent_fields={'kokab': 'cities'}
                           )
         )

        class Meta:
                  model = Sekolah
                  fields = [
                              # other field,
                              'provinsi',
                   ]

This is my models.py

class Provinsi(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    nama = models.CharField(max_length=50)
    negara = models.ForeignKey(Negara, on_delete=models.CASCADE, related_name="provinces")

    def __str__(self):
        return self.nama

Do I need to do something with my views.py (beside create and save forms and render to the html) or even create my own .js ?

Thanks before.

Include SELECT2_THEME settings

Discussed in #99

Originally posted by CleitonDeLima October 29, 2021
Select2 accepts themes, an example is bootstrap4.

To configure it, you need to include a new css file and add the theme option when starting select2.

<link rel="stylesheet" href="/path/to/select2.css">
<link rel="stylesheet" href="/path/to/select2-bootstrap4.min.css">
$('select').select2({
    theme: 'bootstrap4',
});

The settings could look like this:

# accept str too
SELECT2_CSS = (
    "/path/to/select2.css",
    "/path/to/select2-bootstrap4.min.css",
)
SELECT2_THEME = `"bootstrap4"`

I am willing to develop this option if it is valid.

chained select2, parent required

Goal
I want to use the chained select2 feature but it does not works fine.

Problem
Taking as example the below code snipped, the city field has to be populated according with country selection. However when country is null then the city is populated with data of all countries. Is it possible to make a child null when parent null?

Code Snippet
class AddressForm(forms.Form):
country = forms.ModelChoiceField(
queryset=Country.objects.all(),
label=u"Country",
widget=ModelSelect2Widget(
model=Country,
search_fields=['name__icontains'],
)
)

city = forms.ModelChoiceField(
    queryset=City.objects.all(),
    label=u"City",
    widget=ModelSelect2Widget(
        model=City,
        search_fields=['name__icontains'],
        dependent_fields={'country': 'country'},
        max_results=500,
    )
)

django-select2 $element.select2 is not a function in modal

Problem
Using django-select2 fields in Bootstrap modal (provided by django-bootstrap-modal-forms) I faced with issue that first time you open modal it can't initialize select2 inputs due to DOM is not ready.
Browser console log looks like

XHR finished loading: GET "http://localhost:7002/static/django_select2/django_select2.js".
XHR finished loading: GET "http://localhost:7002/documents/63/attach/".

jQuery.Deferred exception: $element.select2 is not a function TypeError: $element.select2 is not a function
    at initHeavy (<anonymous>:48:14)
    at HTMLSelectElement.<anonymous> (<anonymous>:56:9)
    at Function.each (https://code.jquery.com/jquery-3.5.1.min.js:2:2976)
    at S.fn.init.$.fn.djangoSelect2 (<anonymous>:53:7)
    at HTMLDocument.<anonymous> (<anonymous>:71:26)
    at e (https://code.jquery.com/jquery-3.5.1.min.js:2:30005)
    at t (https://code.jquery.com/jquery-3.5.1.min.js:2:30307) undefined

Uncaught TypeError: $element.select2 is not a function
    at initHeavy (<anonymous>:48:14)
    at HTMLSelectElement.<anonymous> (<anonymous>:56:9)
    at Function.each (jquery-3.5.1.min.js:2)
    at S.fn.init.$.fn.djangoSelect2 (<anonymous>:53:7)
    at HTMLDocument.<anonymous> (<anonymous>:71:26)
    at e (jquery-3.5.1.min.js:2)
    at t (jquery-3.5.1.min.js:2)

Code Snippet
Modal initiator (/documents/63) page

    <div class="modal fade" role="dialog" id="modal">
        <div class="modal-dialog modal-dialog-centered" role="document">
            <div class="modal-content"></div>
        </div>
    </div>

Modal content (/documents/63/attach/)

<form method="post" action="">
  {% csrf_token %}

 <div class="modal-header">
    <h5 class="modal-title">{{title}}</h5>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>

  <div class="modal-body">
    {% for field in form %}
      <div class="form-group{% if field.errors %} is-invalid{% endif %}">
        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
        {{ field }}
        {% for error in field.errors %}
          <p class="help-block">{{ error }}</p>
        {% endfor %}
      </div>
    {% endfor %}
  </div>

  <div class="modal-footer">
    <button type="button" class="btn btn-light" data-dismiss="modal">Close</button>
    <button type="submit" class="submit-btn btn btn-dark">Save</button>
  </div>

</form>

I assume the main issue that is django-select2 initialize inputs before it was loaded. I applied a workaround to re-initialize inputs in 100ms after the modal opens, it works correctly but I have an error in the console on each first modal open.

{{ form.media }}
<script>
$('#modal').ready(function() {
  setTimeout(() => {
    $('.django-select2').djangoSelect2({
        dropdownParent: $('#modal'),
        width: '100%'
    });
     }, 100);

});
</script>

Any suggestions to get it works correctly in the modal?

The results could not be loaded

Describe the bug
In some time after the page is opened and inactive (like 3-5 min) select2 fields going unworkable state.
This is happening on 3 different projects with various configurations. This is happening with all select2 fields regardless its configuration complexity.

Caching engine: django_redis
I'm really not sure what can be wrong and how to debug it, this looks like some kind of timeout but what timeout no idea.
Single debugging information on the ajax response screenshot.

UPDATE: I'd made a few more test and looks like it is happening
Exception & Traceback
image

image

To Reproduce
Steps to reproduce the behavior:

  1. Open page
  2. Wait for 3-5 mins

Switch to tail.select

little reminder to consider switching to tail.select as a more lightweight alternative to select2.

CHANGELOG

Hi @codingjoe ,

Thank you that you took the maintenance of the package.
A have a general question related to major upgrade.
We are using django-select2@6 and we want to upgrade to django-select2@7 (the latest version from PyPI) and I did not found any changelog file so we can do upgrade.

Can we have changelog for that package or maybe if you don't mind sharing some thoughts, ideas before we start to upgrade. At what we should pay attention to.

Thank you for your attention to this matter

Render Select2Widget as radio buttons

Goal
I need to render Select2Widget (choices) as radio buttons select.
Why I need this.
I have user type and dependent on it ModelSelect2Widget which rendered results need to be based on user type.

Problem
Have no idea how to render Select2Widget options as radio select. I tried to render it manually, but no success.

{% for pk, choice in form.type.field.widget.choices %}
    <div class="custom-control custom-radio custom-control-inline">
        <input id="id_{{form.type.name}}_{{ forloop.counter0 }}" name="{{form.type.name}}"
            type="{{form.type.field.widget.input_type}}" value="{{pk}}" class="custom-control-input" required
            {% ifequal form.type.data pk.0 %} checked="checked" {% endifequal %} />
        <label for="id_{{form.type.name}}_{{ forloop.counter0 }}" class="custom-control-label">{{ choice }}</label>
    </div>
    {% endfor %}

Code Snippet

class UserCreationForm(PopRequestMixin, CreateUpdateAjaxMixin, UserCreationForm):
    ...
    CHOICES = [(1, 'UserType1'), (2, 'UserType2')]
    type = forms.ChoiceField(
        choices=CHOICES, widget=s2forms.Select2Widget, initial='1')
        
       class Meta:
        model = User
        fields = ['email', 'name', 'type', 'organization', 'password1', 'password2']
        error_css_class = 'is-invalid'

        widgets = {
            "email": widgets.EmailInput(attrs={
                'class': 'form-control'
            }),

            "name": widgets.TextInput(attrs={
                'class': 'form-control'
            }),

            "organization": s2forms.ModelSelect2Widget(
                search_fields=["name__icontains",],
                dependent_fields={'type': 'type_id'},
                attrs={
                    'class': 'form-control'
                }),
        }

If I display fields as is - it is working correctly, but I need to change user type select to the radio buttons instead of select2 picker.
Thanks in advance.

Cache is hit but SQL still executed

Using the ModelSelect2Widget in a form and when I hit the dropdown multiple times, it hits the DB every time.

I am using redis cache and when I inspect it, the key is there.

In views.py

    def get_widget_or_404(self):
        ...
        try:
            key = signing.loads(field_id)
        except BadSignature:
            raise Http404('Invalid "field_id".')
        else:
            cache_key = "%s%s" % (settings.SELECT2_CACHE_PREFIX, key)
            widget_dict = cache.get(cache_key)
            if widget_dict is None:
                raise Http404("field_id not found")
            if widget_dict.pop("url") != self.request.path:
                raise Http404("field_id was issued for the view.")
        qs, qs.query = widget_dict.pop("queryset")
        self.queryset = qs.all()
        widget_dict["queryset"] = self.queryset
        widget_cls = widget_dict.pop("cls")
        return widget_cls(**widget_dict)

widget_dict is found. However, the db is hit every time on:
self.queryset = qs.all()

In settings.py:

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
    "select2": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
}
SELECT2_CACHE_BACKEND = "select2"

The controls works fine. The data is in the dropdown. Redis has the keys.
I checked the postgres logs and I see multiple SELECTS every time I hit the dropdown.

Am I setting something up wrong?

Any thoughts would be appreciated.

Thanks

Default cache timeout

Default cache TTL is 300s, but default django session is 2 weeks; user could want to have a page opened for almost 2 weeks but 5 minutes later he gets 404 responses only.
Does it make sense to set default timeout for select2 cache to a first explicitly declared timeout or to a default session age otherwise?
Kinda

if settings.SELECT2_CACHE_BACKEND:
    timeouts = [
        settings.get('CACHES', {}).get(settings.SELECT2_CACHE_BACKEND, {}).get('TIMEOUT'),
        settings.SESSION_COOKIE_AGE,
        60*60*24*7*2, # default 2 weeks https://docs.djangoproject.com/en/3.1/ref/settings/#session-cookie-age 
    ]
    default_timeout = list(filter(None, timeouts)).pop(0)

Also another question somehow linked to caching.
Curious about reasons behind using uuid for every widget instance instead of predictable hashing for a db field - 'database name + table name + column name' as a hash input for example.
Thus we don't need to use cache as an external consistent storage for uuids, because every django process can calculate this same field_id on its own.
Though it requires to whitelist somewhere (in settings?) select2-accessible db fields. What are the other downsides?

SELECT2_THEME setting is required in 7.9.0, witch breaks existing projects

Describe the bug
In new version, new setting SELECT2_THEME is required and raises error when not provided. This setting should have default value: default for backward compatibility.

Exception & Traceback
Revalent part of traceback:

/usr/local/lib/python3.8/site-packages/django_select2/forms.py:261: in build_attrs
    attrs = super().build_attrs(default_attrs, extra_attrs=extra_attrs)
/usr/local/lib/python3.8/site-packages/django_select2/forms.py:93: in build_attrs
    "data-theme": settings.SELECT2_THEME,
/usr/local/lib/python3.8/site-packages/django/conf/__init__.py:83: in __getattr__
    val = getattr(self._wrapped, name)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
self = <UserSettingsHolder>, name = 'SELECT2_THEME'
    def __getattr__(self, name):
        if not name.isupper() or name in self._deleted:
            raise AttributeError
>       return getattr(self.default_settings, name)
E       AttributeError: 'Settings' object has no attribute 'SELECT2_THEME'
/usr/local/lib/python3.8/site-packages/django/conf/__init__.py:239: AttributeError

To Reproduce
In test remove attribute SELECT2_THEME from settings. This mimics the behavior of project updating this library.

Hardcoded filter in multi-value dependend fields

I think, that is not good idea to hardcode filter used in dependent field to filter queryset

this line:

f"{model_field_name}__in": self.request.GET.getlist(

is adding this hardcoded filter __in

but in my use case i need another filter to be used - __has_any_keys to query postgress JSONField
so better will be to let user to choose kind of filter in widget initialization, instead of hardcode __in

How to prepopulate the selected choices in HeavySelect2MultipleWidget and ModelMultipleChoiceField

Goal
How to pre populate multiple selected choices in HeavySelect2MultipleWidget and in ModelMultipleChoiceField

Problem
When form reloaded with validation error, all the pre selected choices will vanish for HeavySelect2MultipleWidget, ModelMultipleChoiceField
also not finding a way to pre populate the selected choices when you load update form...

Code Snippet

class RequestRegion(forms.Form):
    region = forms.ModelMultipleChoiceField(queryset=Region.objects.all().order_by('region_id'),
                                            widget=Select2MultipleWidget)

class CustReqForm(forms.Form):

    #CustomerField(widget=CustomerHeavyWidget(data_view = 'customer_ajax', attrs={'data-minimum-input-length': 4, 'delay':200}))
    distributor = forms.CharField(
            widget=HeavySelect2MultipleWidget(data_view='customer_ajax',
                                              attrs={'data-minimum-input-length': 4, 'delay':200},
                                              ), required=False #queryset=Customer.objects.none()
    )

Setting the value of a ModelSelect2Widget with javascript is not working

In my django app I have a WorkerModel and a ProvinceModel, each worker has a province_id field. I have define a form for Worker using ModelSelect2Widget (django_select2) for province_id. I was trying to set a value to the province_id field with javascript but, is not working. I have tried with:
$('#id_province_id').val(province_id).trigger('change');

but is not working. It deletes the value of the field but it does not set the correct value. It only leaves it in blanck.Here is the defintion of my form

from django_select2.forms import ModelSelect2Widget
 class WorkerForm(forms.ModelForm):
     
     class Meta:
         model = WorkerModel
         exclude = ("id",)
         widgets = {
             'name':forms.TextInput(attrs={'class': 'form-control'}),
             'province_id' : ModelSelect2Widget(model=ProvinceModel, queryset=ProvinceModel.objects.filter(),
                                             search_fields=['des_prov__icontains'],
                                             attrs={'style': 'width: 100%;'}),

 }

in the template

 <script>
//on a button click a want to set the value of province_id
    $(document).ready(function () {
   
               $('#id_province_id').djangoSelect2({
                   placeholder: 'Seleccione una opción',
                   escapeMarkup: function (markup) { return markup; },
                   language: {
                       noResults: function () {
                           return "No se encuentran resultados.";
                       }
                   }
   
    });
               });
   </script>

Does not work with `to_field`

Hi @codingjoe, I faced an issue using to_field option in the model field. Form can't be validated at all.

class ModelA(models.Model):
    id = models.AutoField(primary_key=True)
    slug = models.CharField(max_length=4, unique=True)


class ModelB(models.Model):
    id = models.AutoField(primary_key=True)
    a_slug = models.ForeignKey(ModelA, verbose_name=_("Select A"), on_delete=models.CASCADE, to_field='slug')
    note = models.CharField(_("Note"), max_length=50)


class ModelAPickWidget(s2forms.ModelSelect2Widget):
    model = ModelA
    search_fields = [
        "slug__icontains",
    ]

    def label_from_instance(self, obj):
        return str(f'{obj.slug}')


class ModelBForm(ModelForm):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # self.fields['a_slug'].widget = ModelAPickWidget()
        # self.fields['a_slug'].widget.attrs['class'] = 'form-control'
        # self.fields['a_slug'].to_field_name = 'slug'
        # self.fields['a_slug'].queryset = ModelA.objects.all()

    class Meta:
        model = ModelB
        fields = ['a_slug', 'note', ]
        widgets = {
            "a_slug": ModelAPickWidget(attrs={
                'class': 'form-control',
            }),
            "note": widgets.TextInput(attrs={
                'class': 'form-control',
            }),
        }

If I going to disable ModelAPickWidget to use default Django's select widget it works and saves the form.

There is some debugging information.

  1. ModelSelect2Mixin in the optgroups method value is always pk
  2. ModelSelect2Mixin in the optgroups line
query = Q(**{"%s__in" % field_name: selected_choices})
print(query)
>>> (AND: ('slug__in', {'196'}))
  1. I tried to change
query = Q(**{"%s__in" % field_name: selected_choices})

to

query = Q(**{"%s__in" % 'pk': selected_choices})

And I got some success, form get failed validation on first submission but saves if I re-submit it again.

Form validation error raised by Django's ModelChoiceField in the to_python method

Select a valid choice. That choice is not one of the available choices.

because it gets pk value instead slug.

Many2Many Placeholder

$('.django-select2').djangoSelect2({placeholder: 'Select an option'});

Generate placeholder for foreignkey field. But not generated in many2many

I can't get select2 dependent fields work

I am trying to implement dependent select fields as shown in documents .

My models are shown here:


class VehicleBrand(BaseModel):
"""Brands for types of vehicles"""

name = models.CharField(_('Name'), max_length=50)

def __str__(self):
    return self.name


class VehicleModel(BaseModel):
"""vehicle model"""

brand = models.ForeignKey(
    'awesomeinventory.VehicleBrand',
    verbose_name=_('Brand of the vehicle'),
    on_delete=models.CASCADE,
    related_name='models',
)
name = models.CharField(_("Vehicle model name"), max_length=50)

def __str__(self):
    return self.name

My forms.py looks like:


class MarketTrackForm(forms.Form):
brand = forms.ModelChoiceField(
    queryset=VehicleBrand.objects.all(),
    to_field_name='name',
    label=u'Brand',
    widget=ModelSelect2Widget(
        model=VehicleBrand,
        search_fields=['name__icontains'],
        attrs={'style': 'width: 100%', 'data-minimum-input-length': 0},
    ),
)
model = forms.ModelChoiceField(
    queryset=VehicleModel.objects.all(),
    to_field_name='name',
    label=u'Model',
    widget=ModelSelect2Widget(
        model=VehicleModel,
        search_fields=['name__icontains'],
        dependent_fields={'brand': 'brand'},
        max_results=500,
        attrs={
            'style': 'width: 100%',
            'data-minimum-input-length': 0,
        },
    ),
)

my urls.py


urlpatterns += i18n_patterns(
...
path('select2/', include('django_select2.urls')),
...
)

and my settings looks like


...
    CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        },
    },
    'select2': {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        },
    },
}

# Set the cache backend to select2
SELECT2_CACHE_BACKEND = 'select2'
...

When I remove dependent fields everything works. Also I tried to copy exact example shown in documentation (country and city models) and even that didn't work. when I add dependent field, it just starts to say no results found(after selecting dependent field), If I remove dependent field from form it works. So I thought it could be about settings or caching. But couldnt figure it out. Any tips would help, thank you.

---update---
When I remove


kwargs.update(
    {
        f"{model_field_name}__in": filter(
            None, self.request.GET.get(f"{form_field_name}[]", "").split(",")
        )
        for form_field_name, model_field_name in self.widget.dependent_fields.items()
    }
)

This code from select2.views.AutoResponseView it just started to work. I dont want to mess with it tho. How could I fix it without removing this pile of code and what even this pile does? anyone?

How to add a few strings for like "Select all"?

Goal
To get an entry "Select all" in the search.

Problem
I have around 20 million rows in table. The Admin wants to send mail to some specific or to all users. Now he may type a phrase to search for a user or he may want to send the mail to all users. If he wants to send mail to all the users it would just be sufficient for him to select "Select all" from the field.

Code Snippet
Please provide a code snippet of your problem.



class UsersWidget(s2forms.ModelSelect2MultipleWidget):
    search_fields = [
        "email__istartswith",
        "PAN_ID__istartswith",
        "full_name__istartswith",
    ]
    empty_label = "Select all"

    def label_from_instance(self, obj):
        return obj.email

    def filter_queryset(self, request, term, queryset=None, **dependent_fields):

        return super.filter_queryset(request, term, queryset, **dependent_fields)


class MailForm(forms.Form):
    to = forms.ModelMultipleChoiceField(
        label="To",
        queryset=User.objects.all(),
        widget=UsersWidget,
    )

    subject = forms.CharField(max_length=78)
    content = QuillFormField()
    fileupload = forms.FileField()

image

A badge of this kind with text as "Select all" is required.

image

Insufficient input validation/error handling of form data

Describe the bug
django-select2 does not validate the provided form data properly, so users can trigger an internal server error. The bug seems to be located in the method optgroups of the class ModelSelect2Mixin, where a a database query is built based on the form data (line 471/472). If the form data does not have the expected data type (like string instead of an integer), Django raises a ValueError which is not properly handled.

Exception & Traceback
From the example app:

  Environment:
  
  
  Request Method: POST
  Request URL: http://localhost:8000/
  
  Django Version: 3.2.6
  Python Version: 3.9.2
  Installed Applications:
  ['django.contrib.admin',
   'django.contrib.auth',
   'django.contrib.contenttypes',
   'django.contrib.sessions',
   'django.contrib.messages',
   'django.contrib.staticfiles',
   'django_select2',
   'example']
  Installed Middleware:
  ['django.middleware.security.SecurityMiddleware',
   'django.contrib.sessions.middleware.SessionMiddleware',
   'django.middleware.common.CommonMiddleware',
   'django.middleware.csrf.CsrfViewMiddleware',
   'django.contrib.auth.middleware.AuthenticationMiddleware',
   'django.contrib.messages.middleware.MessageMiddleware',
   'django.middleware.clickjacking.XFrameOptionsMiddleware']
  
  
  Template error:
  In template /home/.../django-select2/example/example/templates/example/book_form.html, error at line 14
     Field 'id' expected a number but got 'test'.
     4 :     <title>Create Book</title>
     5 :     {{ form.media.css }}
     6 :     <style>
     7 :         input, select {width: 100%}
     8 :     </style>
     9 : </head>
     10 : <body>
     11 :     <h1>Create a new Book</h1>
     12 :     <form method="POST">
     13 :         {% csrf_token %}
     14 :          {{ form.as_p }} 
     15 :         <input type="submit">
     16 :     </form>
     17 :     <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
     18 :     {{ form.media.js }}
     19 : </body>
     20 : </html>
     21 : 
  
  Traceback (most recent call last):
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/fields/__init__.py", line 1823, in get_prep_value
      return int(value)
  
  The above exception (invalid literal for int() with base 10: 'test') was the direct cause of the following exception:
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
      response = get_response(request)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 204, in _get_response
      response = response.render()
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/template/response.py", line 105, in render
      self.content = self.rendered_content
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/template/response.py", line 83, in rendered_content
      return template.render(context, self._request)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/template/backends/django.py", line 61, in render
      return self.template.render(context)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/template/base.py", line 170, in render
      return self._render(context)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/template/base.py", line 162, in _render
      return self.nodelist.render(context)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/template/base.py", line 938, in render
      bit = node.render_annotated(context)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
      return self.render(context)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/template/base.py", line 988, in render
      output = self.filter_expression.resolve(context)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/template/base.py", line 671, in resolve
      obj = self.var.resolve(context)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/template/base.py", line 796, in resolve
      value = self._resolve_lookup(context)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/template/base.py", line 858, in _resolve_lookup
      current = current()
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/forms/forms.py", line 290, in as_p
      return self._html_output(
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/forms/forms.py", line 227, in _html_output
      output.append(normal_row % {
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/utils/html.py", line 376, in <lambda>
      klass.__str__ = lambda self: mark_safe(klass_str(self))
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/forms/boundfield.py", line 34, in __str__
      return self.as_widget()
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/forms/boundfield.py", line 93, in as_widget
      return widget.render(
    File "/home/.../django-select2/django_select2/forms.py", line 264, in render
      output = super().render(*args, **kwargs)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/forms/widgets.py", line 246, in render
      context = self.get_context(name, value, attrs)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/forms/widgets.py", line 683, in get_context
      context = super().get_context(name, value, attrs)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/forms/widgets.py", line 644, in get_context
      context['widget']['optgroups'] = self.optgroups(name, context['widget']['value'], attrs)
    File "/home/.../django-select2/django_select2/forms.py", line 472, in optgroups
      for obj in self.choices.queryset.filter(query):
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/query.py", line 941, in filter
      return self._filter_or_exclude(False, args, kwargs)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/query.py", line 961, in _filter_or_exclude
      clone._filter_or_exclude_inplace(negate, args, kwargs)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/query.py", line 968, in _filter_or_exclude_inplace
      self._query.add_q(Q(*args, **kwargs))
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1393, in add_q
      clause, _ = self._add_q(q_object, self.used_aliases)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1412, in _add_q
      child_clause, needed_inner = self.build_filter(
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1265, in build_filter
      return self._add_q(
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1412, in _add_q
      child_clause, needed_inner = self.build_filter(
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1347, in build_filter
      condition = self.build_lookup(lookups, col, value)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1193, in build_lookup
      lookup = lookup_class(lhs, rhs)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/lookups.py", line 25, in __init__
      self.rhs = self.get_prep_lookup()
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/lookups.py", line 240, in get_prep_lookup
      rhs_value = self.lhs.output_field.get_prep_value(rhs_value)
    File "/home/.../django-select2/example/venv/lib/python3.9/site-packages/django/db/models/fields/__init__.py", line 1825, in get_prep_value
      raise e.__class__(
  
  Exception Type: ValueError at /
  Exception Value: Field 'id' expected a number but got 'test'.

Code Snippet
The example app can be used to reproduce the error.

To Reproduce
This screenshot shows an exemplarily HTTP request, that triggers the internal server error:
grafik
A primary key (integer) would be expected here, but a string is provided.

Expected behavior
Invalid data should be handled properly in the widget.

Django validates the data later on while cleaning the form. When removing the django-select2 widget, it works as expected:
grafik

I assume that handling the ValueError exception is sufficient here, but I am not familiar with the django-select2 code.

Example for ModelSelect2MultipleWidget dependent_fields

Goal
Given multiple countries selected in a parent ModelSelect2MultipleWidget, display all cities within the aforementioned countries in a child ModelSelect2MultipleWidget.

Problem
I am not sure how to do this given the examples. Does the package support this feature? If not, can you point out the major steps that I would need to do in order to implement this functionality?

Code Snippet

models.py

class Country(models.Model):
    name = models.CharField(max_length=255)

class City(models.Model):
    name = models.CharField(max_length=255)
    country = models.ForeignKey('Country', related_name="cities")

forms.py

class InterestingCities(forms.Form):
    countries = forms.ModelChoiceField(
        label = "Countries",
        widget = ModelSelect2MultipleWidget(
            model = Country,
            search_fields = ['name__icontains'],
        ),
        queryset = Country.objects.all(),
    )
    
    cities = forms.ModelChoiceField(
        label = "Cities",
        widget = ModelSelect2MultipleWidget(
            model = City,
            search_fields = ['name__icontains'],
            dependent_fields = {'country': 'country'}, # What should this line be? Is this the only thing that needs to change?
            max_results = 500,
        ),
        queryset = City.objects.all(),
    )

'djangoSelect2 is not a function' error, although fields already initialized with it successfully

Goal
Using formsets that include field widgets using django 3.1.2 and django-select2 7.4.2. Trying to implement an "Add Another" functionality. Inquiring if I am missing some understanding of manual initialization of django-select2.

Problem
Cloning the form rows is done. Have not been successful manually initializing django-select2 for new rows. Attempting to use django-select2 via the jquery plugin

$('.django-select2').djangoSelect2();

method as specified in the documentation triggers the error djangoSelect2 is not a function, even though:

  • there are on same page fields already rendered and successfully working that have been instantiated at page load using djangoSelect2
  • both jquery-3.5.1.min.js and django-select2.js appear in ChromeDevTools sources tab
  • {{form.media.js}} and {{formset.media.js}} are included on template
  • no other errors are reported in the console

My understanding is that the reported error should only occur if jquery or django-select2 were not installed. What would you suggest I look into to resolve?

Code Snippets

  $("#add-row").click(function (e) {
    e.preventDefault();
    let prefix = "lines"
    let totalForms = `#id_${prefix}-TOTAL_FORMS`
    let formIndex  = parseInt($(totalForms).val());
    var newRow = $("#form-template").clone()
    newRow.removeAttr("id")
    reindexForm(newRow, formIndex);
    $(totalForms).val(formIndex + 1)
    newRow.appendTo('#target').removeClass("d-none")
    $('.django-select2').djangoSelect2()
  });

Use minimumInputLength to not require search

Hi, I'm attempting to integrate django-select2 into my django page for a select box that has very few items. Because of this, I wish to show all the items without having to enter something into the search box.

With the normal select2 lib, I understood it can be done using options 'minimumInputLength' and 'minimumResultsForSearch', but with django-select2 I cannot get it to work. Where should I use these options with this library, or if not supported, how can I achieve the described behaviour?

Here is my sample

# forms.py
class MySubObjectWidget(s2forms.ModelSelect2MultipleWidget):
    search_fields = [
        "name__icontains",
    ]

class MyForm(forms.ModelForm):
    class Meta:
        model = models.Object1
        fields = "__all__"

        widgets = {
            "subObjectList": MySubObjectWidget(),
        }

# views.py
class Object1CreateView(CreateView):
    model = Object1
    form_class = forms.MyForm
    success_url = "/"

Thanks.

Search behavior after update

Describe the bug

Obs: I'm not sure between bug or new feature

After #26, the search behavior has changed from AND to OR on splited terms. In my opinion, this behavior is incorrect because when I add two words to the search I would like both to be in the result query. I’ve been using __icontains on the widgets until then to achieve the goal of bringing results that include all the searched words, but now it is not working the same way.

But I also agree that there may be situations where OR is preferred. Is there a possibility to implement the choice between the two forms(AND | OR) of quering? Or how could I do to have the previous AND behavior (here) with the newest version of the app?

{{form.media.*}} return None on Django 3.1.*

I work with django 3.1.* + python 3.8
I have correctly follow all steps on get started tutorial
but when i try to render form django-select2 not render js and css file
In my template i have try {{form.media.js}} and {{form.media.css}} nothing done !
I have try {{form.media.render_js}} and {{form.media.render_css}} i get empty list

I want to know please what i missing...

Only related objects to the last selected object of the dependent are loaded

Describe the bug
Okay, lets say I have a first multiple select widget called: base_select and a second multiple select widget dependent_select. The dependent_select widget should display it's content based on the selection of the base_select widget.

Now when I have selected two items of the base_select only the related objects of one of these items are displayed in the dependent_select.

Expected behavior
The dependent_select should show all related items of all the selected items of the base_select

Duplicated select2 input when rendering

Looking at so many uncommented issues makes me not very hoping of fixing it anytime soon, but I'm facing a problem that I can't seem to figure out. The select2 input is rendered twice, I get two search fields, specifically
two of these:

<span class="select2 select2-container select2-container--default" dir="ltr" data-select2-id="1" style="width: 100%;"><span class="selection"><span class="select2-selection select2-selection--single" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="-1" aria-disabled="false" aria-labelledby="select2-id_form-0-producto-container"><span class="select2-selection__rendered" id="select2-id_form-0-producto-container" role="textbox" aria-readonly="true"><span class="select2-selection__placeholder">Busque productos</span></span><span class="select2-selection__arrow" role="presentation"><b role="presentation"></b></span></span></span><span class="dropdown-wrapper" aria-hidden="true"></span></span>

Captura de pantalla de 2020-10-30 11-14-35

This is my django code:

models.py
class Producto(models.Model):

    nombre_amistoso = models.CharField(
        max_length=40,
        help_text=_('Nombre amigable del producto.')
    )
    nombre_fabricante = models.CharField(
        max_length=60,
        help_text=_(
            'Nombre real del producto, tal como lo conoce el fabricante.'
        )
    )
    fabricante = models.ForeignKey(
        'Fabricante',
        on_delete=models.SET_NULL,
        blank=True,
        null=True
    )
    referencia = models.CharField(
        max_length=25,
        help_text=_('Referencia del fabricante.')
    )

forms.py
class ProductoWidget(s2forms.ModelSelect2Widget):
    """ Widget especial creado con libreria django-select2.
    Busca según los campos especificados en serach_fields. """

    search_fields = [
        "nombre_amistoso__icontains",
        "nombre_fabricante__icontains",
        "referencia__icontains",
    ]


class ArticuloForm(forms.ModelForm):
    """ Este formulario se utiliza para agregar articulos a la pizarra. """

    class Meta:
        model = Articulo
        fields = ['producto', 'unidades']
        widgets = {
            "producto": ProductoWidget(
                {'data-language': 'es',
                 'data-placeholder': 'Busque productos',
                 'data-width': '100%',
                 }
            ),
        }

views.py

def NuevaNota(request):
    ArticuloFormset = formset_factory(ArticuloForm)
    if request.method == "POST":
    # bunch of code

    else:
        articulos = ArticuloFormset()
        nota = NotaForm()
        context = {
            'articulos': articulos,
            'nota': nota
        }
        return render(request, "gestion/anotar.html", context)

The inputs work perfectly, they search in the fields they have to. Only they render in duplicate.
Also, the data-language attribute seems to not be taking any effect (still in english).

I hope @codingjoe can take a look at the open issues anytime soon.
Thanks a lot for taking over, let me know If I can be helpful in any manner, I'd love to.
J.

update: I add also the html template.

base_generic.html

  <head>
    {% load static %}
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Favicon -->
    <link rel="icon" href="{% static '/img/favicon.ico' %}">
    <!-- CSS links -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
          integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2"
          crossorigin="anonymous">
    <!-- Iconos FontAwesome -->
    <link rel="stylesheet" type="text/css" href="{% static 'gestion/css/styles.css' %}">
    {% block extracss %}{% endblock %}
    <script src="https://kit.fontawesome.com/434ec950ab.js" crossorigin="anonymous"></script>
    <!-- - -->
    <title>{% block titulo %}Gestión de pedidos TERSTEM{% endblock %}</title>
  </head>
  <body>
    ...
    <!-- JS Scripts -->
    {% block jquery %}
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
            integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
            crossorigin="anonymous"></script>
    {% endblock %}
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx"
            crossorigin="anonymous"></script>
    {% block extrajs %}{% endblock %}
    <!-- - -->
  </body>

anotar.html

{% extends "base_generic.html" %}
{% block extracss %}
  {{ articulos.media.css}}
{% endblock %}
{% block titulo %}Nueva nota | PEDIDOS TERSTEM{% endblock %}

{% block contenido %}
<form>
  {% csrf_token %}
    {{ articulos.management_form }}
  <div class="form-group">
    {% for articulo in articulos %}
        {{ articulo.as_p }}
    {% endfor %}
  </div>
  <div class="form-group">
    {{ nota.entrega }}
  </div>
</form>
{% block jquery %}
  <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
{% endblock %}
{% block extrajs %}
  {{ articulos.media.js }}
{% endblock %}
{% endblock %}

Tests missing in sdist

Please include tests in the source tarball, they are needed for debian packaging of select2.

Clearing value of dependent fields

Clearing value of dependent fields not working for multiple dependent fields

for me this selector will not match if there are multiple field names

$('[data-select2-dependent-fields=' + name + ']').each(function () {
          $(this).val('').trigger('change')
})

what is working for me is to change it like this

$("[data-select2-dependent-fields~='" + name + "']").each(function () {
          $(this).val('').trigger('change')
})

Django select2 field in pure html in modal with already used field_id

Goal
I am trying to make select2 work in pure html in a modal.

Problem
I have a workaround by using another field_id from another form. Is this the right way? Do I need to create a field_Id for each select2 field?

Code Snippet
Please provide a code snippet of your problem:

            <div class="form-group" >
               <label for="id_filecategory" class="">
               Filecategory
               </label>
               <div class="">
                  <div class="input-group">
                     <select name="filecategory" data-minimum-input-length="0" data-allow-clear="true" data-placeholder="---------" data-ajax--url="/select2/fields/auto.json?field_id=Mjc5NDMxNzU1OTM0NA%3A1lEEm5%3AK_HUKQUF1aEwQZZGHySFs6tbuzc" data-ajax--cache="true" data-ajax--type="GET" class="modelselect2widget form-control django-select2 django-select2-heavy" id="id_filecategory">
                        <option value=" " selected></option>
                     </select>
                     <span class="input-group-append"><button  class="btn btn-danger" onClick="window.open(&#39;/filecategory/new&#39;, &#39;_blank&#39;, &#39;width=1000,height=600,menubar=no,toolbar=no&#39;);" type="button">+</button>
                     </span>
                  </div>
               </div>
            </div>

Configurable clearing of dependent fields

it would be nice to have configurable clearing of dependent field on various events

by now only select event is clearing dependent fields

$element.on('select2:select', function (e) {

in my use case i need to clear also on unselect and clear events
so i added code

      $element.on('select2:clear', function (e) {
        var name = $(e.currentTarget).attr('name')
        $("[data-select2-dependent-fields~='" + name + "']").each(function () {
          $(this).val('').trigger('change')
        })
      })
      $element.on('select2:unselect', function (e) {
        var name = $(e.currentTarget).attr('name')
        $("[data-select2-dependent-fields~='" + name + "']").each(function () {
          $(this).val('').trigger('change')
        })
      })

but probably better is to have this some how configurable
for example by adding to django settings something like

SELECT2_CLEAR_ON_EVENTS = ('select', 'clear', 'unselect')

formset issue with django-select2

hi @codingjoe, i would love your assistance as well. i am also trying to implement select2 with this package django_select2 via formsets
but select2 field is not rendering and nothing is throwing errors. i have installed django_select2, added it to my url root config, installed redis-server and django-redis via pip, and set up the caches in the settings.py. i have init for jquery via apps.js ( this is for the external dependencies section )
i must note that {{form.media.js and form.media.css }} load nothing for me and i do not have a context name for the view its all named form

here is a sample of my code
template

<div class="col-md-8">
  <div class="card">


      <div>
      </div>
      <div>

          <form class="card-box" method="POST">
              {% csrf_token %}
              {{ formset.management_form }}
              {% for form in formset %}
              <div class="row form-row spacer">


                  <!-- form variable -->
                  {{ form.as_p }}
                  <div class="input-group-append">
                      <button class="btn btn-success add-form-row">+</button>

                  </div>
              </div>
              {% endfor %}
            <input class="btn btn-primary" type="submit" name="submit" value="Submit">
              <br>

          </form>
       <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
          {{ form.media.js }}




      </div>
  </div>

forms.py

class ItemS2Widget(s2forms.ModelSelect2Widget):
          search_fields = [
              "names__icontains",
          ]

class RequisitionItemForm(forms.ModelForm):
    class Meta:
        model = RequisitionItem
        fields = ('item', 'requested_quantity', 'requisition')
        widgets = {'requisition': HiddenInput, 'item': ItemS2Widget()}

also i am using django 3.1 and python 3.6
any assistance will be greatly appreciated

How to set value to django-select2 field Programmatically (on button click) using javascipt?

Goal
In my django app I have a WorkerModel and a ProvinceModel, each worker has a province_id field. I have define a form for Worker using ModelSelect2Widget (django_select2) for province_id. I want to know how to set a value to province_id field using javascript. The idea is that when a button is clicked we make an ajax request getting the id and name of the province and I want to set the value of province_id to the province id I just got

Code Snippet

from django_select2.forms import ModelSelect2Widget
class WorkerForm(forms.ModelForm):
    
    class Meta:
        model = WorkerModel
        exclude = ("id",)
        widgets = {
            'name':forms.TextInput(attrs={'class': 'form-control'}),
            'province_id' : ModelSelect2Widget(model=ProvinceModel, queryset=ProvinceModel.objects.filter(),
                                            search_fields=['des_prov__icontains'],
                                            attrs={'style': 'width: 100%;'}),

}

in the template

    <script>
//on a button click a want to set the value of province_id
     $(document).ready(function () {
    
                $('#id_province_id').djangoSelect2({
                    placeholder: 'Seleccione una opción',
                    escapeMarkup: function (markup) { return markup; },
                    language: {
                        noResults: function () {
                            return "No se encuentran resultados.";
                        }
                    }
    
     });
                });
    </script>

Simple Problem - Creating interdependent dropdowns using Select2 and Django-filter

Goal
I have one model called Car. My aim is to create two dropdowns for 'make and 'model' fields for which the dropdown choices are distinct and interdependent between each other. When one choice is made then the other will filter its possible choices respectively (interdependent).

Problem
I am very much a novice to Django and Select2, so forgive me if the answer is obvious but I have been struggling for some time now. I cannot seem to render a form that shows any fields. This may also be an issue with my html code so it would be great to know how to show this effectively in html.

Code Snippet

                        import django_filters
                        from.models import Car
                        from django_select2 import forms as s2forms
                        from django_select2.forms import Select2Widget
                        from django_select2.forms import ModelSelect2Widget
                          
                          
                          
                        
                        class MyWidget (s2forms.ModelSelect2Widget):
                        
                            search_fields = [
                                'make__icontains','model__icontains',
                        
                            ]





                        class CarFilter (django_filters.FilterSet):
                          make = django_filters.ModelChoiceFilter(queryset=Car.objects.values('make').distinct(), widget=MyWidget)
                          model = django_filters.ModelChoiceFilter(queryset=Car.objects.values('model').distinct(), widget=MyWidget)
                        
                            class Meta:
                                model = Car
                                fields = ['make','model']

my views.py

                          from django.shortcuts import render
                          from .models import Car
                          from django.db.models import Count
                          from .filters import CarFilter
                          
                          def index(request):
                              all = Car.objects.all()
                              myFilter = CarFilter(request.GET, queryset=all)
                              all = myFilter.qs

                          context = {
                         
                              'all': all,
                              'myFilter' :myFilter,
                      
                          }
                      
                      
                          return render(request, 'index.html', context)

my html

                      <form method="get" action="">
                        <div class="col-md-3 col-sm-4">
                            <select class="selectpicker topsearch" data-width="100%" >
                                <option value = {{ myFilter.form.make  }}></option>
                            </select>
                            <select class="selectpicker topsearch" data-width="100%" >
                                <option value = {{ myFilter.form.model }}></option>
                            </select>
                        </div>
                      </form>

Any help would be greatly appreciated! thank-you

Add id to html so javascript can be easely used.

Select2 can be used in combination with javascript to return the value(s) selected.
In html id is used to bind event listeners, for instance populate other fields upon change.

  $('#id_reference').change(function(){
    alert($(this).val());
    console.log("id_reference changed")
  })

  $('#reference').change(function(){
    alert($(this).val());
    console.log("reference changed")
  })

It is unclear what the id is from the django_select2 components since this is generated dynamically.

When a model is defined

Class Product(models.Model):
    reference = models.CharField(null=True, blank=True, max_length=100)
    description = models.TextField(null=True, blank=True)
....

The reference is a s2forms.ModelSelect2Widget component and upon selection this should fill up the description filed (this is ajax query to other refecence)

In order to perform this a clear view is needed on the generated id so function like below can be used.

  $('#id_reference').change(function(){
    alert($(this).val());
    console.log("id_reference changed")
  })

  $('#reference').change(function(){
    alert($(this).val());
    console.log("reference changed")
  })

changed behaviour for __contains queries and multiple words in search-term

I'm creating this as a bug, while of course this could be also an intentional (breaking) change to the library. If that's the case I would work around it.

Beginning with version 7.6.0 there was a change in search behaviour, originating in in this commit.

The example is

  • search_fields = {'title__icontains'} and
  • using ModelSelect2Widget as base for the widget

Now I'm searching for two separate words.

The old behavior (7.5.0 and earlier) was that both words needed to be in the title, so the term was split into the words, while combining the resulting two __icontains searches with AND. So in the result for the selectbox we only get the records which contain both words in the title.

New behaviour since 7.6.0 is different, here we also split, but the searches are combined with OR.
So in the result we have all records that have either one OR the other word in the title

Expected behavior
I would have expected the search-results to be the same. While I understand the breaking change in the release, I don't see why this specific behaviour was changed.

When we take the default django-admin-search as an example (also the base for autocomplete_fields), we find:

https://github.com/django/django/blob/3668da8de821fcb4ddd83fb50a1f04aa02600894/django/contrib/admin/options.py#L1020-L1030

        use_distinct = False
        search_fields = self.get_search_fields(request)
        if search_fields and search_term:
            orm_lookups = [construct_search(str(search_field))
                           for search_field in search_fields]
            for bit in search_term.split():
                or_queries = [models.Q(**{orm_lookup: bit})
                              for orm_lookup in orm_lookups]
                queryset = queryset.filter(reduce(operator.or_, or_queries))
            use_distinct |= any(lookup_needs_distinct(self.opts, search_spec) for search_spec in orm_lookups)

Which means, django admin also does:

  • use OR for connecting the searches by field,
  • but is uses AND for the search for multiple words in the search-term.

possible solution

If you see this also as a bug, I'm happy to work on a fix for it. Otherwise I would try to work around this behaviour.

How to pass object into the Widget

Goal
I want to pass an object or variable to the ModelSelect2MultipleWidget to perform filter_queryset according this object.

Problem
I tried to pass object into the widget and catch it in the __init__, it is seems worked but only on field initialization, on search requests self.service going to None.

Code Snippet

class PricingPickWidget(s2forms.ModelSelect2MultipleWidget):
    search_fields = [
        "name__icontains",
    ]
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.service = kwargs.pop('service', None) # <- Service is set on form opening but went to None on search requests

    def filter_queryset(self, request, term, queryset, **kwargs):
        qs = super().filter_queryset(request, term, queryset, **kwargs)
        
        print('BBB', self.service) # <- Always None
        qs = qs.exclude(service=self.service)
        return qs

Use Dropdown widget in dynamically added/deleted formset factory.

Goal
Use django-select2 dropdown widget in dynamically added/deleted formset factory.

Problem
The widget loads for each formset, and works properly for the first form, however future forms do not show the dropdown when clicked on. This is non-Admin view.

applegrew#606 (comment)

On this linked comment, Joe asks if the form is being added dynamically, which mine is - is this the cause of the issue?

Code Snippet
Not sure which part of my code is causing this, and don't want to add everything, so can add this in the future if needed.

Installing via pipenv Fails

Goal
Trying to install Django-Select2.

Problem

pipenv install django-select2
ERROR: Could not find a version that matches django<2.0.0,==1.11.27,>=1.11,>=1.8,>=1.8.0,>=2.2

Code Snippet

[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"

[packages]
dj-database-url = "==0.5.0"
Django = "==1.11.27"
gunicorn = "==19.9.0"
"psycopg2-binary" = "==2.7.5"
djangorestframework = "==3.8.2"
whitenoise = "==3.3.1"
python-decouple = "==3.1"
django-tenants = "==1.3.4"
brotlipy = "==0.7.0"
django-el-pagination = "==3.2.4"
django-debug-toolbar = "==1.9.1"
"boto3" = "==1.7.66"
django-storages = "==1.6.6"
pillow = "==5.2.0"
redis = "*"
celery = "*"
xlrd = "*"
defusedxml = "*"
django-inlinecss = "*"
django-select2 = "*"

[dev-packages]

[requires]
python_version = "3.6.10"

Django 4.1 Deprecation Warning

Describe the bug
Django raises the deprecation warning shown below.

Exception & Traceback
RemovedInDjango41Warning: 'django_select2' defines default_app_config = 'django_select2.apps.Select2AppConfig'. Django now detects this configuration automatically. You can remove default_app_config.

Code Snippet
python -Wa manage.py check in a Django 3.2.8 project with django_select2 7.7.3 installed.

I assume this would be a breaking change - I'm not sure how far back Django stopped requiring explicit default_app_config definition.

custom labels and custom querysets with Django autocomplete_fields?

I had a look at the current state of autocomplete_fields and i sadly fail to see how they all of a sudden are superior to this package which worked quite nice in my Django 2.1.5 admin, which im trying to upgrade.

My project uses django-select2 to have custom labels and custom querysets.
While i can work my way around some of that stuff, it gets kinda crazy once i want different restrictions for the same model used in different relations.

By claiming: "Autocomplete fields are superior and we recommend using them, instead of this package for the admin." this should be possible somehow and @codingjoe i bet you know how? Could you point me in the right direction?

Why was the Admin supported removed in the first place?

tagging in the django-select2

I try to use ModelSelect2TagWidget and I receive value list, where is id for existing items and name for new. How can I undestand in the method value_from_datadict what is what? My name of new item can be "1" for example and 1 is id for current item in the queryset

ModelSelect2Widget broken for empty fields in 7.6.0

Describe the bug
I have a widget that lets me search models related to another model. It worked as expected in 7.5.0, but is causing a 500 error in 7.6.0 when expanding the select2 (searching with an empty string should just show the first x results I think). I think it is because a check for empty strings was removed in #26.

Exception & Traceback

Internal Server Error: /premises/select2_flock_lookup/auto.json
Traceback (most recent call last):
  File "C:\Path\env\lib\site-packages\django\db\models\fields\__init__.py", line 1774, in get_prep_value
    return int(value)
ValueError: invalid literal for int() with base 10: ''

The above exception was the direct cause of the following exception:

Traceback (most recent call last):

  File "C:\Path\env\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Path\env\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Path\env\lib\site-packages\django\views\generic\base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Path\env\lib\site-packages\django\views\generic\base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "C:\Path\env\lib\site-packages\django_select2\views.py", line 37, in get
    self.object_list = self.get_queryset()
  File "C:\Path\premises\views.py", line 153, in get_queryset
    cached_queryset = super().get_queryset()
  File "C:\Path\env\lib\site-packages\django_select2\views.py", line 57, in get_queryset
    return self.widget.filter_queryset(
  File "C:\Path\env\lib\site-packages\django_select2\forms.py", line 414, in filter_queryset
    return queryset.filter(select).distinct()
  File "C:\Path\env\lib\site-packages\django\db\models\query.py", line 942, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "C:\Path\env\lib\site-packages\django\db\models\query.py", line 962, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, *args, **kwargs)
  File "C:\Path\env\lib\site-packages\django\db\models\query.py", line 969, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "C:\Path\env\lib\site-packages\django\db\models\sql\query.py", line 1358, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "C:\Path\env\lib\site-packages\django\db\models\sql\query.py", line 1377, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "C:\Path\env\lib\site-packages\django\db\models\sql\query.py", line 1237, in build_filter
    return self._add_q(
  File "C:\Path\env\lib\site-packages\django\db\models\sql\query.py", line 1377, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "C:\Path\env\lib\site-packages\django\db\models\sql\query.py", line 1319, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "C:\Path\env\lib\site-packages\django\db\models\sql\query.py", line 1165, in build_lookup
    lookup = lookup_class(lhs, rhs)
  File "C:\Path\env\lib\site-packages\django\db\models\lookups.py", line 24, in __init__
    self.rhs = self.get_prep_lookup()
  File "C:\Path\env\lib\site-packages\django\db\models\lookups.py", line 76, in get_prep_lookup
    return self.lhs.output_field.get_prep_value(self.rhs)
  File "C:\Path\env\lib\site-packages\django\db\models\fields\__init__.py", line 1776, in get_prep_value
    raise e.__class__(
ValueError: Field 'house_number' expected a number but got ''.

Code Snippet

# widgets.py
class HouseSelectWidget(ModelSelect2Widget):
    """Used in forms to search for houses"""
    model = House
    search_fields = [
        'house_number',
    ]

    def __init__(self, attrs=None, choices=(), **kwargs):
        if 'data_view' not in kwargs:
            kwargs['data_view'] = 'premises:select2_house_lookup'
        super().__init__(attrs=None, choices=(), **kwargs)

    def build_attrs(self, base_attrs, extra_attrs=None):
        self.attrs.setdefault('data-minimum-input-length', 0)
        return super().build_attrs(base_attrs, extra_attrs)

# views.py
class HouseAutoResponseView(AutoResponseView):
    """
    Used by select2 for filtering by subscriber.
    """
    def get_queryset(self):
        cached_queryset = super().get_queryset()
        # code that filters the queryset by current user
        return cached_queryset

To Reproduce
This is using Django 3.1.5 with Python 3.8.7 on Windows and also tested on Linux with the same config.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.