ModelMultipleChoiceField вызывает «Введите список значений». - PullRequest
0 голосов
/ 20 февраля 2020

У меня есть форма:

class BaseCommandForm(forms.Form):
    devices = forms.ModelMultipleChoiceField(
        queryset=Device.objects.filter(token__isnull=False).order_by('division__name', 'pk'),
        widget=forms.Select(attrs={'class': 'devices-list', 'multiple': 'multiple', })
    )

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.fields['devices'].label_from_instance = BaseCommandForm.label_for_device_instance

    @staticmethod
    def label_for_device_instance(obj: Device) -> str:
        return f'{obj.division.name} -> #{obj.pk}'

Это отображается как выберите:

<select name="devices" class="devices-list select form-control is-invalid select2-hidden-accessible" multiple="" id="id_devices" data-select2-id="id_devices" tabindex="-1" aria-hidden="true"> 
   <option value="1" data-select2-id="6">Test Division -&gt; #1</option> 
   <option value="2" data-select2-id="7">Test Division -&gt; #2</option> 
   ...
</select>

Мой взгляд:

class CreateCommandView(CompanyMixin, GroupRequiredMixin, FormView):
    template_name = 'commands/create.html'
    group_required = 'company_admin'  # TODO: Change group
    success_url = reverse_lazy('companies:commands:list')

    def dispatch(self, request, *args, **kwargs):
        command_type = self.request.GET.get('type')
        if command_type not in [TYPE_UPDATE_CONFIG, TYPE_SHOW_MESSAGE, TYPE_DOWNLOAD_FILE, TYPE_UNINSTALL_APP, TYPE_WIPE_DEVICE, TYPE_UNINSTALL_AGENT]:
            return HttpResponseBadRequest()

        return super().dispatch(request, *args, **kwargs)

    def get_form_class(self):
        command_type = self.request.GET.get('type')

        if command_type == TYPE_UPDATE_CONFIG:
            form_class = UpdateConfigCommandForm
        elif command_type == TYPE_SHOW_MESSAGE:
            form_class = ShowMessageCommandForm
        elif command_type == TYPE_DOWNLOAD_FILE:
            form_class = DownloadFileCommandForm
        elif command_type == TYPE_UNINSTALL_APP:
            form_class = UninstallAppCommandForm
        elif command_type == TYPE_WIPE_DEVICE:
            form_class = WipeDeviceCommandForm
        elif command_type == TYPE_UNINSTALL_AGENT:
            form_class = UninstallAgentCommandForm
        else:
            raise ValueError(f'Invalid type: {command_type}')

        return form_class

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        context['command_type'] = self.request.GET.get('type')

        return context

    def form_invalid(self, form):
        print(self.request.POST)
        return super().form_invalid(form)

    def form_valid(self, form):
        form.save()

        return super().form_valid(form)

Я выбираю два значения и отправляю Форма:

enter image description here

И возвращается ошибка:

enter image description here

I видеть только одно устройство в cleaned_data.get('devices') с отладчиком (и, как вы можете видеть на скриншоте, оно выводит только одно устройство при ошибке).

request.POST:

<QueryDict: {'csrfmiddlewaretoken': ['sdlVFQVnjoEz2uQHpFvv00OqcypZKjOCP7v5wYIdgqx5iUhikjNuCIGW5Q9Qbopr'], 'devices': ['6']}>

Что не так

1 Ответ

0 голосов
/ 20 февраля 2020

Хорошо, проблема была в виджете. SelectMultiple требуется для правильного разбора тела:

    devices = forms.ModelMultipleChoiceField(
        queryset=Device.objects.filter(token__isnull=False).order_by('division__name', 'pk'),
        widget=forms.SelectMultiple(attrs={'class': 'devices-list', 'multiple': 'multiple', })
    )
...