Zope.Schema / Plone - 如何在updateWidget函数中设置Datetime字段的值?

时间:2014-11-14 01:42:15

标签: python plone zope

在我正在处理的plone网站上,我有一个表单,用于编辑存储映射到后端数据库中的表的对象的记录。在接口类中,其中一个字段是schema.Datetime字段。

class ICalibration(Interface):
"""Interface class for calibration records
"""
...
    Last_Calibration = schema.Datetime(title=u"Last Calibration"
                                       description=u"date of last calibration",


                                      )
...

在我的updateWidgets函数中,在编辑表单中,我尝试设置小部件的值,

class EditCalibration(form.Form):
    grok.name('edit-calibration')
    grok.require('zope2.View')
    grok.context(ISiteRoot)

    def updateWidgets(self):
        super(EditCalibration, self).updateWidgets()
        id = self.request.get('id',None)

        if id:
            currentCal = session.query(Calibration).filter(Calibration.Calibration_ID == id).one()

            ...
            self.widgets["Last_Calibration"].value = currentCal.Last_Calibration
        ...

但是我收到了这个错误:

" TypeError:' datetime.datetime'对象没有属性' getitem '。

我确实尝试过一些有趣的事情。 我打印了cal.Last_Calibration的值,它是我添加记录时输入的日期。
我尝试打印cal.Last_Calibration的对象类型,这是python的日期时间(而不是zope,我相信?)。 我尝试将字段设置为等于今天的日期:datetime.today()并得到相同的错误。 只是为了踢,我还尝试将currentCal.Last_Calibration转换为字符串并将其传递到字段中,尽管这只是将随机数放在字段中。

为了记录,我将python的日期时间导入为:

from datetime import datetime

此外,添加记录/校准工作正常,因此它不是数据库或我正在使用的sqlalchemy架构的问题。

如果可能,在updateWidgets函数中设置架构字段值的适当方法是什么?

我应该使用不同的小部件吗?如果是这样,我真正需要的就是日期。 add / update函数将采用datetime对象,因此无论我认为哪种类型,我都可以从数据中创建一个datetime对象。

1 个答案:

答案 0 :(得分:3)

在z3c.form框架中,发生以下步骤以获取窗口小部件值:

  1. 如果请求已有值(来自之前的表单提交),则使用该值。
  2. 如果form.ignoreContext == False(默认值),则调用form.getContent()以获取"内容对象"表单正在编辑(默认为form.context)。
  3. 如果内容对象提供了字段来自的架构界面,则"字段值"将被提取为对象的属性。 (如果它不提供模式接口,z3c.form将查找对象的适配器到模式接口,并获取适配器上的属性。如果内容对象是dict,则字段值将作为项目获取dict而不是使用属性查找。)
  4. A"转换器"基于字段类型和窗口小部件类型用于将字段值转换为窗口小部件值。区别在于字段值是实际存储的值,而窗口小部件值是该值的字符串序列化。
  5. 您的问题是您正在尝试将窗口小部件值设置为日期时间,而不是窗口小部件所期望的该日期时间的序列化。

    我会通过覆盖getContent而不是updateWidgets来做你想要做的事情:

    from five import grok
    from plone.directives import form
    
    class EditCalibration(form.SchemaForm):
        grok.name('edit-calibration')
        grok.require('zope2.View')
        grok.context(ISiteRoot)
    
        schema = ICalibration
    
        def getContent(self):
            id = self.request.get('id', None)
            if id:
                return session.query(Calibration).filter(Calibration.Calibration_ID == id).one()
    

    您还需要声明您的Calibration类实现了ICalibration接口,以便z3c.form识别出它可以将Last_Calibration作为Calibration实例的属性。这应该是这样的:

    from zope.interface import implementer
    
    @implementer(ICalibration)
    class Calibration(Base):
        etc...