読者です 読者をやめる 読者になる 読者になる

<Python, flask> WTForms をもうちょい研究。

WTFromsをもうちょい研究。

ちと試しにWTFormsでオブジェクト作ってメンバーでも見てみようかと思った。

In [81]: from wtforms import TextAreaField, SubmitField

In [82]: class PostForm(Form):
    ...:     body = TextAreaField('Hi')
    ...:     submit = SubmitField('Submit')
    ...:     

で、インスタンス化。

In [83]: form = PostForm()
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-83-458f710775b9> in <module>()
----> 1 form = PostForm()

C:\Anaconda3\Lib\site-packages\wtforms\form.py in __call__(cls, *args, **kwargs)
    210                     bases.append(mro_class.Meta)
    211             cls._wtforms_meta = type('Meta', tuple(bases), {})
--> 212         return type.__call__(cls, *args, **kwargs)
    213 
    214     def __setattr__(cls, name, value):

C:\Anaconda3\Lib\site-packages\flask_wtf\form.py in __init__(self, formdata, obj, prefix, csrf_context, secret_key, csrf_enabled, *args, **kwargs)
     66 
     67         if csrf_enabled is None:
---> 68             csrf_enabled = current_app.config.get('WTF_CSRF_ENABLED', True)
     69 
     70         self.csrf_enabled = csrf_enabled

C:\Anaconda3\Lib\site-packages\werkzeug\local.py in __getattr__(self, name)
    341         if name == '__members__':
    342             return dir(self._get_current_object())
--> 343         return getattr(self._get_current_object(), name)
    344 
    345     def __setitem__(self, key, value):

C:\Anaconda3\Lib\site-packages\werkzeug\local.py in _get_current_object(self)
    300         """
    301         if not hasattr(self.__local, '__release_local__'):
--> 302             return self.__local()
    303         try:
    304             return getattr(self.__local, self.__name__)

C:\Anaconda3\Lib\site-packages\flask\globals.py in _find_app()
     32     top = _app_ctx_stack.top
     33     if top is None:
---> 34         raise RuntimeError('working outside of application context')
     35     return top.app
     36 

RuntimeError: working outside of application context

ゲロる。
application contextの枠外だと、、

え、そうなん、、、app作らないとあかんの???
ちゃっと確認できんのかな、、と悩むこと小一時間。
もしかして、前に、みげるの本で読んだ Flask-Scriptでできるんちゃうか?
と、思ったので、試す。

>git clone https://github.com/miguelgrinberg/flasky
>cd flasky
>git checkout 8d

で、

>python manage.py shell

で、

>>> from wtforms import TextAreaField, SubmitField, Form
>>> class PostForm(Form):
...   body = TextAreaField('Hi')
...   submit = SubmitField('Submit')
...
>>> form = PostForm()

お!、エラーがでない。
なら、

>>> dir(form)
['Meta', '__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_errors', '_fields', '_get_translations', '_prefix', '_unbound_fields', '_wtforms_meta', 'body', 'data', 'errors', 'meta', 'populate_obj', 'process', 'submit', 'validate']

やり、いけるね!
なら、メンバーを見てみる。

>>> form
<PostForm object at 0x2ad5659a47f0>

>>> form._fields
OrderedDict([('body', <wtforms.fields.simple.TextAreaField object at 0x2ad5659a48d0>), ('submit', <wtforms.fields.simple.SubmitField object at 0x2ad5659a4898>)])

>>> form._unbound_fields
[('body', <UnboundField(TextAreaField, ('Hi',), {})>), ('submit', <UnboundField(SubmitField, ('Submit',), {})>)]

>>> form._prefix
''

>>> form._wtforms_meta
<class 'wtforms.form.Meta'>

>>> form.body
<wtforms.fields.simple.TextAreaField object at 0x2ad5659a48d0>

>>> form.submit
<wtforms.fields.simple.SubmitField object at 0x2ad5659a4898>

ふーん、なるほど。
で、メソッド実行してみる。

>>> form.submit()
'<input id="submit" name="submit" type="submit" value="Submit">'

>>> form.body()
'<textarea id="body" name="body"></textarea>'

ははー。
やはし思ったとおり、htmlコードを吐くんだ。
なるほど~。おもしろい。