Flask wtforms访问和编辑配置数据

时间:2014-10-01 19:48:18

标签: datetime flask wtforms

我正在使用带有烧瓶框架的wtforms。当我使用DateTimeField时我添加格式参数。 但是日期时间格式来自用户登录

forms.py

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。 解决这个问题的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

哦,我看到了您的问题,您想要的日期格式会根据请求进行更改。 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子类Form。这完全没问题。)

答案 1 :(得分:0)

我不确定当你这样做时是否会正确配置。您的app.config可能不在应用中,因为您制作它的结构。你是否像app = Flask(__name__)那样进行了导入?

您可以使用应用工厂模式解决此问题

# app/__init__.py
def create_app():
  app = Flask(__name__)
  app.config.from_object('app.settings.default')

  from app.yourforms import bp
  app.register_blueprint(bp)

  return app

您可以在单独的文件中制作蓝图,如下所示:

# yourforms/__init__.py
from flask import Blueprint
bp = Blueprint('forms', __name__)
from . import views

然后在同一目录的views.py文件中,使用蓝图

from flask import current_app
from . import bp
from .forms import PostForm

@bp.before_app_request
def set_datetime_format():
  # your code
  # access app's config with current_app.config.get('YOURKEY')

那么你只需稍微调整一下你的runfile就可以了:

if __name__ == '__main__':
  app = create_app()
  app.run()