看过Django后回头来看Flask 1

首先给大家推荐一下我老师大神的人工智能教学网站。教学不仅零基础,通俗易懂,而且非常风趣幽默,还时不时有内涵黄段子!点这里可以跳转到网站

用了Django后回头来看看FLASK,把一些值得写的区别和体会记录下来,加深一下印象和理解,写完对比再来写Flask源码的

1.表单

Flask表单有更加方便的实现方法Flask-WTF这个扩展让搞起FLASK的表单轻松加愉快
使用 Flask-WTF 时,每个 Web 表单都由一个继承自 Form 的类表示。这个类定义表单中的一组字段,每个字段都用对象表示。字段对象可附属一个或多个验证函数。验证函数用来验证用户提交的输入值是否符合要求。

from flask.ext.wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required

class NameForm(Form):
    name = StringField('What is your name?', validators=[Required()])
    submit = SubmitField('Submit')

表单字段是可调用的,在模板中调用后会渲染成 HTML,视图函数把NameForm实例通过参数form传给模版,模版就可以直接生成表单,Flask-Bootstrap 提供了一个非常高端的辅助函数,可以使用 Bootstrap 中预先定义好的表单样式渲染整个 Flask-WTF 表单,极大的提升了效率

{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}

这里有一点需要注意,我们使用了{{ wtf.quick_form(form) }}之后不用手动指定form的action了,那么submit的时候提交到哪里去呢?答案是跳转到这个html页面的那个视图函数,这里有个非常好的写法是把接收form的处理和不接受form的直接跳转写到一个视图函数里面
视图函数中怎么接收提交的数据呢?实例化一个NameForm类的实例来表示表单,实例.name.data就可以啦

@app.route('/', methods=['GET', 'POST'])
def index():
    name = None
    form = NameForm()
    if form.validate_on_submit():
        name = form.name.data
        form.name.data = ''
    return render_template('index.html', form=form, name=name)

Django中获取表单数据常用request.POST[‘name’],而且视图函数需要接收request参数,Flask里面就不用啦,Flask里面request我们可以当成一个每个请求的全局变量,不用传参给视图函数也可以使用的

2.ORM

暂时不探讨兼容,性能等,从学习阶段来说个人感觉Django的ORM比狗书里面使用的 Flask-SQLAlchemy方便一些
暂时忽略py2和py3差别,我们先通过定义models.py的过程对比下

# Create your models here.
class AchievementYear(models.Model):
    achievement_date = models.CharField(max_length=8,verbose_name='成就年')
    achievement_author = models.ForeignKey('auth.User', blank=True, null=True, verbose_name='作者')  # 外键不能直接写别名
    achievement_summary = models.CharField('成就年总结', blank=True, null=True, max_length=50)

    def __unicode__(self):
        return self.achievement_date
    class Meta:
        verbose_name = '成就年'
        verbose_name_plural = '成就年'
class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    def __repr__(self):
        return '<Role %r>' % self.name
class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    def __repr__(self):
        return '<User %r>' % self.username

Django中的一对多关系直接用models.ForeignKey,比如下面的一个分类对应多个问题,只需在问题中指定分类外键

# Create your models here.

class QuestionCategory(models.Model):
    category_name = models.CharField('问题分类',max_length=50)

    def __unicode__(self):
        return self.category_name
    class Meta:
        verbose_name = '问题分类'
        verbose_name_plural = '问题分类'


class Question(models.Model):
    question_category = models.ForeignKey(QuestionCategory,verbose_name="归属分类")
    question_title = models.CharField('标题', max_length=50)
    question_author = models.ForeignKey('auth.User', blank=True, null=True,verbose_name='作者')#外键不能直接写别名
    question_keywords = models.CharField('关键词',max_length=20)
    question_date = models.DateTimeField('发表时间', auto_now=True)
    question_text = models.CharField('正文内容', max_length=200)

    def __unicode__(self):
        return self.question_title

    class Meta:
        verbose_name = '技术问题'
        verbose_name_plural = '技术问题'

Flask中的一对多关系定义的时候麻烦一点,看下面狗书的例子,一个角色可以对应多种用户,需要在用户中指定角色外键,另外在角色中还需要用db.relationship来指定关系的另一端是哪个模型,指定之后,角色中的users属性就讲返回与角色关联的用户组成的列表
另外这里面的backref在用户表中添加一个role属性,从而反向定义关系,这一属性可以替代role_id来访问角色,用它来访问的话获取到的是模型对象,不只是外键的键值了

class Role(db.Model):
        # ...
        users = db.relationship('User', backref='role')
class User(db.Model):
        # ...
        role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

Django里面,咱们创建的时候,直接创建或者save就行了,之前写过

#一共四种方法

from blog.models import Blog,Author,Entry

#第一种
Author.objects.create(name="zhangkun", email="lalalal@qq.com")

#第二种
zk = Author(name="zhangkun", email="lalalal@qq.com")
zk.save()

#第三种
zk = Author()
zk.name="zhangkun"
zk.email="lalalal@qq.com"
zk.save()

#第四种 先读,不存在就创建,防止重复
Author.objects.get_or_create(name="zhangkun", email="lalalal@qq.com")
# 返回值(object, True/False),创建时返回 True, 已经存在时返回 False

但是Flask里面因为不自带ORM嘛,狗书说 在 Flask-SQLAlchemy 中,数据库会话由 db.session表示。准备把对象写入数据库之前,先要将其添加到会话中:

>>> db.session.add(admin_role)
>>> db.session.add(mod_role)
>>> db.session.add(user_role)
>>> db.session.add(user_john)
>>> db.session.add(user_susan)
>>> db.session.add(user_david)

或者简写成:

>>> db.session.add_all([admin_role, mod_role, user_role,
... user_john, user_susan, user_david])

为了把对象写入数据库,我们要调用 commit() 方法提交会话:

>>> db.session.commit()

但最终代码量差不多的,平时可能还会需要多表连接和一些方法之类的东西,不过Django自带后台,和modles.py中的数据模型深度结合,定制方便,从这一点上来说优势就非常明显了

3.应用的管理

Django中非常方便,startapp新建一个就是一个应用了,新建好之后seeting.py里面注册好,urls.py里面include一下新的应用的urls.py就可以用了,但是Flask中呢?
不怕,Flask我们有蓝本,也叫蓝图!
有了Django经验理解起来就容易了,新建一个蓝本当作Django应用当中的新建应用startapp一样,蓝本里面可以有自己的模板,静态目录,有自己的视图函数和URL规则,蓝本之间互相不影响。但是它们又属于应用中,可以共享应用的配置。对于大型应用来说,我们可以通过添加蓝本来扩展应用功能,而不至于影响原来的程序

4.Django把一些小功能都做好了

比如说用户系统,Django自带啊,创建的密码Django也是自动加密处理的,嗯,很省心
Flask里面,就需要借用Flask-Login来搞一搞喽,但是各有各的好

5.template模版的存放位置

Django
Flask

Django里面,咱们可以每新建一个应用就在新的应用下建立templates文件夹存放这个应用所需的html文件,也就是模版文件,但是在FLask里面呢,一般都是都放在一块的,那怎么保证不乱呢,当然也是用文件夹区分了!


总结:Flask里面虽然有蓝本来区分不同功能的应用,但是模版html文件一般不放在蓝本文件夹里面,是都放在和蓝本同级的一个特定的templates文件夹下面的,我们当然也有办法将蓝本配置成使用其独立的文件夹保存模板。但是如果配置了多个模板文件夹, 视图函数中render_template() 函数会首先搜索程序配置的模板文件夹,然后再搜索蓝本配置的模板文件夹。曲线救国了哦,让人家找一次就够啦(๑•́ ₃ •̀๑)

6.请求拦截

Django里面有各种中间件middleware,可以自定义,在Flask中我们可以通过钩子来实现

有空继续写,最近一直搞Django,是时候回头用用Flask写点东西了,写个什么好呢?

点这里可以跳转到人工智能网站