user1983713
user1983713

Reputation: 21

django-autocomplete-light filter queryset

I am trying to use django-autocomplete-light but I have some problems. I would like to filter the queryset in the ModelChoiceField. If I don't use auto-complete my result selection is correct but if I use widget it doesn't work correctly, it shows all records.

Here is my code:

class MyModelAdminForm(forms.ModelForm):
    def __init__(self, *args, **kw):
        super(MyModelAdminForm, self).__init__(*args, **kw)
        self.fields['my_field'] = forms.ModelChoiceField(
            MyModel.objects.filter(status=1),
            widget=autocomplete_light.ChoiceWidget('MyModelAutocomplete')
    )

class MyModelAdmin(ModelAdmin):
    form = MyModelAdminForm

Upvotes: 2

Views: 2874

Answers (3)

jpic
jpic

Reputation: 33420

You should set MyModelAutocomplete.choices, either via register():

autocomplete_light.register(MyModel, choices=MyModel.objects.filter(status=1))

Or within the class:

class MyModelAutocomplete(autocomplete_light.AutocompleteModelBase):
    choices = MyModel.objects.filter(status=1)

Refer to docs for more:

I would like to automate this, but the widget isn't aware about the form field instance unfortunately.

Upvotes: 3

jenniwren
jenniwren

Reputation: 351

I was trying to figure out how to do this within the autocomplete-light documentation. I figured out how, but not without a bit of digging, so hopefully this is helpful.

In the autocomplete_light_registry.py file, fill out the "name" and "choices" parameters:

#myapp/autocomplete_light_registry.py
autocomplete_light.register(MyModel,
    #... Other Parameters ...
    name = 'SpecialMyModelAutocomplete',
    choices = YourQuerySetHere, #e.g. MyModel.objects.filter(...)
)

The default name is "MyModelAutocomplete" so if you include more than one registered autocomplete for a model, you need to specify which one you want to use (otherwise it uses the first one in the registry, NOT the default).

To specify, use "autocomplete_names" which is (from the docs) "A dict of field_name: AutocompleteName to override the default autocomplete that would be used for a field." In my case I'm using it within the django admin.

#myapp/admin.py
class MyModelAdminForm(autocompletelight.ModelForm):
    class Meta:
        model = MyModel
        autocomplete_names = {'field_name':'SpecialMyModelAutocomplete'}

Note that you don't need to include any fields for which you want to use the default Autocomplete in autocomplete_names. Incidentally "autocomplete_exclude" and "autocomplete_fields" may also be of interest here and are analogous to "fields" and "exclude" in a ModelAdmin to specify which fields to include/exclude from using autocomplete.

Addition: You can also use "autocomplete_names" in the modelform_factory:

form = autocomplete_light.modelform_factory(MyOtherModel,autocomplete_names={MyFieldName:'MyModelAutocomplete'}) #where MyFieldName is a ForeignKey to MyModel

From the docs:

autocomplete_light.forms.modelform_factory(model,autocomplete_fields=None,autocomplete_exclude=None,autocomplete_names=None,registry=None,**kwargs)

Upvotes: 2

proprius
proprius

Reputation: 522

Apply the filter inside MyModelAutocomplete by defining a method

class MyModelAutocomplete(autocomplete_light.AutocompleteModelBase):
     choices=MyModel.objects.all()
     def choices_for_request(self):
        choices = choices.filter(status=1)
        return self.order_choices(choices)[0:self.limit_choices]  

choices_for_request is mostly used for dynamic filterming

Upvotes: 2

Related Questions