Reputation: 21
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
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:
register()
to pass class attributes: "In addition, keyword arguments will be set as class attributes."choices_for_request()
might be useful if you need to filter choices based on the user.I would like to automate this, but the widget isn't aware about the form field instance unfortunately.
Upvotes: 3
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
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