使用Django中的自定义MultiValueWidget验证MultiValueField [英] Validate a MultiValueField with a custom MultiValueWidget in Django

查看:173
本文介绍了使用Django中的自定义MultiValueWidget验证MultiValueField的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个字段和一个小部件,让它有一个近似的日期,这个想法有以下唯一的一个:




  • 确切日期

  • 一年或许一个月

  • 初始和结束年份



一些压缩的有效值可能是:




  • 1988/08/07, ,,,

  • ,1988 ,,,

  • ,1988,08 ,,

  • ,,, 1997,1999



问题是我无法验证字段只有一个上述三个选项,在Field定义中,我尝试创建有效和干净的方法,但它没有得到验证,我怀疑字段和小部件之间的链接是不对的。为了完成这个,我创建了一个Widget:

  class ApproximatedDateWidget(forms.MultiWidget):
def __init __(self,attrs = None,choices =()):
self.widgets =(
forms .tateInput(attrs = attrs),
forms.TextInput(attrs = attrs),
forms.Select(attrs = attrs,choices = choices),
forms.TextInput(attrs = attrs) ,
forms.TextInput(attrs = attrs),

super(ApproximatedDateWidget,self).__ init __(self.widgets,attrs = attrs)

def解压缩(self,value):
try:
打印值
如果值:
l = value.split(,)
打印l
如果l [0]和l [0]!=:
d = l [0] .split(/)
print d
return [date(int(d [0]) ,INT( d [1]),int(d [2])),无,无,无,无]
else:
返回[无,l [1],l [2],l [3 ],l [4]]
return [无,无,无,无,无]
除外:
raise
返回[无,无,无,无,无]

def format_output(self,rendered_widgets):
return mark_safe(u< table>
< tr>< td>确切日期:< / td>< td colspan =3> {0}< / td>< / tr>
< tr>< td>年份和月份:< / td>< td> {1}< / td>< td colspan =2> {2}< / td> ;< / TR>
< tr>< td>< / td>< td> Year< / td>< td colspan =2> Month< / td>< / tr>
< tr>< td>之间:< / td>< td> {3}< / td>< td>和< / td>< td> {4} TD>< / TR>
< tr>< td>< / td>< td>年< / td>< td>< / td>< td>年< td>< / tr>
< / table>
.format(* rendered_widgets))

表单Field: p>

 从工具导入MonthChoices 
从验证器导入nullableinteger

类ApproximatedDateField(forms.MultiValueField):

允许具有近似日期的字段,
确切的日期,月份和年份或年份范围



def __init __(self,required = False,widget = None,label = None,initial = None,
help_text = None,attrs = {},* args,** kwargs)
self.widget = ApproximatedDateWidget(attrs = attrs,choices = MonthChoices)
widgets = self.widget.widgets
fields =(
forms.DateField(required = required ,validators = [lessthantomorrow],widget = widgets [0]),
forms.CharField(widget = widgets [1],required = required,max_length = 4,validators = [nullableinteger]),
表单.ChoiceFi eld(required = required,choices = MonthChoices,widget = widgets [2]),
forms.CharField(widget = widgets [3],required = required,max_length = 4,validators = [nullableinteger]),
forms.CharField(widget = widgets [4],required = required,max_length = 4,validators = [nullableinteger]),

super(ApproximatedDateField,self).__ init __(fields = fields,

def compress(self,data_list):
返回{0 =必需,小部件=小部件,
label = label,initial = initial,help_text = help_text },{1},{2},{3},{4} 。格式(DATA_LIST [0] .strftime( %D /%米/%Y),DATA_LIST [1],(DATA_LIST [ 2]和data_list [2] .id)或,data_list [3],data_list [4])

def validate(self,values):
super(ApproximatedDateField,self) .validate(values)
如果值[0]不为无,(值[1]不为无或值[2]不为无)和(值[1]不为无或值[2]为不是没有):
raise ValidationError(u'Please only

def clean(self,values):
super(ApproximatedDateField,self).clean(values)
如果值[0]不是无,(值[1]不为无或值[2]不为无)和(值[1]不为无或值[2]不为无):
raise ValidationError你只需要填写确切的日期,年月日或范围年份)


解决方案

我写了一个自定义小部件和多值字段来处理英尺和英寸: http:// djangosnippets.org/snippets/2327/ ,还有另一个是数学验证码: https://github.com/btaylordesign/django-simple-math-captcha



我把验证放在MultiValueField的compress方法中,这对于这些都很好。您可能会看到该代码段和repo,看看是否让您处于正确的轨道。


I want to have a field and a widget that lets have an "approximated" date, the idea is have one and only one of the following :

  • Exact date
  • A year and maybe a month
  • An initial and an end year

Some compressed valid values could be:

  • "1988/08/07,,,,"
  • ",1988,,,"
  • ",1988,08,,"
  • ",,,1997,1999"

The problem is that I'm unable to validate the fields to have only one of the three options described above, in the Field definition I tried creating validate and clean methods, but it's not getting validating, I suspect that the link between the fields and widgets is not right. What am I missing?

To accomplish this I created a Widget:

class ApproximatedDateWidget(forms.MultiWidget):
    def __init__(self, attrs=None,choices=()):
        self.widgets = (
            forms.DateInput(attrs=attrs),
            forms.TextInput(attrs=attrs),
            forms.Select(attrs=attrs,choices=choices),
            forms.TextInput(attrs=attrs),
            forms.TextInput(attrs=attrs),
        )
        super(ApproximatedDateWidget, self).__init__(self.widgets, attrs=attrs)

    def decompress(self,value):
        try :
            print value
            if value:
                l=value.split(",")
                print l
                if l[0] and l[0]!="":                    
                    d=l[0].split("/")
                    print d
                    return [date(int(d[0]),int(d[1]),int(d[2])),None,None,None,None]
                else:
                    return [None, l[1], l[2], l[3], l[4]]
            return [None, None, None, None, None]
        except:
            raise
            return [None, None, None, None, None]

    def format_output(self,rendered_widgets):
        return mark_safe(u"""<table>
        <tr><td>Exact date:</td><td colspan="3">{0}</td></tr>
        <tr><td>Year and month:</td><td>{1}</td><td colspan="2">{2}</td></tr>
        <tr><td></td><td>Year</td><td colspan="2">Month</td></tr>
        <tr><td>Between:</td><td>{3}</td><td>and</td><td>{4}</td></tr>
        <tr><td></td><td>Year</td><td></td><td>Year<td></tr>
        </table>
        """.format(*rendered_widgets))

And the form Field:

from tools import MonthChoices
from validators import nullableinteger

class ApproximatedDateField(forms.MultiValueField):
    """
    Field that allows having an approximated date, one of
    exact date, month and year or range of years
    """


    def __init__(self, required=False, widget=None, label=None, initial=None,
                 help_text=None,attrs={}, *args, **kwargs):
        self.widget = ApproximatedDateWidget(attrs=attrs,choices=MonthChoices)
        widgets=self.widget.widgets
        fields = (
            forms.DateField(required=required,validators=[lessthantomorrow],widget=widgets[0]),
            forms.CharField(widget=widgets[1],required=required,max_length=4,validators=[nullableinteger]),
            forms.ChoiceField(required=required,choices=MonthChoices,widget=widgets[2]),
            forms.CharField(widget=widgets[3],required=required,max_length=4,validators=[nullableinteger]),
            forms.CharField(widget=widgets[4],required=required,max_length=4,validators=[nullableinteger]),
        )
        super(ApproximatedDateField, self).__init__(fields=fields,required=required, widget=widget, 
              label=label, initial=initial, help_text=help_text)

    def compress(self,data_list):
        return """{0},{1},{2},{3},{4}""".format(data_list[0].strftime("%d/%m/%Y"),data_list[1],(data_list[2] and data_list[2].id) or "",data_list[3],data_list[4])

    def validate(self,values):
        super(ApproximatedDateField, self).validate(values)
        if values[0] is not None and (values[1] is not None or values[2] is not None) and (values[1] is not None or values[2] is not None):
            raise ValidationError(u'Please only fill exact date or year and month or the range years')

    def clean(self,values):
        super(ApproximatedDateField, self).clean(values)
        if values[0] is not None and (values[1] is not None or values[2] is not None) and (values[1] is not None or values[2] is not None):
            raise ValidationError(u'Please only fill exact date or year and month or the range years')

解决方案

I wrote a custom widget and multi-value field to handle feet and inches: http://djangosnippets.org/snippets/2327/, and also another one that is a math captcha: https://github.com/btaylordesign/django-simple-math-captcha

I put my validation in the compress method of the MultiValueField, which worked great for these. You might have a look at that snippet and repo and see if that gets you on the right track.

这篇关于使用Django中的自定义MultiValueWidget验证MultiValueField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆