Hi all,
I'm new to python, Django and, obviously, DAL. So sorry if I'm asking trivial things or misunderstanding some of your docs.
I'm trying to write a small application with a couple of dropdown menus that autocomplete and one depends on the other.
My model is very simple:
```
class Module(models.Model):
module_name = models.CharField(max_length=200, primary_key=True)
packages_available = models.JSONField()
```
module_name will be the name of a software and packages_avaialble the list of packages available for that software. The list can be large, up to 2/3k items, that's why I used JSONField (is there a better approach?)
I then created 2 views for the autocomplete, one to get all the module_names in the DB and the other to get the list of packages once the module has been selected:
```
class ModuleAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
qs = Module.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
class PackageAutocomplete(autocomplete.Select2ListView):
def get_list(self):
module_selected = self.forwarded.get('module', None)
pklist = ''
if module_selected:
pklist = Module.objects.get(module_name=module_selected).packages_available
return pklist
```
registered in urls:
```
url(r'^modules-autocomplete/$',ModuleAutocomplete.as_view(),name='modules-autocomplete',),
url(r'^packages-autocomplete/$',PackageAutocomplete.as_view(),name='packages-autocomplete',),
```
and checked that both urls can be reversed (the second with a forwared value, of course). All worked, so far so good.
I 'd like my application to ask for a module_name and a list of packages, so I created a form like:
```
class ModuleListForm(forms.Form):
module = forms.ModelChoiceField(
queryset=Module.objects.all(),
widget=autocomplete.ModelSelect2(url='modules-autocomplete'),
required=True,
)
packages = autocomplete.Select2ListChoiceField(
widget=autocomplete.Select2Multiple(url='packages-autocomplete',
forward=('module',)
),
)
```
With all in place, I start the server and I see 2 dropdown select boxes that show exactly what I want and I can select multiple packages:
(for testing purposes the list of packages contains trash data, I still need to test this with thousands of packages).
My problem starts here. When I submit my form it returns an error because the option I select does not exist:
<tr><th><label for="id_packages">Packages:</label></th><td><ul class="errorlist"><li>Select a valid choice. ['mariposa', 'zariguella'] is not one of the available choices.</li></ul><select name="packages" required id="id_packages" data-autocomplete-light-url="/Rweb/packages-autocomplete/" data-autocomplete-light-function="select2" data-autocomplete-light-language="en" multiple>
As far as I understood that's expected because the ChoiceField validation expects the selected options to be predefined (if that's the word).
So I think that in my form the packages field needs a choice_list. Something like:
```
packages = autocomplete.Select2ListChoiceField(
choice_list=get_choice_list
widget=autocomplete.Select2Multiple(url='packages-autocomplete',
forward=('module',)
),
)
```
BUT, how do I build a function that returns the list of choices if I do not know what options will be available? I have the feeling that I'm missing some important piece of information from the docs, but I don't find it :-(
Are my assumptions right or am I completely wrong?
I had a working solution when adding the choices to the form directly in the main view, something like:
```
Class Index(View):
form_class = ModuleListForm
template_name = 'index.html'
av_choices = []
def post(self, request, *args, **kwargs):
modules_list = self.form_class(request.POST)
packages_selected = request.POST.getlist('packages')
context = { 'modules_list': modules_list}
for pck in packages_selected:
choice=tuple((pck, pck))
self.av_choices.append(choice)
modules_list.fields['packages'].choices = [self.av_choices]
```
(I have some problems building the fields list of tuples, but in some cases it worked).
The thing is that I believe that this workaround is not appropriate and that DAL can do it for me.
Thanks for all that read until here :-)
Arnau