4

i am new on django and i need your help, trying since many days to understand django-autocomplete-light, after setup my test, http://192.168.0.108:8000/country-autocomplete/ work, data is showed like explaned here http://django-autocomplete-light.readthedocs.io/en/master/tutorial.html#overview

But after following next step, i am getting error:

AttributeError at /auto
'list' object has no attribute 'queryset'
Request Method: GET
Request URL:    http://192.168.0.108:8000/auto
Django Version: 1.10.3
Exception Type: AttributeError
Exception Value:'list' object has no attribute 'queryset'
Exception Location: /home/alcall/ENV/lib/python3.4/site-packages/dal/widgets.py in filter_choices_to_render, line 161

Below my setup:

urls:

from dal import autocomplete
from django.conf.urls import url
from django.contrib import admin
from rates.view.index import *
from rates.view.index import UpdateView

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(
    r'^country-autocomplete/$',
    CountryAutocomplete.as_view(),
    name='country-autocomplete',
),
url(r'^auto$',
    UpdateView.as_view(),
    name='select',
),
]

models.py

from __future__ import unicode_literals
from django.db import models

class Country(models.Model):
    enabled = models.IntegerField()
    code3l = models.CharField(unique=True, max_length=3)
    code2l = models.CharField(unique=True, max_length=2)
    name = models.CharField(unique=True, max_length=64)
    name_official = models.CharField(max_length=128, blank=True, null=True)
    prix = models.FloatField()
    flag_32 = models.CharField(max_length=255, blank=True, null=True)
    flag_128 = models.CharField(max_length=255, blank=True, null=True)
    latitude = models.DecimalField(max_digits=10, decimal_places=8,     blank=True,$
    longitude = models.DecimalField(max_digits=11, decimal_places=8, blank=True$
    zoom = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'country'

    def __str__(self):
        return self.name

view (include form too)

from dal import autocomplete
from django.shortcuts import render
from rates.models import Country
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.http import HttpResponse
from django import forms
from django.core.urlresolvers import reverse_lazy
from django.views import generic

class CountryAutocomplete(autocomplete.Select2QuerySetView):
    def get_queryset(self):
        # Don't forget to filter out results depending on the visitor !
       # 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 Form_country(forms.ModelForm):
    class Meta:
       model = Country
       fields = ('name', 'code2l')
       widgets = {
          'name': autocomplete.ModelSelect2Multiple(
            'country-autocomplete'
           )
       }

class UpdateView(generic.UpdateView):
    model = Country
    form_class = Form_country
    template_name = 'fr/public/monformulaire.html'
    success_url = reverse_lazy('select')


    def get_object(self):
        return Country.objects.first() 
Kef
  • 73
  • 2
  • 9

3 Answers3

6

I had the same issue. The problem here is with the widget. Tried to fix it for very long. The only way in worked for me was changing form's widget.

If it doesn't matter that much you can use autocomplete.ListSelect2 instead, it worked for me.

So try this:

class Form_country(forms.ModelForm):
    class Meta:
       model = Country
       fields = ('name', 'code2l')
       widgets = {
          'name': autocomplete.ListSelect2(
            'country-autocomplete'
           )
       }

Actually you can just try any other autocomplete widget and see weather it works

pythad
  • 4,241
  • 2
  • 19
  • 41
3

I you create the widget in __init__(), then this work-around of issue #790 helps:

form.fields['name'].widget.choices = form.fields['name'].choices
guettli
  • 25,042
  • 81
  • 346
  • 663
0

Here is my implementation, where I used it to suggest similar names that are already present in a model

IMPORTANT: After you must have done all these, don't forget to run python manage.py collectstatic. Also note that you wish to include a placeholder in your form field you have to do it with data-placeholder in the widget autocomplete widget.

When you run it, you'll see this message

Found another file with the destination path 'admin/js/jquery.init.js'. It will be ignored since only the first encountered file is collected. If this is not what you want, make sure every static file has a unique path.

This is the reason the documentation states here that you must place dal and dal_select2 before django.contrib.admin in your INSTALLED_APPS

models.py

from django.db import models

class Patient(models.Model):
    name = models.CharField(max_length=100)
    stable = models.BooleanField(default=False)

views.py

from django.db.models import Q
from dal import autocomplete

class NewName(autocomplete.Select2QuerySetView):
    """Suggest similar names in form"""
    def get_queryset(self):
        qs = People.objects.filter(stable=True)
        if self.q:
            query = Q(name__contains=self.q.title()) | Q(name__contains=self.q.lower()) | Q(name__contains=self.q.upper())
            qs = qs.filter(query)
        return qs

urls.py

from django.urls import path
from . import views
urlpatterns = [
    path('new-name/', views.NewName.as_view(), name='new_name_autocomplete'),
]

forms.py

class PatientForm(forms.ModelForm):
    class Meta:
        model = Patient
        fields = ["stable", "name"]

        widgets = {
            "name" : autocomplete.ModelSelect2(url=reverse_lazy('new_name_autocomplete'), attrs={'class' : 'form-control', 'data-placeholder' : "Name"}),

I had to modify dal/widgets.py and comment out the queryset filtering as shown below. It seems to be a bug or something. The issue has been raised here. But if you're using autocomplete.ListSelect2() as your widget, then there's no need for that.

class QuerySetSelectMixin(WidgetMixin):
    """QuerySet support for choices."""

    def filter_choices_to_render(self, selected_choices):
        """Filter out un-selected choices if choices is a QuerySet."""
        # self.choices.queryset = self.choices.queryset.filter(
        #     pk__in=[c for c in selected_choices if c]
        # )
chidimo
  • 2,684
  • 3
  • 32
  • 47