Django子类化multiwidget - 使用自定义multiwidget重建帖子日期

Posted

技术标签:

【中文标题】Django子类化multiwidget - 使用自定义multiwidget重建帖子日期【英文标题】:Django subclassing multiwidget - reconstructing date on post using custom multiwidget 【发布时间】:2011-06-07 11:07:46 【问题描述】:

所以我的 django 书回到了大学,我正在努力完成这本书。

我已经像这样子类化了django.forms.widgets.MultiWidget

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)

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

我的问题真的很简单。当我将所述表单提交给它的处理方法时(使用这样的过程:

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

这失败了,因为 Django 不知道如何获取我的 multi-widget 并将其转换回基础字段类型,该类型设置在 models.pyDateField() 中,很明显。

现在,django 源中 MultiWidget 周围的 cmets 给了我这个有用的提示:

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

但问题是——我可能不知道。我想保留我的DateField(),因为它非常有用,而且没有必要复制它。然后我需要做的是以某种方式将这些多个字段转换回单个有效的日期字符串 (yyyy-mm-dd) 以插入到数据库中。

我的问题是:

怎么样?实现这一目标的最佳方法是什么?

【问题讨论】:

【参考方案1】:

回答了我自己的问题!

我实现了这个方法:

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从整个post datadict中拉取所有子widget的数据。我所做的是提取出各种日期对应项,并使用日期构造函数来验证日期。如果有效,我们以正确的格式打印字符串,否则,我们返回一个空字符串

forminstance.is_valid()

会抓到的。

我喜欢这样做!

【讨论】:

以上是关于Django子类化multiwidget - 使用自定义multiwidget重建帖子日期的主要内容,如果未能解决你的问题,请参考以下文章

在 Django 中仅渲染 MultiWidget 的一部分

在 Django 中仅渲染 MultiWidget 的一部分

Django MultiWidget 电话号码字段

Twitter Bootstrap 的 Django 和日期范围选择器组件

子类化 Django ListView

为 django 1.5 自定义用户模型子类化 django-registration 1.0 表单