专栏名称: 编程派
Python程序员都在看的公众号,跟着编程派一起学习Python,看最新国外教程和资源!
目录
相关文章推荐
Python爱好者社区  ·  1885页的Python完全版电子书 ·  2 天前  
Python开发者  ·  请立即拿下软考证书(政策风口) ·  3 天前  
Python爱好者社区  ·  张雪峰公司今年的年终奖... ·  4 天前  
Python爱好者社区  ·  推荐我的抖音变现俱乐部! ·  6 天前  
Python爱好者社区  ·  120道Python面试题.pdf ... ·  1 周前  
51好读  ›  专栏  ›  编程派

Flask 插件学习:Flask-WTF 和 WTForms 扩展

编程派  · 公众号  · Python  · 2017-07-19 11:30

正文

继续学习 Flask 插件。。

作者:孤独的自我;原文:https://segmentfault.com/a/1190000004502589

Flask - WTF Flask - SQLAlchemy 都是很好用的插件,然而当它们结合到一起后,就不是那么美妙了。

问题的提出

models . py 中定义了一个 Article Category Tag 类:

  1. class Article(db.Model):

  2.    """定义文章"""

  3.    __tablename__ = 'articles'

  4.    id = db.Column(db.Integer, primary_key=True)

  5.    title = db.Column(db.String(128), unique=True, index=True)

  6.    # 保存 md 格式的文本

  7.    content = db.Column(db.Text)

  8.    # 保存 html 格式的文本

  9.    content_html = db.Column(db.Text)

  10.    # 文章分类

  11.    category_id = db.Column(db.Integer, db.ForeignKey('categories.id'))

  12.     # 文章标签

  13.    tags = db.relationship(

  14.        'Tag', secondary='article_tag_ref', backref='articles')

  15. class Category(db.Model):

  16.    """文章分类"""

  17.    __tablename__ = 'categories'

  18.    id = db.Column(db.Integer, primary_key=True)

  19.    name = db.Column(db.String(128), unique=True)

  20.    articles = db.relationship('Article', backref='category', lazy='dynamic')

  21. class Tag(db.Model):

  22.    """文章标签"""

  23.    __tablename__ = 'tags'

  24.    id = db.Column(db.Integer, primary_key=True)

  25.    name = db.Column(db.String(128), unique=True)

  26. # 文章和标签的映射表 ,多对多关系

  27. article_tag_ref = db.Table('article_tag_ref',

  28.                           db.Column('article_id', db.Integer,

  29.                                     db.ForeignKey('articles.id')),

  30.                           db.Column('tag_id' ,  db.Integer,

  31.                                     db.ForeignKey('tags.id'))

  32.                           )

然后在 forms . py 中定义一个 ArticleForm 表单

  1. class ArticleForm(Form):

  2.    title = StringField(u"标题", validators=[Required()])

  3.    category = QuerySelectField(u"分类", query_factory=getUserFactory(['id', 'name']), get_label='name')

  4.    tags = StringField(u"标签", validators=[Required()])

  5.    content = PageDownField(u"正文", validators=[Required()])

  6.    submit = SubmitField(u"发布")

此时在处理表单的时候可以这样:

  1. form = ArticleForm()

  2. if form.validate_on_submit():

  3.    article = Article(title=from.data.title, content=form.data.content,category =form.category.data)

  4.    ...

等等,这样怎么处理 form . data . tags ?只有像下面这样写了:

  1. """

  2. :param tags:

  3.    标签列表,如 [u'测试',u'Flask']

  4. """

  5. def str_to_obj(tags):

  6.    r = []

  7.     for tag in tags:

  8.        tag_obj = Tag.query.filter_by(name=tag).first()

  9.        if tag_obj is None:

  10.            tag_obj = Tag(name=tag)

  11.        r.append(tag_obj)

  12.    return r

然后在上面的代码中加入:

  1. form = ArticleForm()

  2. if form.validate_on_submit():

  3.    article = Article(title=from.data.title, content=form.data.content, category=form.category.data, tags=str_to_obj(form.data.tags))  

这样是不是很难看,像 form . data . category 就是一个对象,为撒到 form . data . tags 了就不是了,还要专门写一个函数来坐一个转换?这个时候就有必要扩展 WTForms 中的表单了。

WTForms 入门

阅读 WTForms 文档,关于如何创建一个 TagListField,贴一下代码:

  1. class TagListField(Field):

  2.    widget = TextInput()

  3.    def _value(self):

  4.        if self.data:

  5.            return u', '.join(self.data)

  6.        else:

  7.             return u''

  8.    def process_formdata(self, valuelist):

  9.        if valuelist:

  10.            self.data = [x.strip() for x in valuelist[0].split(',')]

  11.        else:

  12.            self.data = []

简单了看了一下 WTForms 源码,大致搞清楚了上面代码两个方法的作用:

  1. _value The _value method is called by the TextInput widget to provide the value that is displayed in the form. 在初始化表单的时候,就是调用这个方法在表单中渲染数据

  2. process_formdata 表单提交时,处理该字段的数据。

编写 WTForm 扩展

根据上面的代码,将 TagListField 中的字符串转为 models . py 中定义的 Tag 对象即可:

  1. class TagListField(Field):

  2.    widget = TextInput()

  3.    def __init__(self, label=None, validators=None,

  4.                 **kwargs):

  5.        super(TagListField, self).__init__(label, validators, **kwargs)

  6.    def _value(self):

  7.        if self.data:

  8.            r = u''

  9.            for obj in self.data:

  10.                r  = self.obj_to_str(obj)

  11.             return u''

  12.        else:

  13.            return u''

  14.    def process_formdata(self, valuelist):

  15.         print 'process_formdata..'

  16.        print valuelist

  17.        if valuelist:

  18.            tags = self._remove_duplicates([x.strip() for x in valuelist[0].split(',')])

  19.            self.data = [self.str_to_obj(tag) for tag in tags]

  20.         else:

  21.            self.data = None

  22.    def pre_validate(self, form):

  23.        pass

  24.    @classmethod

  25.    def _remove_duplicates(cls, seq):

  26.        """去重"""

  27.        d = {}

  28.        for item in seq:

  29.            if item.lower() not in d:

  30.                d[item.lower()] = True

  31.                







请到「今天看啥」查看全文


推荐文章
Python爱好者社区  ·  1885页的Python完全版电子书
2 天前
Python开发者  ·  请立即拿下软考证书(政策风口)
3 天前
Python爱好者社区  ·  张雪峰公司今年的年终奖...
4 天前
Python爱好者社区  ·  推荐我的抖音变现俱乐部!
6 天前
Python爱好者社区  ·  120道Python面试题.pdf ,完全版开放下载
1 周前
今日房产  ·  外高桥再现4万多的房价
7 年前
汉阳投资  ·  【弱势】保护好本金!
7 年前
慈怀读书会  ·  会穿着的女人,才是真正的人生赢家
7 年前