Django Dynami c формы - проверка поля Select - PullRequest
1 голос
/ 07 августа 2020

Я использую Django 2.2

Я создаю форму динамически, читая файл определения JSON; в файле конфигурации указаны типы виджетов, разрешенные значения и т. д. c.

Однако я немного расстроился с виджетом Select, потому что я добавляю '-' к списку разрешенных значений в список (чтобы я знал, когда пользователь не выбрал элемент).

Это фрагмент кода, в котором создается виджет Select:

class myForm(forms.Form):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

       # ...
       elif widget_type_id == WIDGET_TYPE_DROPDOWN:
            CHOICES.insert(0,('-', INVALID_SELECTION))
            form_field = CharField(label=the_label, widget=Select(choices=CHOICES),required=is_required)

Моя проблема в том, что когда В моей форме вызывается метод is_valid(), любые визуализированные виджеты Select принимаются как действительные независимо от выбора.

Я хочу реализовать код с этим logi c (псевдокод ниже):

def is_valid(self):
    for field_name, field in self.fields.items():
        if isinstance(field.type, Select):
            if field.required and field.selected_value == INVALID_SELECTION:
                return False

     return super().is_valid()

Как правильно реализовать эту функцию? Например, как мне вообще получить выбранные значения для поля (в коде формы)?

Ответы [ 3 ]

1 голос
/ 17 августа 2020

Проверить данные формы: docs

  • путем создания настраиваемого Field с проверкой
  • специфицированного c поля с помощью fieldname_clean()
  • путем замены clean()
  • с помощью валидаторов

? Как правильно реализовать эту функцию? Я немного отклонился от псевдокода в том, что вы спросили

Валидаторы документы

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

Создайте validator.py в своем приложении

# validator.py
from django.core.exceptions import ValidationError

def validate_select_option(value):
    if value == '-':
        raise ValidationError('Invalid selection')

В forms.py импортируйте validate_select_option и добавить валидатор в поле

# forms.py
from .validator import validate_select_option

# other parts of code

form_field = CharField(label=the_label, widget=Select(choices=CHOICES), required=is_required, validator=[validate_select_option])

Этот валидатор validate_select_option теперь можно использовать не только для поля, в котором есть варианты, но и для любого другого поля для проверки. Во всяком случае, это не его намерение. Таким образом, можно использовать любые поля с вариантами выбора :)

Поскольку вы сказали, что создаете форму динамически, и я предполагаю, что вы можете добавить дополнительные параметры в Field, используя определение JSON файл. Для fieldname_clean() и clean() вам нужно будет добавить эти методы в свой класс Form. Пользовательское поле может быть создано и импортировано в. Но я думаю, что простые валидаторы могут сделать это легко.

? как мне даже получить выбранные значения для поля (в коде формы)

Если используются методы класса формы clean(self, *args, **kwargs) и fieldname_clean(self, *args, **kwargs): вы можете получить доступ данные формы по self.cleaned_data словарю. cleaned_data создается только после is_valid().

При переопределении is_valid, чтобы получить доступ к данным формы, нам нужно сначала вызвать родительскую проверку, а затем работать над ней.

def is_valid(self, *args, **kwargs):
    # cannot access self.cleaned_data since it is not created yet

    valid = super(myForm, self).is_valid()

    # can access self.cleaned_data since it has been created when parent is_valid() has been called

    for fieldname, field in self.fields.items():
        if isinstance(field, forms.CharField): # the type of widget is not considered.
            if fieldname in self.cleaned_data and field.required and self.cleaned_data[fieldname] == '-':
                valid = False

    return valid
0 голосов
/ 14 августа 2020

CHOICES с уже значениями. Я вставляю ('INVALID_SELECTION', 'INVALID_SELECTION') это. И проверьте, равно ли значение поля form_field INVALID_SELECTION, затем добавьте ошибку в то же поле. Отправлена ​​другая форма.

views.py

class DynamicFormView(View):
    template_name = 'test.html'
    def get(self, request, *args, **kwargs):
        form = myForm( request.POST or None)
        context = { 
            'form' : form,
        }
        return render(request, self.template_name, context)
    
    def post(self, request,id = None, *args, **kwargs):
        context = {}
        form = myForm(request.POST or None,)
        if form.is_valid():
            if request.POST['form_field'] == 'INVALID_SELECTION':
                form.add_error("form_field",_("This field is required."))
            else:
                form.save()
        context = { 
            'form' : form, 
        }
        return render(request, self.template_name, context)

forms.py

class myForm(forms.Form):
    CHOICES = [
        ('FR', 'Freshman'),
        ('SO', 'Sophomore'),
        ('JR', 'Junior'),
        ('SR', 'Senior'),
        ('GR', 'Graduate'),
    ]
    CHOICES.insert(0,('INVALID_SELECTION', 'INVALID_SELECTION'))
    form_field = forms.ChoiceField(label='the_label',choices=CHOICES,widget=forms.Select(attrs={'class':' form-control'}),required = False)
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def save(self):
        # form is success
        pass
    class Meta:
        model   = Student

urls.py

path('dyanmic-form/create/',  views.DynamicFormView.as_view(), name='dyanamic_form_create'),

Извините, я плохо engli sh язык.

0 голосов
/ 14 августа 2020

Это как бы скрыто, потому что вы используете CharField с виджетом Select, но если вы посмотрите документацию ChoiceField, там написано, что пустое значение должно быть пустой строкой.

Предполагая, что поле формы required=True, вы должны просто иметь возможность изменить свой пустой кортеж значений на ('', INVALID_SELECTION).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...