这期内容当中小编将会给大家带来有关Python Flask中的权限设置是怎样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
创新互联专注于宝山网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供宝山营销型网站建设,宝山网站制作、宝山网页设计、宝山网站官网定制、重庆小程序开发公司服务,打造宝山网络公司原创品牌,更为您提供宝山网站排名全网营销落地服务。
我们设置了系统的注册和登陆功能,已经基本满足了一个小型 Web 应用的需求。如果我们想通过这个网站来赚些小钱呢,就需要提供更高级的功能,当然这些高级功能不是免费开放的,设计一个权限系统,来控制高级应用的使用。
所谓的高级功能就是用户舍得花钱去购买的功能,像我这种喜欢薅羊毛的主,只配用用基础功能了。
我这里设计的高级功能,就是丰富 K 线图,在我们原来 K 线图的基础上添加移动平均线和成交量。
移动平均线
移动平均线是技术分析中非常普遍的一项指标,“平均”是指单位周期内的平均收盘价格,“移动”则是指将新的交易日收盘价纳入计算周期的同时,剔除最早的交易收盘价。
我们先来观察下通过 tushare 获取到的数据
可以看到,数据中的 Ma5、Ma10 和 Ma20 值可以用来制作移动平均线,可以通过折线图的方式来展现。
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="移动平均线")) .set_series_opts( label_opts=opts.LabelOpts(is_show=False), ) ) return c moving_average().render_notebook()
成交量
对于成交量,可以通过柱状图来展示,柱状图的高度,就是成交量的大小。把上涨时的成交量显示成红色,下跌时的成交量显示成绿色。
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()
集成三个图表
下面我们就把三个图标,K 线图,移动平均线图和成交量图合成到一起
首先把 K 线图和移动平均线图层叠到一起
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="移动平均线")) .set_series_opts( label_opts=opts.LabelOpts(is_show=False), ) ) kline.overlap(line) return kline
接下来再通过 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%" ), ) ...
至此,我们所谓的“高级”图表就完成了,下面就开始结合 Flask,嵌入我们产生的图表
首先我们先把新产生的两个图表嵌入到 Web 应用中,每个图表都是一个独立的页面
后台函数
先来创建生成移动平均线和成交量图表的函数
# 移动平均线 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-移动平均线" % 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 函数,返回我们需要的数据
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]
接着再增加生成两个图表所对应的视图函数
@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()
然后还要添加对应的前端页面
@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")
最后创建上面的两个 html 文件,并修改
{% extends "base.html" %} {% block title %}我的股票走势图{% endblock %} {% block page_content %} {% for message in get_flashed_messages() %}{{ message }}{% endfor %}{% endblock %} {% block scripts %} {{ super() }} {% endblock %}
同时在 base.html 中添加入口地址
......
现在我们的 Web 应用就是下图的样子了
下面我们就可以进入今天的正题了,设置权限。
定义表结构
首先定义权限表结构
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()
我们定义了两种权限,User 和 Admin,那么只有拥有 Admin 权限的用户才可以访问高级功能。
这里还使用了外键关联到了 WebUser 表上,所以需要同步修改 WebUser 表
# 用户表结构 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) ...
因为我们修改了原始表的表结构,所以需要进行表结构的迁移操作,这里可以使用插件 flask-migrate 来帮助我们实现
表结构迁移
先安装 flask-migrate 插件
pip install flask-migrate
然后在程序中配置 flask_migrate
from flask_migrate import Migrate ... migrate = Migrate(app, db, render_as_batch=True) ...
创建迁移仓库
flask db init
该命令会在当前目录下生成迁移文件夹,所有的迁移脚本都会保存在其中。
创建迁移脚本
flask db migrate
最后就是更新数据库,如果你和我一样是使用的 sqllite 数据库的话,那么需要对迁移脚本做些修改
打开 migrations 下 versions 里的 py 文件,找到语句 “batch_op.create_foreign_key”,修改如下
batch_op.create_foreign_key('role_key', 'roles', ['role_id'], ['id'])
然后再执行下面的命令
flask db upgrade
最后我们初始化角色
进入 flask shell,执行如下操作完成角色表的初始化
flask shell from app import Role Role.init_roles()
这样就完成了数据库的迁移和初始化。
下面我们就可以开始编写权限校验部分了
校验函数
对于校验函数,我们可以写在 WebUser 类中,这样就可以通过 current_user 来调用
... def is_admin(self): if self.role_id is 2: return True else: return False ...
再创建一个必须是 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 页面上
然后新建一个 full chart 函数,用于产生高级图表
# full chart def full_chart(mydate, kdata, data_5, data_10, data_20, volume_rise, volume_drop, name): kline = ( Kline() ...
同样的,编写为前端提供的接口函数
@app.route("/FullChart", methods=['GET', 'POST']) def get_fullcharte(): stock_name = request.form.get('stockName') query_time = request.form.get('queryTime') ...
最后创建 fullchart.html 并做响应修改,同时把 fullchart 视图函数指向该模板
@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中的权限设置是怎样的了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注创新互联行业资讯频道。