Custom autocomplete fields for Django.
Documentation available at https://django-select2.readthedocs.io/.
Note
Django's admin comes with builtin support for Select2 via the autocomplete_fields feature.
This project forked from applegrew/django-select2
This is a Django integration for Select2
Home Page: https://django-select2.rtfd.io
License: MIT License
Custom autocomplete fields for Django.
Documentation available at https://django-select2.readthedocs.io/.
Note
Django's admin comes with builtin support for Select2 via the autocomplete_fields feature.
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:
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:
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.
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%;'}),
}
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?
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',)})
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.
'
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.
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.
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,
)
)
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">×</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?
Link https://django-select2.github.io/ no longer exists
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
To Reproduce
Steps to reproduce the behavior:
little reminder to consider switching to tail.select as a more lightweight alternative to select2.
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
ManyToMany field does not save as I select. I've tried Disable Auto Sort but is not getting correct output. Help needed.
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.
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 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 uuid
s, 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?
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.
I think, that is not good idea to hardcode filter used in dependent field to filter queryset
this line:
django-select2/django_select2/views.py
Line 57 in bfc9313
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
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()
)
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>
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.
ModelSelect2Mixin
in the optgroups
method value is always pk
ModelSelect2Mixin
in the optgroups
linequery = Q(**{"%s__in" % field_name: selected_choices})
print(query)
>>> (AND: ('slug__in', {'196'}))
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.
$('.django-select2').djangoSelect2({placeholder: 'Select an option'});
Generate placeholder for foreignkey field. But not generated in many2many
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?
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()
A badge of this kind with text as "Select all" is required.
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:
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:
I assume that handling the ValueError
exception is sufficient here, but I am not familiar with the django-select2 code.
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(),
)
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:
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 templateMy 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()
});
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.
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?
I'm using the default Django cache setup (that is to say, no cache config at all).
Is it just a performance hit? Or are there circumstances in which the select would not work?
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...
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
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>
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 %}
is django-select2 functional with django rest framework?
since drf uses serializers and not forms, widgets cannot be defined
Please include tests in the source tarball, they are needed for debian packaging of select2.
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')
})
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('/filecategory/new', '_blank', 'width=1000,height=600,menubar=no,toolbar=no');" type="button">+</button>
</span>
</div>
</div>
</div>
it would be nice to have configurable clearing of dependent field on various events
by now only select event is clearing dependent fields
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')
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
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>
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
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")
})
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'}
andModelSelect2Widget
as base for the widgetNow 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:
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:
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.
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
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.
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.
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"
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.
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?
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
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.