Kingkk's Blog.

flask-学习记录

2018/06/21 Share

前言

等待漏洞审核和国赛名单真是个难熬的事情,目前已经等到麻木了
期间就决定学习一下flask,了解一下python web
之前学过一些Django,但是那时候还懵懵懂懂,而且Django封装了太多东西,那时候也就只能照着教程来依葫芦画瓢
然后这回打算从更加轻量级的flask入手,来学习python web

正文

不知道写啥就写博客系统呗,于是就花了两个星期左右时间写了一个博客系统
还是先上下项目的github地址

主要的功能在github里已经说清楚了,写博客主要是为了理清flask的运行逻辑,以及一些相互关系

目录结构

先上一下整个项目的目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
├─app
│ │ models.py
│ │ __init__.py
│ │
│ ├─admin
│ │ │ forms.py
│ │ │ views.py
│ │ │ __init__.py
│ │
│ ├─blog
│ │ │ forms.py
│ │ │ views.py
│ │ │ __init__.py
│ │
│ ├─member
│ │ │ forms.py
│ │ │ views.py
│ │ │ __init__.py
│ │
│ ├─static
│ │ ├─css
│ │ ├─fonts
│ │ ├─img
│ │ │ │
│ │ │ └─avatars
│ │ └─js
│ │
│ ├─templates
│ │ 404.html
│ │ base.html
│ │
│ ├─admin
│ │ admin.html
│ │ adminlog.html
│ │ article.html
│ │ base.html
│ │ index.html
│ │ login.html
│ │ password.html
│ │ user.html
│ │
│ ├─blog
│ │ article.html
│ │ base.html
│ │ index.html
│ │
│ └─member
│ articles.html
│ base.html
│ create.html
│ index.html
│ login.html
│ member.html
│ modify.html
│ password.html
│ register.html
│ update.html
│ userlog.html
└─manage.py

app init.py

重点在app的init.py中
不妨先来看下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
import os

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://root:@127.0.0.1/flask-blog"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SECRET_KEY'] = 'cc1df2e4-fd25-4a33-a7ae-9555f5e361b0'
app.config['UPLOAD_FOLDER'] = os.path.join(os.path.dirname(__file__),'static','img')
app.debug = True
db = SQLAlchemy(app)

from app.member import member
from app.admin import admin
from app.blog import blog

app.register_blueprint(member, url_prefix='/member')
app.register_blueprint(admin, url_prefix='/admin')
app.register_blueprint(blog, url_prefix='/')


@app.errorhandler(404)
def page_not_found(error):
return render_template('404.html'), 404

一开始是导入一些必要的库,然后用Flask(__name__)生成一个flask app
之后就是对app的一些配置信息

db = SQLAlchemy(app)将数据库和app绑定

app.register_blueprint(member, url_prefix='/member')
蓝图注册,将不同模块注册到不同的蓝图下(也就是所谓的目录),然后配置目录的前缀
如这里memebr模块下的url都是在/memeber下的

然后定义了一个app的404页面

models.py

models.py中主要是定义了数据类型

取一小部分看下

1
2
3
4
5
6
7
8
9
10
11
from . import db

class Userlog(db.Model):
__tablename__ = 'userlog'
id = db.Column(db.Integer, primary_key = True)
user_id = db.Column(db.Integer, db.ForeignKey('member.id'))
ip = db.Column(db.String(50))
addtime = db.Column(db.DateTime, index=True, default=datetime.now)

def __repr__(self):
return "<Userlog %r>" % self.id

导入了init.py中的db变量
继承了db.Model类,定义了一个数据类,对应了mysql中的一张表
然后__tablename__也就是表名,然后比变量对应着字段

可以重写一些函数,或者添加一写数据处理的函数

models.py也就对应着mvc中的整个Model数据层

modules init.py

然后接下来来看下模块中的__init__.py
由于三个模块都类似,取blog的看一下

1
2
3
4
5
from flask import Blueprint

blog = Blueprint('blog', __name__)

import app.blog.views

内容很简单,就三行
主要是调用了Blueprint蓝图方法,创建了一个blog变量,供init_.py中注册全局蓝图,以及views.py中注册子url
然后调用views.py中的内容

views.py

作为mvc中的Controller(其实我也不知道为什么要叫成views)是后台代码量的主要部分,处理着主要业务逻辑

取一小部分看一下

1
2
3
4
5
6
7
8
from . import blog
from flask import render_template, redirect, url_for, session, flash, request
from app.models import *

@blog.route('/')
def index():
articles = Article.query.all()
return render_template('blog/index.html', articles=articles)

init.py中导入blog蓝图变量,用于注册url`@blog.route(‘/‘)`

然后从flask中导入一些常用的变量

  • render_template 用于返回视图
  • redirect 进行重定向
  • url_for 动态构建url
  • session 就是服务器cookie
  • flash 消息闪现
  • request 请求变量,存放一些url,get、post参数之类

然后从models.py中导入全部数据类型

接下来就是注册url为根url
然后从Article数据类型中筛选出全部字段
然后返回templates目录下blog/index.html,并注册articles变量

视图层

flask视图层自带着jinja2
语法也是特别好用

常用语法

1
2
3
4
5
- {% extends 'base.html' %} 页面继承
- {% if %} {% elif %} {% else %} {% endif %} if判断语句
- {% for i in xxx %} {% endfor %} for循环
- {{ variable }} 变量输出
- {{ variable|safe }} 变量输出(不html编码)

然后在views.py中引入了的函数名也可以直接引用

forms.py

涉及到和表单打交道时就免不了数据校验
flask中单独把数据校验这块拿了拿出(django中似乎也是)

forms.py中会继承wrforms中的Form,新建一个自定义表单类

1
2
3
4
5
6
7
8
class LoginForm(Form):
username = TextField('username', [validators.Required()])
password = PasswordField('password', [validators.Required()])

def validate_username(self, field):
user = Admin.query.filter_by(username=field.data).count()
if user == 0:
raise ValidationError("username does not exist.")

或者可以添加自定义校验函数,实现更复杂的数据校验

在views.py中会对post或者get的数据传入这个LoginForm中form = LoginForm(request.form)
然后调用form的validate()方法,通过数校验时返回True,否则返回False
失败时也可以通过form.errors获取具体的错误原因

bootstrap

这个本来属于前端的东西,我这里要说一下的原因就在于,我也是通过写这个小系统才熟悉的bootstrp

bootstrap只需要在html开头导入几个文件,即可利用class标签,生成对应的css和js样式,极其方便

整个html主要是以div标签为切块,然后利用col-md-x进行栅格排列,还有col-md-offset-x进行位移
使得整个页面的布局变得简单,然后还有一些container btn danger info之类的标签,使得央视的更改也变得简易

更多的详情见官方手册好了,毕竟那么多标签我也记不住(逃。。。

启动

启动app的工作就在manage.py中,其实也很简单

1
2
3
4
from app import app

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

只要运行app变量的run方法即可,实际上线时记得关闭debug模式即可

CATALOG
  1. 1. 前言
  2. 2. 正文
    1. 2.1. 目录结构
    2. 2.2. app init.py
    3. 2.3. models.py
    4. 2.4. modules init.py
    5. 2.5. views.py
    6. 2.6. 视图层
    7. 2.7. forms.py
    8. 2.8. bootstrap
    9. 2.9. 启动