這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)Python Flask中的權(quán)限設(shè)置是怎樣的,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
創(chuàng)新互聯(lián)專注于寶山網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供寶山營(yíng)銷型網(wǎng)站建設(shè),寶山網(wǎng)站制作、寶山網(wǎng)頁(yè)設(shè)計(jì)、寶山網(wǎng)站官網(wǎng)定制、重慶小程序開發(fā)公司服務(wù),打造寶山網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供寶山網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。
我們?cè)O(shè)置了系統(tǒng)的注冊(cè)和登陸功能,已經(jīng)基本滿足了一個(gè)小型 Web 應(yīng)用的需求。如果我們想通過這個(gè)網(wǎng)站來(lái)賺些小錢呢,就需要提供更高級(jí)的功能,當(dāng)然這些高級(jí)功能不是免費(fèi)開放的,設(shè)計(jì)一個(gè)權(quán)限系統(tǒng),來(lái)控制高級(jí)應(yīng)用的使用。
所謂的高級(jí)功能就是用戶舍得花錢去購(gòu)買的功能,像我這種喜歡薅羊毛的主,只配用用基礎(chǔ)功能了。
我這里設(shè)計(jì)的高級(jí)功能,就是豐富 K 線圖,在我們?cè)瓉?lái) K 線圖的基礎(chǔ)上添加移動(dòng)平均線和成交量。
移動(dòng)平均線
移動(dòng)平均線是技術(shù)分析中非常普遍的一項(xiàng)指標(biāo),“平均”是指單位周期內(nèi)的平均收盤價(jià)格,“移動(dòng)”則是指將新的交易日收盤價(jià)納入計(jì)算周期的同時(shí),剔除最早的交易收盤價(jià)。
我們先來(lái)觀察下通過 tushare 獲取到的數(shù)據(jù)
可以看到,數(shù)據(jù)中的 Ma5、Ma10 和 Ma20 值可以用來(lái)制作移動(dòng)平均線,可以通過折線圖的方式來(lái)展現(xiàn)。
import pyecharts.options as opts from pyecharts.charts import Line def moving_average() -> Line: c = ( Line() .add_xaxis(df.index.tolist()) .add_yaxis("Ma5", df['ma5'].values.tolist(), is_smooth=True) .add_yaxis("Ma10", df['ma10'].values.tolist(), is_smooth=True) .add_yaxis("Ma20", df['ma20'].values.tolist(), is_smooth=True) .set_global_opts(title_opts=opts.TitleOpts(title="移動(dòng)平均線")) .set_series_opts( label_opts=opts.LabelOpts(is_show=False), ) ) return c moving_average().render_notebook()
成交量
對(duì)于成交量,可以通過柱狀圖來(lái)展示,柱狀圖的高度,就是成交量的大小。把上漲時(shí)的成交量顯示成紅色,下跌時(shí)的成交量顯示成綠色。
import pyecharts.options as opts from pyecharts.charts import Line, Bar volume_rise=[df.volume[x] if df.close[x] > df.open[x] else "0" for x in range(0, len(df.index))] volume_drop=[df.volume[x] if df.close[x] <= df.open[x] else "0" for x in range(0, len(df.index))] def volume() -> Bar: c = ( Bar() .add_xaxis(df.index.tolist()) .add_yaxis("volume_rise", volume_rise, stack=True, color=["#ec0000"]) .add_yaxis("volume_drop", volume_drop, stack=True, color=["#00da3c"]) .set_global_opts(title_opts=opts.TitleOpts(title="成交量"), datazoom_opts=[opts.DataZoomOpts()],) .set_series_opts( label_opts=opts.LabelOpts(is_show=False), ) ) return c volume().render_notebook()
集成三個(gè)圖表
下面我們就把三個(gè)圖標(biāo),K 線圖,移動(dòng)平均線圖和成交量圖合成到一起
首先把 K 線圖和移動(dòng)平均線圖層疊到一起
def kline_base() -> Kline: kline = ( Kline() .add_xaxis(df.index.tolist()) .add_yaxis("日K圖", df[['open', 'close', 'low', 'high']].values.tolist(), markpoint_opts=opts.MarkLineOpts( data=[opts.MarkLineItem(type_="max", value_dim="close")] ), markline_opts=opts.MarkLineOpts( data=[opts.MarkLineItem(type_="max", value_dim="close")] ), itemstyle_opts=opts.ItemStyleOpts( color="#ec0000", color0="#00da3c", border_color="#8A0000", border_color0="#008F28", ), ) .set_global_opts( yaxis_opts=opts.AxisOpts(is_scale=True, splitarea_opts=opts.SplitAreaOpts( is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1) ), ), xaxis_opts=opts.AxisOpts(is_scale=True, axislabel_opts=opts.LabelOpts(rotate=-30)), title_opts=opts.TitleOpts(title="股票走勢(shì)"), datazoom_opts=[opts.DataZoomOpts()], toolbox_opts=opts.ToolboxOpts(is_show=True), ) ) line = ( Line() .add_xaxis(df.index.tolist()) .add_yaxis("Ma5", df['ma5'].values.tolist(), is_smooth=True) .add_yaxis("Ma10", df['ma10'].values.tolist(), is_smooth=True) .add_yaxis("Ma20", df['ma20'].values.tolist(), is_smooth=True) .set_global_opts(title_opts=opts.TitleOpts(title="移動(dòng)平均線")) .set_series_opts( label_opts=opts.LabelOpts(is_show=False), ) ) kline.overlap(line) return kline
接下來(lái)再通過 grid 把成交量圖添加到主圖表中
... bar = ( Bar() .add_xaxis(df.index.tolist()) .add_yaxis("volume_rise", volume_rise, stack=True, color=["#ec0000"], ) .add_yaxis("volume_drop", volume_drop, stack=True, color=["#00da3c"], ) .set_global_opts(title_opts=opts.TitleOpts(), legend_opts=opts.LegendOpts(pos_right="20%")) .set_series_opts( label_opts=opts.LabelOpts(is_show=False), ) ) overlap_kline_line = kline.overlap(line) grid = Grid() grid.add( overlap_kline_line, grid_opts=opts.GridOpts(pos_left="10%", pos_right="8%", height="50%"), ) grid.add( bar, grid_opts=opts.GridOpts( pos_left="10%", pos_right="8%", pos_top="70%", height="16%" ), ) ...
至此,我們所謂的“高級(jí)”圖表就完成了,下面就開始結(jié)合 Flask,嵌入我們產(chǎn)生的圖表
首先我們先把新產(chǎn)生的兩個(gè)圖表嵌入到 Web 應(yīng)用中,每個(gè)圖表都是一個(gè)獨(dú)立的頁(yè)面
后臺(tái)函數(shù)
先來(lái)創(chuàng)建生成移動(dòng)平均線和成交量圖表的函數(shù)
# 移動(dòng)平均線 def moving_average_chart(mydate, data_5, data_10, data_20, name) -> Line: moving_average = ( Line() .add_xaxis(mydate) .add_yaxis("ma5", data_5, is_smooth=True) .add_yaxis("ma10", data_10, is_smooth=True) .add_yaxis("ma20", data_20, is_smooth=True) .set_global_opts(title_opts=opts.TitleOpts(title="%s-移動(dòng)平均線" % name), datazoom_opts=[opts.DataZoomOpts()], ) .set_series_opts( label_opts=opts.LabelOpts(is_show=False), ) ) return moving_average # 成交量 def volume_chart(mydate, volume_rise, volume_drop, name) -> Bar: bar = ( Bar() .add_xaxis(mydate) .add_yaxis("volume_rise", volume_rise, stack=True, color=["#ec0000"]) .add_yaxis("volume_drop", volume_drop, stack=True, color=["#00da3c"]) .set_global_opts(title_opts=opts.TitleOpts(title="%s-成交量" % name), datazoom_opts=[opts.DataZoomOpts()],) .set_series_opts( label_opts=opts.LabelOpts(is_show=False), ) ) return bar
然后再修改 get_stock_data 函數(shù),返回我們需要的數(shù)據(jù)
def get_stock_data(code, ctime): df = ts.get_hist_data(code) df_time = df[:ctime] mydate = df_time.index.tolist() kdata = df_time[['open', 'close', 'low', 'high']].values.tolist() madata_5 = df_time['ma5'].values.tolist() madata_10 = df_time['ma10'].values.tolist() madata_20 = df_time['ma20'].values.tolist() volume_rise = [df_time.volume[x] if df_time.close[x] > df_time.open[x] else "0" for x in range(0, len(df_time.index))] volume_drop = [df_time.volume[x] if df_time.close[x] <= df_time.open[x] else "0" for x in range(0, len(df_time.index))] return [mydate, kdata, madata_5, madata_10, madata_20, volume_rise, volume_drop]
接著再增加生成兩個(gè)圖表所對(duì)應(yīng)的視圖函數(shù)
@app.route("/Line", methods=['GET', 'POST']) def get_moving_average(): stock_name = request.form.get('stockName') query_time = request.form.get('queryTime') if not stock_name: stock_name = '平安銀行' if not query_time: query_time = 30 if int(query_time) > 30: if current_user.is_authenticated: pass else: abort(403) status, stock_code = check_stock(stock_name) if status == 0: return 'error stock code or name' mydate, kdata, madata_5, madata_10, madata_20, volume_rise, volume_drop = get_stock_data(stock_code[0], int(query_time)) c = moving_average_chart(mydate, madata_5, madata_10, madata_20, stock_code[1]) return c.dump_options() @app.route("/Bar", methods=['GET', 'POST']) def get_volume(): stock_name = request.form.get('stockName') query_time = request.form.get('queryTime') if not stock_name: stock_name = '平安銀行' if not query_time: query_time = 30 if int(query_time) > 30: if current_user.is_authenticated: pass else: abort(403) status, stock_code = check_stock(stock_name) if status == 0: return 'error stock code or name' mydate, kdata, madata_5, madata_10, madata_20, volume_rise, volume_drop = get_stock_data(stock_code[0], int(query_time)) c = volume_chart(mydate, volume_rise, volume_drop, stock_code[1]) return c.dump_options()
然后還要添加對(duì)應(yīng)的前端頁(yè)面
@app.route("/mavg", methods=['GET', 'POST']) def moving_average(): return render_template("mavg.html") @app.route("/volume", methods=['GET', 'POST']) def volume(): return render_template("volume.html")
最后創(chuàng)建上面的兩個(gè) html 文件,并修改
{% extends "base.html" %} {% block title %}我的股票走勢(shì)圖{% endblock %} {% block page_content %} {% for message in get_flashed_messages() %}{{ message }}{% endfor %}{% endblock %} {% block scripts %} {{ super() }} {% endblock %}
同時(shí)在 base.html 中添加入口地址
......
現(xiàn)在我們的 Web 應(yīng)用就是下圖的樣子了
下面我們就可以進(jìn)入今天的正題了,設(shè)置權(quán)限。
定義表結(jié)構(gòu)
首先定義權(quán)限表結(jié)構(gòu)
class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) users = db.relationship('WebUser', backref='role') @staticmethod def init_roles(): roles = ['User', 'Admin'] for r in roles: role = Role.query.filter_by(name=r).first() if role is None: role = Role(name=r) db.session.add(role) db.session.commit()
我們定義了兩種權(quán)限,User 和 Admin,那么只有擁有 Admin 權(quán)限的用戶才可以訪問高級(jí)功能。
這里還使用了外鍵關(guān)聯(lián)到了 WebUser 表上,所以需要同步修改 WebUser 表
# 用戶表結(jié)構(gòu) class WebUser(UserMixin, db.Model): __tablename__ = 'webuser' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.String(64), unique=True, index=True) email = db.Column(db.String(64), unique=True, index=True) username = db.Column(db.String(64), unique=True, index=True) password_hash = db.Column(db.String(128)) role_id = db.Column(db.Integer, db.ForeignKey('roles.id'), default=1) ...
因?yàn)槲覀冃薷牧嗽急淼谋斫Y(jié)構(gòu),所以需要進(jìn)行表結(jié)構(gòu)的遷移操作,這里可以使用插件 flask-migrate 來(lái)幫助我們實(shí)現(xiàn)
表結(jié)構(gòu)遷移
先安裝 flask-migrate 插件
pip install flask-migrate
然后在程序中配置 flask_migrate
from flask_migrate import Migrate ... migrate = Migrate(app, db, render_as_batch=True) ...
創(chuàng)建遷移倉(cāng)庫(kù)
flask db init
該命令會(huì)在當(dāng)前目錄下生成遷移文件夾,所有的遷移腳本都會(huì)保存在其中。
創(chuàng)建遷移腳本
flask db migrate
最后就是更新數(shù)據(jù)庫(kù),如果你和我一樣是使用的 sqllite 數(shù)據(jù)庫(kù)的話,那么需要對(duì)遷移腳本做些修改
打開 migrations 下 versions 里的 py 文件,找到語(yǔ)句 “batch_op.create_foreign_key”,修改如下
batch_op.create_foreign_key('role_key', 'roles', ['role_id'], ['id'])
然后再執(zhí)行下面的命令
flask db upgrade
最后我們初始化角色
進(jìn)入 flask shell,執(zhí)行如下操作完成角色表的初始化
flask shell from app import Role Role.init_roles()
這樣就完成了數(shù)據(jù)庫(kù)的遷移和初始化。
下面我們就可以開始編寫權(quán)限校驗(yàn)部分了
校驗(yàn)函數(shù)
對(duì)于校驗(yàn)函數(shù),我們可以寫在 WebUser 類中,這樣就可以通過 current_user 來(lái)調(diào)用
... def is_admin(self): if self.role_id is 2: return True else: return False ...
再創(chuàng)建一個(gè)必須是 admin role 的用戶才能訪問的視圖
@app.route('/fullchart/', methods=['GET', 'POST']) @login_required def fullchart(): if current_user.is_admin(): return "OK" flash('You have not permission to access this page') return redirect(url_for('index'))
把頁(yè)面入口添加到 base.html 頁(yè)面上
然后新建一個(gè) full chart 函數(shù),用于產(chǎn)生高級(jí)圖表
# full chart def full_chart(mydate, kdata, data_5, data_10, data_20, volume_rise, volume_drop, name): kline = ( Kline() ...
同樣的,編寫為前端提供的接口函數(shù)
@app.route("/FullChart", methods=['GET', 'POST']) def get_fullcharte(): stock_name = request.form.get('stockName') query_time = request.form.get('queryTime') ...
最后創(chuàng)建 fullchart.html 并做響應(yīng)修改,同時(shí)把 fullchart 視圖函數(shù)指向該模板
@app.route('/fullchart/', methods=['GET', 'POST']) @login_required def fullchart(): if current_user.is_admin(): return render_template('fullchart.html') flash('You have not permission to access this page') return redirect(url_for('index'))
至此,我們的高級(jí)圖表功能也完成了
上述就是小編為大家分享的Python Flask中的權(quán)限設(shè)置是怎樣的了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。