For some reason, suggestions from django-autocomplete-light 3.5.0
are displayed beyond the drop-down list, to the right (there's narrow blue rectangle visible that indicates suggestions):
I'm able to reverse the widget's url and obtain correct suggestions. Everything's working fine but rendering - when I click on this narrow rectangle, correct value appears in the edit box. I collected all the static files. I'm working on Linux 20.04 LTS, Chrome 83.0.4103.106, python 3.7.7, django 3.0.3, bootstrap 4.5.0 and font-awesome 4.7.0. Here is the code (except settings) that I wrote
forms.py
class OpinionForm(forms.ModelForm):
# user field is defined as hidden and disabled such that it couldn't be changed
user = forms.ModelChoiceField(
widget=forms.HiddenInput,
queryset=get_user_model().objects.all(),
disabled=True
)
# defining all the fields with autocomplete feature
country = forms.ModelChoiceField(
queryset=Country.objects.all(),
widget=autocomplete.ModelSelect2(url="country_autocomplete")
)
class Meta:
model = Opinion
fields = ("content",)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["country"].label = "Kraj"
self.fields["content"].label = "Treść"
models.py
class Country(models.Model):
name = models.CharField(max_length=200, null=False)
def __str__(self):
return self.name
class Opinion(models.Model):
user = models.ForeignKey(to=settings.AUTH_USER_MODEL)
content = models.TextField()
created = models.DateTimeField(auto_now=True)
urls.py
urlpatterns = [
path("add_opinion", views.CreateOpinionView.as_view(), name="add_opinion"),
path("country-autocomplete/", CountryAutocomplete.as_view(create_field="name"),
]
views.py
class CountryAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return Country.objects.none()
qs = Country.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
class CreateOpinionView(LoginRequiredMixin, CreateView):
form_class = OpinionForm
template_name = "opinions/create.html"
def get_initial(self):
"""
When our view is instantiating the form, it will pass the result of get_initial() as the 'initial'
argument and the POST data as the 'data' argument
:return:
"""
return {
"user": self.request.user.id
}
def form_valid(self, form):
"""
If a form is valid, CreateView will call form_valid.
If the form isn't valid, CreateView will re-render the template.
:param form:
:return:
"""
action = self.request.POST.get("action")
# when we want to save, we will call the original form_valid method
# the original method saves the new opinion
if action == "SAVE":
# save and redirect as usual
return super().form_valid(form)
return HttpResponseBadRequest()
create.html
{% extends "base.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block title %}Dodaj opinię{% endblock %}
{% block content %}
<div class="col-md-12">
<h1>Dodaj opinię</h1>
<form method="post">
{{ form | crispy }}
{% csrf_token %}
<button class="btn btn-primary" type="submit" name="action" value="SAVE">Zapisz</button>
</form>
</div>
{% endblock %}
{% block footer %}
<script type="text/javascript" src="{% static "admin/js/vendor/jquery/jquery.js" %}"></script>
{{ form.media }}
{% endblock %}
Your code seems to work fine for me, so the error must be somewhere else, probably somewhere in your CSS.
Your code had two errors that prevented it from running though:
- user = models.ForeignKey(to=settings.AUTH_USER_MODEL)
+ user = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
- path("country-autocomplete/", CountryAutocomplete.as_view(create_field="name"),
+ path("country-autocomplete/", CountryAutocomplete.as_view(create_field="name"), name='country_autocomplete'),
Here are additional details of my setup, perhaps you can find what is different from yours:
Versions:
Django==3.0.3
django-autocomplete-light==3.5.0
django-crispy-forms==1.9.1
base.html
:
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock title %}</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
</head>
<body>
{% block content %}
{% endblock %}
{% block footer %}
{% endblock %}
</body>
</html>
settings.py
:
# ...
INSTALLED_APPS = [
# ...
'dal',
'dal_select2',
'crispy_forms',
'yourappname'
]
# ...
# (everything else left at defaults)