把每一个模块独立出来,然后在主app里面注册,这样就实现了模块之间互不干扰
新建蓝图
artcle.views.py
"""article蓝图"""from flask import request, render_template, redirect, url_forfrom 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_forfrom flask import Blueprintfrom 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_forfrom flask import Blueprintfrom 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-8import sqlite3from datetime import datetime, timedeltafrom 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 articlefrom 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 )
原文地址:https://www.cnblogs.com/zhongyehai/p/11483933.html
时间: 2024-10-21 10:49:01