Django子类化multiwidget - 使用自定义multiwidget重建日期 [英] Django subclassing multiwidget - reconstructing date on post using custom multiwidget

查看:140
本文介绍了Django子类化multiwidget - 使用自定义multiwidget重建日期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我的django书回到大学,我正在努力工作这一个。



我已经子类 django.forms .widgets.MultiWidget like so:

  class DateSelectorWidget(widgets.MultiWidget):
def __init __(self,attrs = None,dt = None,mode = 0):
如果dt不是无:
self.datepos = dt
else:
self.datepos = date.today()

#bit的python创建天,月,年
#下面的例子,其余的剪切为整洁。

years = [(year,year)for year in year_digits]

_widgets =(
widgets.Select(attrs = attrs,choices = days),
widgets.Select(attrs = attrs,choices = months),
widgets.Select(attrs = attrs,choices = years),

super(DateSelectorWidget,self).__ init__ (_widgets,attrs)

def解压缩(self,value):
如果值:
return [value.day,value.month,value.year]
返回[无,无,无]

def format_output(self,rendered_widgets):
return u''join(rendered_widgets)
pre>

这给我一个漂亮的日期选择字段,如:



我的任务真的很简单。当我将表单提交给它的处理方法(使用这样的过程:

  forminstance = ModelNameForm(request.POST,instance = modelinstance)
如果forminstance.is_valid():
forminstance.save()

这样会失败,因为Django不知道如何使用我的多小部件并将其转换回底层的字段类型,它在 models.py 中设置为 DateField(),清楚。



现在,django源中的MultiWidget周围的评论给了我一个有用的提示:



您可能希望将此类与MultiValueField一起使用。



但事情是 - 我可能不会,我想保留我的 DateField()因为它是非常有用的,没有点重复它,我需要做的是以某种方式将这些多个字段转换成一个有效的数据



然后我的问题是: yyyy-mm-dd ) >

如何?实现这个的最好方法是什么?

解决方案

回答我自己的问题!



我实现了这个方法:

  def value_from_datadict(self,data,files,name):
datelist = [widget.value_from_datadict(data,files,name +'_%s'%i)\
for i,widget in enumerate(self.widgets)]
try:
D = date(day = int(datelist [0]),month = int(datelist [1]),\
year = int(datelist [2]))
返回str(D)
除ValueError外:
返回

value_from_datadict 从整个post datadict中提取所有子窗口小部件的数据。我所做的是提取出不同的日期,并使用date构造函数验证日期。如果它有效,我们以正确的格式打印字符串,否则我们返回一个空字符串

  forminstance.is_valid ()

将捕获。



当我这样做时,爱上它!


So my django book is back at university and I'm struggling to work this one out.

I've subclassed django.forms.widgets.MultiWidget like so:

class DateSelectorWidget(widgets.MultiWidget):
    def __init__(self, attrs=None, dt=None, mode=0):  
        if dt is not None:
            self.datepos = dt
        else:
            self.datepos = date.today()    

        # bits of python to create days, months, years
        # example below, the rest snipped for neatness.

        years = [(year, year) for year in year_digits]

        _widgets = (
            widgets.Select(attrs=attrs, choices=days), 
            widgets.Select(attrs=attrs, choices=months),
            widgets.Select(attrs=attrs, choices=years),
            )
        super(DateSelectorWidget, self).__init__(_widgets, attrs)

    def decompress(self, value):
        if value:
            return [value.day, value.month, value.year]
        return [None, None, None]

    def format_output(self, rendered_widgets):
        return u''.join(rendered_widgets)

Which gives me a nifty looking date selection field like so:

My queston is very simple really. When I submit said form to its handling method (which uses a process like this:

forminstance = ModelNameForm(request.POST, instance=modelinstance)
    if forminstance.is_valid():
        forminstance.save()

This fails, because Django doesn't know how to take my multi-widget and convert it back to the underlying field type, which is set in models.py to DateField(), clearly.

Now, the comments around the MultiWidget in the django source give me this useful hint:

You'll probably want to use this class with MultiValueField.

But the thing is - I probably don't. I want to keep my DateField() because it is very useful and there is no point duplicating it. What I need to do then is somehow convert these multiple fields back into a single valid datestring (yyyy-mm-dd) for insertion into the database.

My question is then:

How? What is the best way to achieve this?

解决方案

Answered my own question!

I implemented this method:

def value_from_datadict(self, data, files, name):
    datelist = [widget.value_from_datadict(data, files, name + '_%s' % i) \ 
                                      for i, widget in enumerate(self.widgets)]
    try:
        D = date(day=int(datelist[0]), month=int(datelist[1]), \
             year=int(datelist[2]))
        return str(D)
    except ValueError:
        return ""

value_from_datadict pulls the data of all the sub-widgets from the entire post datadict. What I've done is to extract out the various date counterparts, and use the date constructor to validate the date. If it is valid, we print the string out in the correct format, otherwise, we return an empty string which

forminstance.is_valid()

will catch.

I love it when I do this!

这篇关于Django子类化multiwidget - 使用自定义multiwidget重建日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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