我在烧瓶框架中使用wtforms。当我使用DateTimeField时,我添加了格式参数。
但是datetime格式来自登录的用户

表格

from flask import g
from wtforms import *
import wtforms.validators as v
from flask.ext.babel import lazy_gettext as _
from flask.ext.babel import npgettext as _n

from app.app import app
from app.base_forms import *
from app.modules.post.models import *

class PostForm(BaseForm):
    post_date = DateTimeField("Post Date", format = app.config.get("DATETIME_FORMAT"), validators =[v.Required(message=_("Post date is required"))]  )


我在请求之前将app.config.get(“ DATETIME_FORMAT”)的值设置为

@app.before_request
def before_request():
    if g.user.language == "tr"
        app.config["DATETIME_FORMAT"] = "%d.%m.%Y %H:%M"
    else:
        app.config["DATETIME_FORMAT"] = "%m-%d-%Y %H:%M"


我的应用程序结构

/app
    /modules
        /post
            /controllers.py
            /forms.py
            /models.py
    /app.py
/run.py


/app/app.py的内容

from flask import Flask, url_for, g, request, redirect, render_template
app = Flask(__name__)
app.config.from_object('app.config.config.ConfigDevelopment')

# Import Modules
from modules.post.controllers.admin import module as modulePostAdmin
app.register_blueprint(modulePostAdmin)

# other codes here

@app.before_request
def before_request():
    if g.user.language == "tr"
        app.config["DATETIME_FORMAT"] = "%d.%m.%Y %H:%M"
    else:
        app.config["DATETIME_FORMAT"] = "%m-%d-%Y %H:%M"


/run.py的内容

from app.app import app
app.run(host='localhost', port=8080, debug=True)


当我启动应用程序时,它将引发该错误“ KeyError:'DATETIME_FORMAT'”。我认为forms.py在请求之前加载,因此它抛出keyError。
解决此问题的正确方法是什么?

最佳答案

哦,我看到了您的问题,您想要的日期格式正在根据每个请求进行更改。 app.config对此无济于事。

这是我会做的:

from flask import g
from wtforms import DateTimeField


class I18NDateTimeField(DateTimeField):
    def __init__(self, label=None, validators=None, format=None, **kwargs):
        if g.user.language == "tr"
            format = "%d.%m.%Y %H:%M"
        else:
            format = "%m-%d-%Y %H:%M"
        super(I18NDateTimeField, self).__init__(label=label, validators=validators, format=format, **kwargs)


class PostForm(Form):
    post_date = I18NDateTimeField("Post Date", validators =[v.Required(message=_("Post date is required"))]  )


背景

您(大部分)是正确的,尚未调用before_request。就是说,表单定义根本不会在请求上下文中发生,而是在导入应用程序时发生,很久没有任何请求到达,并且不会发生多次。

但是,将针对每个请求再次实例化表单及其字段,这就是为什么它起作用的原因。可以在此处修改self.format,因为无论如何该字段对象仅用于此请求。

更新2:

我编辑了对子类Form而不是BaseForm的答案。 BaseForm是WTForms的低级API的一部分;他们说不要使用它,除非您确定需要。我还将国际化逻辑放在构造函数中,而不是在process_formdata中(感谢#pocoo的mattupstate提出这个想法)。

我认为这样更清晰一些,在调试器中检查字段将更有意义。现在,以编写代码的方式,您希望在定义表单时将该字段实例化为类属性,这意味着它将不起作用,并且此代码也不是线程安全的。但是由于一些元类的欺骗,实例化表单时,该字段实际上被实例化为实例属性。请注意,如果您使用BaseForm,则该元类的欺骗方法无法正常工作,这是避免使用BaseForm的另一个原因。

更新3:

抱歉,刚刚在IRC上与您交谈,发现您编写了自己的BaseForm,该BaseForm继承了Form。很好:)

07-27 17:37