Django动态表单-验证选择字段

Django动态表单-验证选择字段,django,django-forms,Django,Django Forms,我正在使用Django 2.2 我通过读取JSON定义文件动态创建表单;配置文件指定小部件的类型、允许的值等 然而,我对Select小部件有点不习惯,因为我在列表中的允许值列表前加了一个“-”,这样我就可以知道用户何时没有选择项目 这是创建Select小部件的代码段: class myForm(forms.Form): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)

我正在使用Django 2.2

我通过读取JSON定义文件动态创建表单;配置文件指定小部件的类型、允许的值等

然而,我对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小部件都会被接受为有效的,而不管选择是什么

我想实现具有以下逻辑伪代码的代码:

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()

实现此功能的正确方法是什么?例如,我怎么才能在表单代码中获得字段的选定值呢?

它有点隐藏,因为您使用的是带有Select小部件的CharField,但是如果您查看文档,它会说空值应该是空字符串

假设表单字段为required=True,您应该能够将空值元组更改为无效的\u选择。

选择已经有值。我在此插入“无效选择”、“无效选择”。并检查表单_字段的值是否为无效_选择,然后在同一字段中添加错误。否则提交表格

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
url.py

path('dyanmic-form/create/',  views.DynamicFormView.as_view(), name='dyanamic_form_create'),
抱歉,我的英语不好。

验证表单数据:

通过创建带有验证的自定义字段 使用fieldname\u clean创建特定字段 凌驾于清洁之上 通过使用验证器 ??实现此功能的正确方法是什么? 在你问的问题中,我有点偏离了伪代码

验证器

已经有许多内置验证器。为此,创建一个自定义验证器,用于检查字段中的值并引发ValidationError

在应用程序中创建validator.py

验证器.py 从django.core.exceptions导入ValidationError def validate_select_选项值: 如果值=='-': 引发验证错误“选择无效” 在forms.py import validate_中,选择_选项并将验证器添加到字段中

forms.py 从.validator导入验证\选择\选项 代码的其他部分 表单\u field=CharFieldlabel=the\u标签,widget=Selectchoices=CHOICES,required=is\u required,validator=[validate\u select\u选项] 这个验证器validate_select_选项现在不仅可以用于有选项的字段,还可以用于任何其他要验证的字段。无论如何,这不是它的意图。因此可用于具有以下选项的任何字段:

因为您说过要动态创建表单,我假设您可以使用JSON定义文件向字段添加其他选项。对于fieldname_clean和clean,您需要在表单类中添加这些方法。可以创建自定义字段并将其导入。但是,我认为简单的验证器很容易做到这一点

??我如何在表单代码中获得字段的选定值

如果使用表单类方法cleanself、*args、**kwargs和fieldname_cleanself、*args、**kwargs:您可以通过self.cleansed_数据字典访问表单数据。只有在\u有效后才能创建清理的\u数据

虽然重写是有效的,但为了访问表单数据,我们需要先调用父验证,然后再处理它

def为_validself,*args,**kwargs: 无法访问self.cleaned_数据,因为它尚未创建 valid=超级形式,self.is\u有效 可以访问自清理的\u数据,因为它是在调用parent is\u valid时创建的 对于fieldname,self.fields.items中的字段: 如果是isinstancefield,则forms.CharField:不考虑小部件的类型。 如果self.cleaned_数据中的fieldname和field.required和self.cleaned_数据[fieldname]=='-': 有效=错误 返回有效
如果使用无,无效的\u选择怎么办?无而不是-您可以为选择字段动态添加clean_field_name方法并覆盖验证行为。是否尝试此方法?我更新了我的答案,请尝试此方法-Homunculus Reticulli