测开之路一百四十一:蓝图实现程序模块化

把每一个模块独立出来,然后在主app里面注册,这样就实现了模块之间互不干扰

新建蓝图

artcle.views.py

"""
article蓝图
"""
from flask import request, render_template, redirect, url_for
from flask import Blueprint

article = Blueprint('article', __name__)


@article.route('/articles/')
def article_list():
return render_template('article-list.html')


@article.route('/articles/<id>/')
def articles_id(id=None):
item = {'id': id}
return render_template('artocle-detail.html', item=item)

artcle-list.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文章列表</title>
</head>
<body>
<h1>文章列表</h1>

</body>
</html>

artcle-detail.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文章信息</title>
</head>
<body>
<h1>文章标题{{ item.id }}</h1>
</body>
</html>

注册蓝图:app.register_blueprint(蓝图名)

main.py

请求

蓝图下基于类和方法的视图

"""
article蓝图
"""
from flask import request, render_template, redirect, url_for
from flask import Blueprint
from flask.views import MethodView

article = Blueprint('article', __name__)


class ArticleList(MethodView):
def get(self):
return render_template('article-list.html')

def post(self):
pass


class ArticlesId(MethodView):
def get(self, id=None):
item = {'id': id}
return render_template('artocle-detail.html', item=item)


article.add_url_rule('/articles/', view_func=ArticleList.as_view('article_list'))
article.add_url_rule('/articles/<int:id>/', view_func=ArticlesId.as_view('articles_id'))

# @article.route('/articles/')
# def article_list():
# return render_template('article-list.html')


# @article.route('/articles/<id>/')
# def articles_id(id=None):
# item = {'id': id}
# return render_template('artocle-detail.html', item=item)

前面已经注册artcle,所以不用管,直接访问

注册蓝图时加默认前缀,实现模块分类

新建一个product蓝图

"""
product蓝图
"""

from flask import Blueprint

product = Blueprint('product', __name__)


@product.route('/') # 由于注册蓝图时已添加前缀products, 所以访问时真实路径为/products/
def product_list():
return '产品列表页'


@product.route('/id/') # 由于注册蓝图时已添加前缀products, 所以访问时真实路径为/products/id/
def product_id(id=None):
return '产品详情' + str(id)

主入口里面注册

访问

蓝图生成链接重定向

找到蓝图注册名和要重定向的终结点

在base.html里面添加中定向:蓝图名.终结点名

article蓝图

"""
article蓝图
"""
from flask import request, render_template, redirect, url_for
from flask import Blueprint
from flask.views import MethodView

article = Blueprint('article', __name__)


class ArticleList(MethodView):
def get(self):
return render_template('article-list.html')

def post(self):
pass


class ArticlesId(MethodView):
def get(self, id=None):
item = {'id': id}
return render_template('artocle-detail.html', item=item)


article.add_url_rule('/', view_func=ArticleList.as_view('article_list'))
article.add_url_rule('/<int:id>/', view_func=ArticlesId.as_view('articles_id'))

# @article.route('/articles/')
# def article_list():
# return render_template('article-list.html')


# @article.route('/articles/<id>/')
# def articles_id(id=None):
# item = {'id': id}
# return render_template('artocle-detail.html', item=item)


product蓝图

"""
product蓝图
"""

from flask import Blueprint

product = Blueprint('product', __name__)


@product.route('/') # 由于注册蓝图时已添加前缀products, 所以访问时真实路径为/products/
def product_list():
return '产品列表页'


@product.route('/id/') # 由于注册蓝图时已添加前缀products, 所以访问时真实路径为/products/id/
def product_id(id=None):
return '产品详情' + str(id)



main.py

# coding:utf-8
import sqlite3
from datetime import datetime, timedelta
from flask import Flask, request, render_template, redirect, url_for, g, send_from_directory, session, make_response

app = Flask(__name__)

DATABASE = r'.\db\feedbach.db'

'=======================封装sql助手函数============================='


def make_dicts(cursor, row):
""" 将游标获取的Tuple根据数据库列表转换为dict """
return dict((cursor.description[idx][0], value) for idx, value in enumerate(row))


def get_db():
""" 获取(简历数据库链接)
g: flask内置的变量:g = LocalProxy(partial(_lookup_app_object, "g"))
"""
db = getattr(g, '_database', None)
if not db:
db = g._database = sqlite3.connect(DATABASE)
db.row_factory = make_dicts
return db


def execute_sql(sql, params=()):
""" 执行sql语句不返回数据结果 insert、update、delete """
c = get_db().cursor()
c.execute(sql, params)
c.connection.commit()


def query_sql(sql, params=(), one=False):
""" 查询数据 one=False的时候返回多条"""
c = get_db().cursor()
result = c.execute(sql, params).fetchall()
c.close()
return (result[0] if result else None) if one else result


@app.teardown_appcontext # 在当前app上下文销毁时执行
def close_connection(exeption):
""" 关闭数据库 """
db = getattr(g, '_database', None)
if db is not None:
db.close()


'========================================================================'


@app.route("/")
def index():
return render_template('base.html')


app.secret_key = 'qoihf2397r21380r2/./ad' # 加密的安全码,越复杂越好,flask后台自动进行加密


# @app.route('/login/', methods=['GET', 'POST'])
# def login():
# """ 登录 """
# if request.method == 'POST':
# username = request.form.get('username')
# password = request.form.get('password')
# sql = 'select count(*) as [Count] from UserInfo where username = ? and password = ?'
# result = query_sql(sql, (username, password), True)
# if int(result.get('Count')) > 0:
# print(username)
# session['admin'] = username # 已登录的用户保存到session
# return redirect(url_for('list'))
# return '用户名或密码错误'
# return render_template('login.html')


# 模板继承
@app.route("/feedback/")
def feedback():
return render_template('post.html')


UPLOAD_FOLDER = r'.\uploads' # 声明存文件的目录
ALLOWED_EXTENSIONS = ['.jpg', '.png', '.gif'] # 允许上传的后缀,限制上传格式

import os


def allowed_file(filename):
""" 判断文件是否允许上传 """
# filename = 'asdasdasd.jpg'
_, ext = os.path.splitext(filename)
return ext.lower() in ALLOWED_EXTENSIONS # 把后缀转为小写


@app.route("/post_feedback/", methods=["POST"])
def post_feedback():
""" 提交视图 """
if request.method == 'POST': # 如果是post请求就获取表单值
subject = request.form.get('subject', None)
categoryid = request.form.get('category', 1)
username = request.form.get('username')
email = request.form.get('email')
body = request.form.get('body')
release_time = str(datetime.now())
state = 0
img_path = None
# 提交的内容包含图片,就获取图片名字用于插入数据库,并保存图片
if request.files.get('file_s', None):
img = request.files['file_s']
if allowed_file(img.filename):
# 为防止文件名重复,重命名文件
img_path = datetime.now().strftime('%Y%m%d%H%M%f') + os.path.splitext(img.filename)[1]
img.save(os.path.join(UPLOAD_FOLDER, img_path))
print(subject, categoryid, username, email, body, state, release_time, img_path)
conn = sqlite3.connect(DATABASE)
c = conn.cursor()
# 防止sql注入,用?代替值
sql = "insert into feedback (Subjeck, CategoryID, UserName, Email, Body, State, ReleaseTime, Image) values (?,?,?,?,?,?,?,?)"
c.execute(sql, (subject, categoryid, username, email, body, state, release_time, img_path))
conn.commit()
conn.close()
# 为防止因卡顿引起重复提交,提交过后跳转到填写页面
return redirect(url_for('feedback'))


@app.route("/list/")
def list():
""" 展示所有问题 """
# 访问/list/的时候,如果session里面没有admin,就返回登录页
if session.get('admin', None) is None:
return redirect(url_for('login'))
key = request.args.get('key', '')
sql = 'select f.ROWID,f.*,c.CategoryName from feedback f INNER JOIN category c on c.ROWID = f.CategoryID where f.Subjeck like ? order by f.ROWID'
feedbacks = query_sql(sql, (f'%{key}%',))
return render_template('feedback-list.html', items=feedbacks)


@app.route('/del/<id>/')
def delete_feedback(id=0):
""" 删除问题 ,前端传id"""
conn = sqlite3.connect(DATABASE)
c = conn.cursor()
sql = "delete from feedback where ROWID = ?"
c.execute(sql, (id,))
conn.commit()
conn.close()
return redirect(url_for('list'))


@app.route('/profile/<filename>')
def render_file(filename):
""" 呈现特定目录下的资源,用于jinja2模板调用渲染服务器的图片"""
return send_from_directory(UPLOAD_FOLDER, filename) # uploads + feilename


@app.route("/edit/<id>/")
def edit(id=None):
""" 根据前端传过来的id返回编辑的html """
# 访问/edit/<id>/的时候,如果session里面没有admin,就返回登录页
if session.get('admin', None) is None:
return redirect(url_for('login'))
# 获取绑定的下拉列表
sql = "select ROWID,CategoryName from category"
categories = query_sql(sql)
# 获取当前id的信息,并绑定至form表单,以备修改
sql = "select rowid,* from feedback where rowid = ?"
curren_feedback = query_sql(sql, (id,), True)
# return str(curren_feedback) # 查看查出来的数据顺序,方便html渲染排序
return render_template('edit.html', categories=categories, item=curren_feedback)


@app.route("/save_edit/", methods=['POST'])
def save_edit():
""" 保存编辑 """
if request.method == 'POST':
id = request.form.get('rowid', None)
reply = request.form.get('reply')
state = 1 if request.form.get('state', 0) == 'on' else 0
sql = 'update feedback set Reply=?, State=? where rowid=?'
conn = sqlite3.connect(DATABASE)
c = conn.cursor()
c.execute(sql, (reply, state, id))
conn.commit()
conn.close()
return redirect(url_for('list'))


@app.route('/logout/')
def logout():
""" 退出登录,删除session跳转到登录页 """
session.pop('admin')
return redirect(url_for('list')) # 为了防止在页面上点后退的情况,让list视图来执行让页面跳转到登录页


@app.route('/setck/')
def setck():
""" 添加cookie,timedelta由datatime导入 """
response = make_response('ok')
response.set_cookie('username', 'aaa', path='/', expires=datetime.now() + timedelta(days=7))
# set_cookie 参数
# dmain='baidu.com' 指定cookie只对baidu.com起作用
# path='/' 此cookie能访问的路径
# httponly=True 只能http访问,默认关闭
# max_age=60 cookie生命周期,默认为None,浏览器关闭时销毁,单位为秒
# expires=datetime.now() + timedelta(days=7) # 指定过期时间为7天
return response


@app.route('/getck/')
def getck():
""" 获取cookie request.cookies.get('xxx') """
ck = request.cookies.get('username')
if ck:
return ck
return '未获取到cookie'


@app.route('/rmck/')
def remove_cookie():
""" 删除cookie,
由于不允许直接操作硬盘,所以采用更新cookie生效时间的方法
找到cookie,把生效时间设为当前时间之前
"""
resp = make_response('删除cookie')
# 把生效时间设为上一秒
resp.set_cookie('username', '', expires=datetime.now() + timedelta(minutes=-1))
return resp


# 调用基于类的视图
from account.views import RegUser, UserLogin

# 为导入的基于类的视图添加分配url规则
# 第一个参数:地址,第二个login为终结点,即视图函数名,可用于重定向
# app.add_url_rule('/login/', view_func=UserLogin.as_view('login'))
# app.add_url_rule('/reg/', view_func=RegUser.as_view('reg'))

# 调用基于方法的视图
from account.views import ARegUser

app.add_url_rule('/login/', view_func=UserLogin.as_view('login'))
app.add_url_rule('/reg/', view_func=ARegUser.as_view('reg'))

# 注册蓝图
from article.views import article
from product.views import product

app.register_blueprint(article, url_prefix='/articles/') # 注册时添加地址栏前缀
app.register_blueprint(product, url_prefix='/products/') # 注册时添加地址栏前缀

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

猜你喜欢

转载自www.cnblogs.com/zhongyehai/p/11483933.html