溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python Flask中的權(quán)限設(shè)置是怎樣的

發(fā)布時(shí)間:2021-10-26 14:19:45 來源:億速云 閱讀:142 作者:柒染 欄目:編程語言

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)Python Flask中的權(quán)限設(shè)置是怎樣的,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

我們設(shè)置了系統(tǒng)的注冊和登陸功能,已經(jīng)基本滿足了一個(gè)小型 Web 應(yīng)用的需求。如果我們想通過這個(gè)網(wǎng)站來賺些小錢呢,就需要提供更高級的功能,當(dāng)然這些高級功能不是免費(fèi)開放的,設(shè)計(jì)一個(gè)權(quán)限系統(tǒng),來控制高級應(yīng)用的使用。

撰寫高級功能

所謂的高級功能就是用戶舍得花錢去購買的功能,像我這種喜歡薅羊毛的主,只配用用基礎(chǔ)功能了。

我這里設(shè)計(jì)的高級功能,就是豐富 K 線圖,在我們原來 K 線圖的基礎(chǔ)上添加移動(dòng)平均線和成交量。

移動(dòng)平均線

移動(dòng)平均線是技術(shù)分析中非常普遍的一項(xiàng)指標(biāo),“平均”是指單位周期內(nèi)的平均收盤價(jià)格,“移動(dòng)”則是指將新的交易日收盤價(jià)納入計(jì)算周期的同時(shí),剔除最早的交易收盤價(jià)。

我們先來觀察下通過 tushare 獲取到的數(shù)據(jù)

Python Flask中的權(quán)限設(shè)置是怎樣的


可以看到,數(shù)據(jù)中的 Ma5、Ma10 和 Ma20 值可以用來制作移動(dòng)平均線,可以通過折線圖的方式來展現(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()

Python Flask中的權(quán)限設(shè)置是怎樣的

成交量

對于成交量,可以通過柱狀圖來展示,柱狀圖的高度,就是成交量的大小。把上漲時(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()

Python Flask中的權(quán)限設(shè)置是怎樣的

集成三個(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="股票走勢"),
 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

Python Flask中的權(quán)限設(shè)置是怎樣的


接下來再通過 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%"
 ),
 )
...

Python Flask中的權(quán)限設(shè)置是怎樣的


至此,我們所謂的“高級”圖表就完成了,下面就開始結(jié)合 Flask,嵌入我們產(chǎn)生的圖表

編寫各個(gè)圖表頁面

首先我們先把新產(chǎn)生的兩個(gè)圖表嵌入到 Web 應(yīng)用中,每個(gè)圖表都是一個(gè)獨(dú)立的頁面

后臺函數(shù)

先來創(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è)圖表所對應(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()

然后還要添加對應(yīng)的前端頁面

@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 %}我的股票走勢圖{% endblock %}
{% block page_content %}
{% for message in get_flashed_messages() %}
<div class="alert alert-warning">
 <button type="button" class="close" data-dismiss="alert">×</button>
 {{ message }}
 </div>
{% endfor %}
<body>
 <div id="form-div">
 <form id="form1" onsubmit="return false" action="#" method="post">
 <p id="p1">股票名稱:
 <input name="stockName" type="text" id="stockName" tabindex="1" size="16" value="" placeholder="股票名稱"/>
<!-- <input type="button" onclick="add1();" value="添加" />-->
 </p>
 <p id="p2">查詢時(shí)間:
 <input name="queryTime" type="text" id="queryTime" tabindex="2" size="16" value="" placeholder="輸入30查詢近30天數(shù)據(jù)"/>
 </p>
 <p><input type="submit" value="查詢" onclick="getData()"></p>
 </form>
 </div>
 <div id="Bar" style="width:1000px; height:600px;"></div>
 <script>
 $(
 function () {
 var chart = echarts.init(document.getElementById('Bar'), 'white', {renderer: 'canvas'});
 $.ajax({
 type: "GET",
 url: "http://127.0.0.1:5000/Bar",
 dataType: 'json',
 success: function (result) {
 chart.setOption(result);
 }
 });
 }
 );
 function getData() {
 var chart = echarts.init(document.getElementById('Bar'), 'white', {renderer: 'canvas'});
 $.ajax({
 type: "POST",//方法類型
 dataType: "json",//預(yù)期服務(wù)器返回的數(shù)據(jù)類型
 url: "/Bar" ,//url
 data: $('#form1').serialize(),
 success: function (result) {
 chart.setOption(result);
 },
 error: function(err) {
 if (err.status === 403) {
 alert("請先登陸系統(tǒng)!");
 }
 else {
 alert("錯(cuò)誤的股票代碼!");
 }
 }
 });
 }
 function add1(){
 var input1 = document.createElement('input');
 input1.setAttribute('type', 'text');
 input1.setAttribute('name', 'organizers[]');
 var btn1 = document.getElementById("p1");
 //btn1.insertBefore(input1,null);
 btn1.appendChild(input1);
 }
 </script>
</body>
{% endblock %}
{% block scripts %}
{{ super() }}
 <script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
 <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
{% endblock %}

同時(shí)在 base.html 中添加入口地址

...
<ul class="nav navbar-nav">
 <li><a href="{{ url_for('moving_average')}}">Moving Average</a></li>
 </ul>
 <ul class="nav navbar-nav">
 <li><a href="{{ url_for('volume')}}">Volume</a></li>
 </ul>
...

現(xiàn)在我們的 Web 應(yīng)用就是下圖的樣子了

Python Flask中的權(quán)限設(shè)置是怎樣的


下面我們就可以進(jìn)入今天的正題了,設(shè)置權(quán)限。

權(quán)限設(shè)計(jì)

定義表結(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)限的用戶才可以訪問高級功能。

這里還使用了外鍵關(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 來幫助我們實(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)建遷移倉庫

flask db init

該命令會(huì)在當(dāng)前目錄下生成遷移文件夾,所有的遷移腳本都會(huì)保存在其中。

創(chuàng)建遷移腳本

flask db migrate

最后就是更新數(shù)據(jù)庫,如果你和我一樣是使用的 sqllite 數(shù)據(jù)庫的話,那么需要對遷移腳本做些修改

打開 migrations 下 versions 里的 py 文件,找到語句 “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ù)庫的遷移和初始化。

權(quán)限校驗(yàn)

下面我們就可以開始編寫權(quán)限校驗(yàn)部分了

校驗(yàn)函數(shù)

對于校驗(yàn)函數(shù),我們可以寫在 WebUser 類中,這樣就可以通過 current_user 來調(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'))

整合前后端

把頁面入口添加到 base.html 頁面上

<ul class="nav navbar-nav">
 <li><a href="{{ url_for('fullchart')}}">Full Chart</a></li>
 </ul>

然后新建一個(gè) full chart 函數(shù),用于產(chǎn)生高級圖表

# 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'))

至此,我們的高級圖表功能也完成了

Python Flask中的權(quán)限設(shè)置是怎樣的

上述就是小編為大家分享的Python Flask中的權(quán)限設(shè)置是怎樣的了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI