Джанго универсальная модель Formsets

Поэтому у меня есть сайт, на котором пользователи могут регистрировать устройства, а затем регистрировать команды для этих устройств. Эти команды имеют связанный виджет (кнопка, ползунок и т. Д.), Который определяет уникальные свойства, которыми обладает команда.

Я пытаюсь найти наиболее общий способ использования наборов форм в моем приложении. У меня все работает: я создаю набор model_formset для каждой ModelForm и получаю данные из каждой модели для размещения в наборе форм, а затем показываю их в своем шаблоне.

Что я действительно хотел бы сделать, это что-то вроде этого:

command_formset = modelformset_factory(Command, extra=0, fields='__all__')
formset = command_formset(queryset=Command.objects.filter(device_id=device_id))

Где я получаю все свои команды (которые возвращают как кнопки, так и ползунки), а затем создаю единый набор command_form, который имеет все объекты команд.

В этом случае он выполняет часть того, что я ищу, где я могу запросить свою модель и получить все команды кнопок и ползунков, но набор форм включает только поля из команды - поэтому значения ползунка и максимума для ползунка теряются.

Возможно ли что-то подобное? Вот мой более полный код:

модели

class Command(models.Model):
    command_name = models.CharField(max_length=100)
    command = models.CharField(max_length=100)
    command_url = models.CharField(max_length=100)
    command_type = models.CharField(max_length=100)
    device = models.ForeignKey(Device, on_delete=models.CASCADE, default=1)  # Each command has one device

    def __str__(self):
        return self.command_name


class ButtonCommand(Command):
    button_color = models.CharField()


class SliderCommand(Command):
    min_value = models.IntegerField()
    max_value = models.IntegerField()

формы

class CommandForm(ModelForm):
    class Meta:
        model = Command
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in iter(self.fields):
            self.fields[field].widget.attrs.update({'class': 'form-control'})


class ButtonCommandForm(ModelForm):
    class Meta:
        model = ButtonCommand
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in iter(self.fields):
            self.fields[field].widget.attrs.update({'class': 'form-control'})


class SliderCommandForm(ModelForm):
    class Meta:
        model = SliderCommand
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in iter(self.fields):
            self.fields[field].widget.attrs.update({'class': 'form-control'})

Посмотреть

command_formset = modelformset_factory(Command, extra=0, fields='__all__')
button_command_formset = modelformset_factory(ButtonCommand, form=ButtonCommandForm, extra=0,
                                              fields=('command_name', 'command', 'command_type', 'command_url'))
slider_command_formset = modelformset_factory(SliderCommand, extra=0,
                                              fields=('command_name', 'command', 'command_type', 'command_url',
                                                      'min_value', 'max_value'))

device_form = DeviceForm(initial=device)

formset = command_formset(queryset=Command.objects.filter(device_id=device_id))
button_formset = button_command_formset(queryset=ButtonCommand.objects.filter(device_id=device_id),
                                        prefix="button_form")
slider_formset = slider_command_formset(queryset=SliderCommand.objects.filter(device_id=device_id),
                                        prefix="slider_form")

Изменить дополнительный вид кода

template = 'device_control/device_management.html'
return TemplateResponse(request, template, {'device': device,
                                            'device_form': device_form,
                                            'button_formset': button_formset,
                                            'slider_formset': slider_formset,
                                            'formset' : formset})

Еще один связанный вопрос

    input_type = request.POST['command_type']
    if input_type == 'button':
        form = ButtonCommandForm(request.POST)
    elif input_type == 'slider':
        form = SliderCommandForm(request.POST)
    else:
        form = None

Надеюсь, я не в восторге, но приведенный выше вопрос очень похож, который кажется гораздо проще. Пользователь отправляет форму, которая наследуется от Command. Хотя вышеприведенное довольно просто, если в итоге у меня будет более 20 различных типов командных форм, это будет довольно неприятно.

Я действительно надеюсь, что упускаю какой-то способ, которым Джанго может сказать, какую дочернюю форму следует использовать для создания формы.

0 ответов

Другие вопросы по тегам