# -*- coding: utf-8 -*-
from flask import Blueprint,request,redirect,jsonify
from common.libs.Helper import ops_render,iPagination,getCurrentDate,getDictFilterField,selectFilterObj
from common.libs.UrlManager import UrlManager
from common.models.member.Member import Member
from common.models.member.MemberComments import MemberComments
from common.models.food.Food import Food
from common.models.pay.PayOrder import PayOrder
from application import app,db
route_member = Blueprint( 'member_page',__name__ )
@route_member.route( "/index" )
def index():
resp_data = {}
req = request.values
page = int( req['p'] ) if ( 'p' in req and req['p'] ) else 1
query = Member.query
if 'mix_kw' in req:
query = query.filter( Member.nickname.ilike( "%{0}%".format( req['mix_kw'] ) ) )
if 'status' in req and int( req['status'] ) > -1 :
query = query.filter( Member.status == int( req['status'] ) )
page_params = {
'total':query.count(),
'page_size': app.config['PAGE_SIZE'],
'page':page,
'display':app.config['PAGE_DISPLAY'],
'url': request.full_path.replace("&p={}".format(page),"")
}
pages = iPagination( page_params )
offset = ( page - 1 ) * app.config['PAGE_SIZE']
list = query.order_by( Member.id.desc() ).offset( offset ).limit( app.config['PAGE_SIZE'] ).all()
resp_data['list'] = list
resp_data['pages'] = pages
resp_data['search_con'] = req
resp_data['status_mapping'] = app.config['STATUS_MAPPING']
resp_data['current'] = 'index'
return ops_render( "member/index.html",resp_data )
@route_member.route( "/info" )
def info():
resp_data = {}
req = request.args
id = int( req.get( "id",0 ) )
reback_url = UrlManager.buildUrl( "/member/index" )
if id < 1:
return redirect( reback_url )
info = Member.query.filter_by( id =id ).first()
if not info:
return redirect( reback_url )
pay_order_list = PayOrder.query.filter_by( member_id = id ).filter( PayOrder.status.in_( [-8,1] ) )\
.order_by( PayOrder.id.desc() ).all()
comment_list = MemberComments.query.filter_by( member_id = id ).order_by( MemberComments.id.desc() ).all()
resp_data['info'] = info
resp_data['pay_order_list'] = pay_order_list
resp_data['comment_list'] = comment_list
resp_data['current'] = 'index'
return ops_render( "member/info.html",resp_data )
@route_member.route( "/set",methods = [ "GET","POST" ] )
def set():
if request.method == "GET":
resp_data = {}
req = request.args
id = int( req.get( "id",0 ) )
reback_url = UrlManager.buildUrl("/member/index")
if id < 1:
return redirect(reback_url)
info = Member.query.filter_by(id=id).first()
if not info:
return redirect(reback_url)
if info.status != 1:
return redirect(reback_url)
resp_data['info'] = info
resp_data['current'] = 'index'
return ops_render( "member/set.html",resp_data )
resp = { 'code':200,'msg':'操作成功~~','data':{} }
req = request.values
id = req['id'] if 'id' in req else 0
nickname = req['nickname'] if 'nickname' in req else ''
if nickname is None or len( nickname ) < 1:
resp['code'] = -1
resp['msg'] = "请输入符合规范的姓名~~"
return jsonify( resp )
member_info = Member.query.filter_by(id=id).first()
if not member_info:
resp['code'] = -1
resp['msg'] = "指定会员不存在~~"
return jsonify(resp)
member_info.nickname = nickname
member_info.updated_time = getCurrentDate()
db.session.add( member_info )
db.session.commit()
return jsonify( resp )
@route_member.route( "/comment" )
def comment():
resp_data = {}
req = request.args
page = int(req['p']) if ('p' in req and req['p']) else 1
query = MemberComments.query
page_params = {
'total': query.count(),
'page_size': app.config['PAGE_SIZE'],
'page': page,
'display': app.config['PAGE_DISPLAY'],
'url': request.full_path.replace("&p={}".format(page), "")
}
pages = iPagination(page_params)
offset = (page - 1) * app.config['PAGE_SIZE']
comment_list = query.order_by(MemberComments.id.desc()).offset( offset ).limit( app.config['PAGE_SIZE'] ).all()
data_list = []
if comment_list:
member_map = getDictFilterField( Member,Member.id,"id", selectFilterObj( comment_list ,"member_id" ) )
food_ids = []
for item in comment_list:
tmp_food_ids = (item.food_ids[1:-1]).split("_")
tmp_food_ids = {}.fromkeys( tmp_food_ids ).keys()
food_ids = food_ids + list( tmp_food_ids )
food_map = getDictFilterField( Food,Food.id,"id", food_ids )
for item in comment_list:
tmp_member_info = member_map[ item.member_id ]
tmp_foods = []
tmp_food_ids = (item.food_ids[1:-1]).split("_")
for tmp_food_id in tmp_food_ids:
tmp_food_info = food_map[ int( tmp_food_id ) ]
tmp_foods.append({
'name': tmp_food_info.name,
})
tmp_data = {
"content":item.content,
"score":item.score,
"member_info":tmp_member_info,
"foods":tmp_foods
}
data_list.append( tmp_data )
resp_data['list'] = data_list
resp_data['pages'] = pages
resp_data['current'] = 'comment'
return ops_render( "member/comment.html",resp_data )
@route_member.route("/ops",methods=["POST"])
def ops():
resp = { 'code':200,'msg':'操作成功~~','data':{} }
req = request.values
id = req['id'] if 'id' in req else 0
act = req['act'] if 'act' in req else ''
if not id :
resp['code'] = -1
resp['msg'] = "请选择要操作的账号~~"
return jsonify(resp)
if act not in [ 'remove','recover' ]:
resp['code'] = -1
resp['msg'] = "操作有误,请重试~~"
return jsonify(resp)
member_info = Member.query.filter_by( id = id ).first()
if not member_info:
resp['code'] = -1
resp['msg'] = "指定会员不存在~~"
return jsonify(resp)
if act == "remove":
member_info.status = 0
elif act == "recover":
member_info.status = 1
member_info.updated_time = getCurrentDate()
db.session.add(member_info)
db.session.commit()
return jsonify( resp )
代码段是一个Flask路由函数index()
,它接收一个GET请求并返回一个JSON响应。下面是对代码的详细解析:
resp_data
来存储响应数据。request.values
获取请求参数,并将其赋值给变量req
。p
,如果存在且不为空,则将其转换为整数并赋值给变量page
,否则将page
设置为1。Member
查询对象query
。mix_kw
,则使用filter()
方法对query
进行过滤,筛选出nickname
字段中包含req['mix_kw']
的记录。请注意,代码中的Member
是一个模型类,可能是通过SQLAlchemy定义的数据库表的映射类。
这段代码是一个条件判断语句,用于筛选查询结果。如果请求参数中包含名为’status’的键,并且该键对应的值大于-1,则会执行以下操作:
根据传入的参数进行分页查询,并返回查询结果和分页信息
offset? 偏移量
这段代码的功能是根据传入的page_params
参数进行分页查询,查询结果存储在list
变量中。然后将查询结果、分页信息、请求参数、状态映射和当前页面信息存储在resp_data
字典中。最后通过ops_render
函数将查询结果和其他信息渲染到指定的HTML模板中。
在给定的代码中,order_by
是SQLAlchemy中的一个函数,用于对查询结果进行排序。它的作用是按照指定的字段对查询结果进行排序,可以按照升序或降序排列。
具体来说,order_by
函数接受一个或多个参数,每个参数表示一个字段,用于指定排序的依据。可以使用点操作符来指定字段,例如Member.id
表示按照Member
表中的id
字段进行排序。
在给定的代码中,query.order_by(Member.id.desc())
表示按照Member
表中的id
字段进行降序排序。
.desc()
表示降序排序,? ? ? abbr.降序排列
descend? 美 /d??send/??v. 下来,下降;
如果要进行升序排序,可以使用.asc()
。
?ascending? ? 美 /??send??/? ?adj.? ?上升的,增长的;升(序)的
sequence? ? ? 美 /?si?kw?ns/?n.? 顺序,次序;连续事件(或动作、事物);
总结一下,order_by
函数用于对查询结果进行排序,可以按照一个或多个字段进行排序,可以指定升序或降序。
在这段代码中,.offset
用于指定查询结果的偏移量。偏移量表示从查询结果中跳过的行数。在这个例子中,.offset(offset)
表示从查询结果中跳过offset
行。这样可以用来实现分页功能,通过指定不同的偏移量来获取不同页的数据。
例如,如果offset
为0,则表示从查询结果的第一行开始获取数据;如果offset
为10,则表示从查询结果的第11行开始获取数据。
需要注意的是,.offset
方法必须与.limit
方法一起使用,以限制查询结果的数量。.limit
用于指定要获取的行数。
总结起来,.offset
方法用于指定查询结果的偏移量,以实现分页功能。
.limit()函数用于限制查询结果的数量。在给定的查询中,它指定了从结果集中返回的记录数的上限。在这段代码中,.limit(app.config[‘PAGE_SIZE’])将查询结果限制为app.config[‘PAGE_SIZE’]指定的页面大小。这通常用于分页查询,以确保每个页面只返回指定数量的记录。
根据提供的引用内容,代码段.all()
的作用是将查询结果以列表的形式返回。在这个例子中,query.order_by( Member.id.desc() ).offset( offset ).limit( app.config['PAGE_SIZE'] )
是一个查询语句,.all()
将返回满足查询条件的所有结果,并将其存储在名为list
的变量中。
DROP TABLE IF EXISTS `pay_order`;
CREATE TABLE `pay_order` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`order_sn` varchar(40) NOT NULL DEFAULT '' COMMENT '随机订单号',
`member_id` bigint(11) NOT NULL DEFAULT '0' COMMENT '会员id',
`total_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '订单应付金额',
`yun_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '运费金额',
`pay_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '订单实付金额',
`pay_sn` varchar(128) NOT NULL DEFAULT '' COMMENT '第三方流水号',
`prepay_id` varchar(128) NOT NULL DEFAULT '' COMMENT '第三方预付id',
`note` text NOT NULL COMMENT '备注信息',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '1:支付完成 0 无效 -1 申请退款 -2 退款中 -9 退款成功 -8 待支付 -7 完成支付待确认',
`express_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '快递状态,-8 待支付 -7 已付款待发货 1:确认收货 0:失败',
`express_address_id` int(11) NOT NULL DEFAULT '0' COMMENT '快递地址id',
`express_info` varchar(1000) NOT NULL DEFAULT '' COMMENT '快递信息',
`comment_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '评论状态',
`pay_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '付款到账时间',
`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最近一次更新时间',
`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_order_sn` (`order_sn`),
KEY `idx_member_id_status` (`member_id`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='在线购买订单表';
DROP TABLE IF EXISTS `member_comments`;
CREATE TABLE `member_comments` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`member_id` int(11) NOT NULL DEFAULT '0' COMMENT '会员id',
`food_ids` varchar(200) NOT NULL DEFAULT '' COMMENT '商品ids',
`pay_order_id` int(11) NOT NULL DEFAULT '0' COMMENT '订单id',
`score` tinyint(4) NOT NULL DEFAULT '0' COMMENT '评分',
`content` varchar(200) NOT NULL DEFAULT '' COMMENT '评论内容',
`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '插入时间',
PRIMARY KEY (`id`),
KEY `idx_member_id` (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员评论表';
DROP TABLE IF EXISTS `food`;
CREATE TABLE `food` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`cat_id` int(11) NOT NULL DEFAULT '0' COMMENT '分类id',
`name` varchar(100) NOT NULL DEFAULT '' COMMENT '书籍名称',
`price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '售卖金额',
`main_image` varchar(100) NOT NULL DEFAULT '' COMMENT '主图',
`summary` varchar(10000) NOT NULL DEFAULT '' COMMENT '描述',
`stock` int(11) NOT NULL DEFAULT '0' COMMENT '库存量',
`tags` varchar(200) NOT NULL DEFAULT '' COMMENT 'tag关键字,以","连接',
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态 1:有效 0:无效',
`month_count` int(11) NOT NULL DEFAULT '0' COMMENT '月销售数量',
`total_count` int(11) NOT NULL DEFAULT '0' COMMENT '总销售量',
`view_count` int(11) NOT NULL DEFAULT '0' COMMENT '总浏览次数',
`comment_count` int(11) NOT NULL DEFAULT '0' COMMENT '总评论量',
`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后更新时间',
`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后插入时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='食品表';
flask-sqlacodegen 'mysql://root:root@127.0.0.1/food_db' --tables pay_order --outfile "common/models/pay/PayOrder.py" --flask
flask-sqlacodegen 'mysql://root:root@127.0.0.1/food_db' --tables member_comments --outfile "common/models/member/MemberComments.py" --flask
flask-sqlacodegen 'mysql://root:root@127.0.0.1/food_db' --tables food --outfile "common/models/food/Food.py" --flask
{% extends "common/layout_main.html" %}
{% block content %}
{% include "common/tab_member.html" %}
<div class="row">
<div class="col-lg-12">
<form class="form-inline wrap_search">
<div class="row m-t p-w-m">
<div class="form-group">
<select name="status" class="form-control inline">
<option value="-1">请选择状态</option>
{% for tmp_key in status_mapping %}
<option value="{{ tmp_key }}" {% if tmp_key == search_con['status'] %} selected {% endif %}>{{ status_mapping[ tmp_key ] }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<div class="input-group">
<input type="text" name="mix_kw" placeholder="请输入关键字" class="form-control" value="{{ search_con['mix_kw'] }}">
<input type="hidden" name="p" value="{{ search_con['p'] }}">
<span class="input-group-btn">
<button type="button" class="btn btn-primary search">
<i class="fa fa-search"></i>搜索
</button>
</span>
</div>
</div>
</div>
<hr>
</form>
<table class="table table-bordered m-t">
<thead>
<tr>
<th>头像</th>
<th>姓名</th>
<th>性别</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% if list %}
{% for item in list %}
<tr>
<td><img alt="image" class="img-circle" src="{{ item.avatar }}" style="width: 40px;height: 40px;"></td>
<td>{{ item.nickname }}</td>
<td>{{ item.sex_desc }}</td>
<td>{{ item.status_desc }}</td>
<td>
<a href="{{ buildUrl('/member/info') }}?id={{ item.id }}">
<i class="fa fa-eye fa-lg"></i>
</a>
{% if item.status == 1 %}
<a class="m-l" href="{{ buildUrl('/member/set') }}?id={{ item.id }}">
<i class="fa fa-edit fa-lg"></i>
</a>
<a class="m-l remove" href="javascript:void(0);" data="{{ item.id }}">
<i class="fa fa-trash fa-lg"></i>
</a>
{% else %}
<a class="m-l recover" href="javascript:void(0);" data="{{ item.id }}">
<i class="fa fa-rotate-left fa-lg"></i>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
{% else %}
<tr><td colspan="5">暂无数据</td></tr>
{% endif %}
</tbody>
</table>
<!--分页代码已被封装到统一模板文件中-->
{% include 'common/pagenation.html' %}
</div>
</div>
{% endblock %}
{% block js %}
<script src="{{ buildStaticUrl('/js/member/index.js') }}"></script>
{% endblock %}
{% extends "common/layout_main.html" %}
{% block content %}
{% include "common/tab_member.html" %}
<div class="row m-t">
<div class="col-lg-12">
<div class="row">
<div class="col-lg-12">
<div class="m-b-md">
{% if info.status == 1 %}
<a class="btn btn-outline btn-primary pull-right" href="{{ buildUrl('/member/set') }}?id={{ info.id }}">
<i class="fa fa-pencil"></i>编辑
</a>
{% endif %}
<h2>会员信息</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-2 text-center">
<img class="img-circle circle-border" src="{{ info.avatar }}"
width="100px" height="100px">
</div>
<div class="col-lg-10">
<p class="m-t">姓名:{{ info.nickname }}</p>
<p>性别:{{ info.sex_desc }}</p>
</div>
</div>
<div class="row m-t">
<div class="col-lg-12">
<div class="panel blank-panel">
<div class="panel-heading">
<div class="panel-options">
<ul class="nav nav-tabs">
<li class="active">
<a href="#tab-1" data-toggle="tab" aria-expanded="false">会员订单</a>
</li>
<li>
<a href="#tab-2" data-toggle="tab" aria-expanded="true">会员评论</a>
</li>
</ul>
</div>
</div>
<div class="panel-body">
<div class="tab-content">
<div class="tab-pane active" id="tab-1">
<table class="table table-striped">
<thead>
<tr>
<th>订单编号</th>
<th>支付时间</th>
<th>支付金额</th>
<th>订单状态</th>
</tr>
</thead>
<tbody>
{% if pay_order_list %}
{% for item in pay_order_list %}
<tr>
<td>{{ item.order_number }}</td>
<td>{{ item.pay_time }}</td>
<td>{{ item.total_price }}</td>
<td>{{ item.status_desc }}</td>
</tr>
{% endfor %}
{% else %}
<td colspan="4">暂无订单</td>
{% endif %}
</tbody>
</table>
</div>
<div class="tab-pane" id="tab-2">
<table class="table table-striped">
<thead>
<tr>
<th>评论时间</th>
<th>评分</th>
<th>评论内容</th>
</tr>
</thead>
<tbody>
<tr>
</tr>
{% if comment_list %}
{% for item in comment_list %}
<tr>
<td>{{ item.created_time }}</td>
<td>{{ item.score }}</td>
<td>{{ item.content }}</td>
</tr>
{% endfor %}
{% else %}
<td colspan="3">暂无评论</td>
{% endif %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% extends "common/layout_main.html" %}
{% block content %}
{% include "common/tab_member.html" %}
<div class="row mg-t20 wrap_member_set">
<div class="col-lg-12">
<h2 class="text-center">会员设置</h2>
<div class="form-horizontal m-t">
<div class="hr-line-dashed"></div>
<div class="form-group">
<label class="col-lg-2 control-label">会员名称:</label>
<div class="col-lg-10">
<input type="text" class="form-control" placeholder="请输入会员名称" name="nickname" value="{{ info.nickname }}">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-lg-4 col-lg-offset-2">
<input type="hidden" name="id" value="{{ info.id }}">
<button class="btn btn-w-m btn-outline btn-primary save">保存</button>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script src="{{ buildStaticUrl('/js/member/set.js') }}"></script>
{% endblock %}
{% extends "common/layout_main.html" %}
{% block content %}
{% include "common/tab_member.html" %}
<div class="row">
<div class="col-lg-12">
<table class="table table-bordered m-t">
<thead>
<tr>
<th>头像</th>
<th>姓名</th>
<th>美餐</th>
<th>评论内容</th>
<th>打分</th>
</tr>
</thead>
<tbody>
{% if list %}
{% for item in list %}
<tr>
<td>
<img alt="image" class="img-circle" src="{{ item.member_info.avatar }}" style="width: 40px;height: 40px;">
</td>
<td>{{ item.member_info.nickname }}</td>
<td>
{% for item_food in item.foods %}
{{ item_food.name }}、
{% endfor %}
</td>
<td>{{ item.content }}</td>
<td>{{ item.score }}</td>
</tr>
{% endfor %}
{% else %}
<tr><td colspan="5">暂无数据</td></tr>
{% endif %}
</tbody>
</table>
<!--分页代码已被封装到统一模板文件中-->
{% include 'common/pagenation.html' %}
</div>
</div>
{% endblock %}