Flask 会员列表展示

Flask 会员列表展示_第1张图片

                                 感谢编程浪子师傅的源码信息分享

web/controllers/member/Member.py

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

@route_member.route("/index")

代码段是一个Flask路由函数index(),它接收一个GET请求并返回一个JSON响应。下面是对代码的详细解析:

  1. 首先,创建一个空字典resp_data来存储响应数据。
  2. 通过request.values获取请求参数,并将其赋值给变量req
  3. 使用条件语句判断是否存在参数p,如果存在且不为空,则将其转换为整数并赋值给变量page,否则将page设置为1。
  4. 创建一个Member查询对象query
  5. 如果请求参数中存在mix_kw,则使用filter()方法对query进行过滤,筛选出nickname字段中包含req['mix_kw']的记录。

请注意,代码中的Member是一个模型类,可能是通过SQLAlchemy定义的数据库表的映射类。

这段代码是一个条件判断语句,用于筛选查询结果。如果请求参数中包含名为’status’的键,并且该键对应的值大于-1,则会执行以下操作:

  1. 将查询对象query的筛选条件设置为Member.status等于请求参数中’status’对应的整数值。
  2. 创建一个名为page_params的字典,包含以下键值对:
    • ‘total’:查询结果的总数。
    • ‘page_size’:每页显示的数量。
    • ‘page’:当前页数。
    • ‘display’:每页显示的页码数量。
    • ‘url’:请求的完整路径,将其中的"&p={}".format(page)替换为空字符串。

根据传入的参数进行分页查询,并返回查询结果和分页信息

offset  偏移量

这段代码的功能是根据传入的page_params参数进行分页查询,查询结果存储在list变量中。然后将查询结果、分页信息、请求参数、状态映射和当前页面信息存储在resp_data字典中。最后通过ops_render函数将查询结果和其他信息渲染到指定的HTML模板中。

问题1: order_by 是什么函数有什么作用?

在给定的代码中,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函数用于对查询结果进行排序,可以按照一个或多个字段进行排序,可以指定升序或降序。

问题2:  .offset 有什么作用

在这段代码中,.offset用于指定查询结果的偏移量。偏移量表示从查询结果中跳过的行数。在这个例子中,.offset(offset)表示从查询结果中跳过offset行。这样可以用来实现分页功能,通过指定不同的偏移量来获取不同页的数据。

例如,如果offset为0,则表示从查询结果的第一行开始获取数据;如果offset为10,则表示从查询结果的第11行开始获取数据。

需要注意的是,.offset方法必须与.limit方法一起使用,以限制查询结果的数量。.limit用于指定要获取的行数。

总结起来,.offset方法用于指定查询结果的偏移量,以实现分页功能。

问题3:   .limit有什么作用?

.limit()函数用于限制查询结果的数量。在给定的查询中,它指定了从结果集中返回的记录数的上限。在这段代码中,.limit(app.config[‘PAGE_SIZE’])将查询结果限制为app.config[‘PAGE_SIZE’]指定的页面大小。这通常用于分页查询,以确保每个页面只返回指定数量的记录。

问题4:  .all有什么作用?

根据提供的引用内容,代码段.all()的作用是将查询结果以列表的形式返回。在这个例子中,query.order_by( Member.id.desc() ).offset( offset ).limit( app.config['PAGE_SIZE'] )是一个查询语句,.all()将返回满足查询条件的所有结果,并将其存储在名为list的变量中。

问题5: resp_data是一个对象吗?

在这段代码中,resp_data是一个字典对象。字典是Python中的一种数据结构,它由键值对组成,可以用来存储和访问数据。在这段代码中,resp_data被初始化为空字典{},然后通过resp_data['search_con'] = req将键为'search_con'的值设置为req。这样,resp_data就成为了一个包含一个键值对的字典对象。

字典对象可以通过键来访问对应的值。例如,可以使用resp_data['search_con']来获取'search_con'键对应的值。在这段代码中,resp_data['search_con']的值将被传递给ops_render()函数,用于渲染模板文件"member/index.html"。

总结起来,resp_data是一个字典对象,用于存储和传递数据

问题6: req是一个什么样的值?请详细解析

reqrequest.values的值。request.values是一个字典,包含了请求中的所有参数和值。在这段代码中,req将包含来自请求的所有参数和值。

这段代码的作用是在resp_data字典中添加一个键值对,键为search_con,值为req。然后将resp_data传递给ops_render函数,该函数将渲染member/index.html模板并返回结果。

请注意,request.values是一个字典,它包含了请求中的所有参数和值。因此,req的值将取决于请求中的参数和值。

@route_member.route("/info")

根据提供的引用内容,代码段中的resp_data是一个字典对象,而不是一个普通的对象。在代码中,resp_data被用来存储一些数据,包括info、pay_order_list和comment_list等。这些数据将在返回的HTML页面中使用。

字典对象是一种可变的数据类型,它可以存储键值对,并且可以通过键来访问对应的值。

以下是代码段的解释和示例:

@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  # 将info存储在resp_data字典中的'info'键下
    resp_data['pay_order_list'] = pay_order_list  # 将pay_order_list存储在resp_data字典中的'pay_order_list'键下
    resp_data['comment_list'] = comment_list  # 将comment_list存储在resp_data字典中的'comment_list'键下
    resp_data['current'] = 'index'  # 将'index'存储在resp_data字典中的'current'键下

    return ops_render( "member/info.html",resp_data )  # 返回HTML页面,并将resp_data作为参数传递给ops_render函数

数据库


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:[email protected]/food_db' --tables pay_order --outfile "common/models/pay/PayOrder.py"  --flask


flask-sqlacodegen 'mysql://root:[email protected]/food_db' --tables member_comments --outfile "common/models/member/MemberComments.py"  --flask


flask-sqlacodegen 'mysql://root:[email protected]/food_db' --tables food --outfile "common/models/food/Food.py"  --flask

common/models/member/Member.py  数据库

# coding: utf-8
from application import db, app


class Member(db.Model):
    __tablename__ = 'member'

    id = db.Column(db.Integer, primary_key=True)
    nickname = db.Column(db.String(100), nullable=False, server_default=db.FetchedValue(), info='会员名')
    mobile = db.Column(db.String(11), nullable=False, server_default=db.FetchedValue(), info='会员手机号码')
    sex = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue(), info='性别 1:男 2:女')
    avatar = db.Column(db.String(200), nullable=False, server_default=db.FetchedValue(), info='会员头像')
    salt = db.Column(db.String(32), nullable=False, server_default=db.FetchedValue(), info='随机salt')
    reg_ip = db.Column(db.String(100), nullable=False, server_default=db.FetchedValue(), info='注册ip')
    status = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue(), info='状态 1:有效 0:无效')
    updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue(), info='最后一次更新时间')
    created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue(), info='插入时间')


    @property
    def status_desc(self):
        return app.config['STATUS_MAPPING'][str(self.status)]

    @property
    def sex_desc(self):
        sex_mapping = {
            "0":"未知",
            "1":"男",
            "2":"女"
        }
        return sex_mapping[str(self.sex)]

    #status 统一返回sex表格的字段,  虚拟的好处是  直接可以在index.html中直接使用。  虚拟字段不可以查询





该段代码是一个Python类中的两个属性装饰器(@property)方法。这些装饰器方法允许我们在访问类的属性时执行一些自定义的逻辑

  1. @property装饰器用于定义一个getter方法,它允许我们像访问普通属性一样访问该方法。在这段代码中,@property装饰器定义了两个getter方法:status_desc和sex_desc。

  2. status_desc方法返回了一个名为app.config[‘STATUS_MAPPING’]的字典中与self.status对应的值。这个字典是一个配置文件中的映射,它将状态码映射到相应的描述。

  3. sex_desc方法返回了一个名为sex_mapping的字典中与self.sex对应的值。这个字典将性别码映射到相应的描述。

这两个属性装饰器方法使得我们可以通过访问类的实例属性来获取相应的描述信息,而不需要直接访问底层的状态码或性别码。

如下在index.html中过渡使用

Flask 会员列表展示_第2张图片

Flask 会员列表展示_第3张图片

虚拟字段的好处:  可以直接使用的

虚拟字段是不能进入字段查询的, 它只能作为该数据类里的某一种属性


搜索功能是在member/index.js里通过对warp_search 这个form标签及里面的search这个button按钮来设定的click点击事件后并submit提交到py后端flask框架里的member.py后进行判断处理。

py后端收到mix_kw  status相关信息,进行筛选后返回并爬着、时刻准备再次进行筛选行为。

templates/member/index.html

{% extends "common/layout_main.html" %}
{% block content %}
{% include "common/tab_member.html" %}
{% if list %} {% for item in list %} {% endfor %} {% else %} {% endif %}
头像 姓名 性别 状态 操作
image {{ item.nickname }} {{ item.sex_desc }} {{ item.status_desc }} {% if item.status == 1 %} {% else %} {% endif %}
暂无数据
{% include 'common/pagenation.html' %}
{% endblock %} {% block js %} {% endblock %}

在这个模板中,定义了一个表单,包含一个下拉选择框和一个搜索按钮

下拉选择框中的选项是通过循环生成的,循环遍历了一个名为status_mapping的字典,并将字典中的键值对生成为下拉选项。在生成选项时,还判断了当前选项是否与搜索条件中的状态匹配,如果匹配则设置为选中状态

search_con['status'] 是已经在Member.py中定义的req即request.values,被包装在resp_data里后,使用ops_render渲染并返回resp_data。

问题1:  search_con['p'] 是怎样的一个值?

search_con[p]是一个在HTML中的隐藏输入字段,它的值是search_con字典中键为p的值。在这个例子中,search_con是一个字典,它包含了从请求中获取的数据。search_con[p]表示获取search_con字典中键为p的值。

问题2:  那p又是一个怎样的值呢? 

在Member.py中可以发现对p的值的后续获取和条件判断

page  = int( req['p'] ) if ( 'p' in req and req['p'] ) else 1

根据提供的引用内容,代码中的p是一个隐藏的输入字段,它的值来自于search_con['p']。在这段代码中,p可能是用来表示页码的参数。根据代码中的注释,它可能用于搜索功能中的分页功能。

总结来说,该段代码用于传输分页的数据信息,p表示page



内容中还包含了一个HTML标签,其中包含了一个链接和一个图标。根据链接的格式,这可能是一个用于查看成员信息的URL链接。图标可能是一个用于显示成员信息的眼睛图标。

点击该图标后进入info方法对用户信息进行展示查看

问题3: 暂无数据 是什么意思?

暂无数据是HTML中的表格标签,用于在表格中创建一行并设置该行的单元格数目。其中,colspan属性用于指定单元格跨越的列数。

以下是一个示例:

姓名 年龄 性别
暂无数据

在上述示例中,表格中的第二行使用了暂无数据来创建一行,并且该行的单元格跨越了3列,显示为"暂无数据"。

问题4: html 中 td tr 分别是什么意思?

在HTML中,td和tr是表格中的两个重要元素。

  1. td元素:td代表表格中的单元格(table data)。每个td元素定义了一个表格中的单元格,并且可以包含文本、图像、链接或其他HTML元素。td元素必须位于tr元素内部。

  2. tr元素:tr代表表格中的行(table row)。每个tr元素定义了表格中的一行,并且包含一个或多个td元素。tr元素必须位于table元素内部

以下是一个简单的HTML表格示例:

单元格1 单元格2
单元格3 单元格4

在上面的示例中,有两个tr元素,每个tr元素包含两个td元素。这将创建一个包含两行两列的表格。


mix_kw 是关键字查询,  value="{{ search_con['mix_kw'] }}" 是相关展示,没有则输入框点击搜索按钮后里面的内容立刻消失,但是有了value="{{search_con['mix_kw']}}", 则点完搜索按钮后 该值持续存在展示。

templates/member/info.html

{% extends "common/layout_main.html" %}
{% block content %}
{% include "common/tab_member.html" %}

姓名:{{ info.nickname }}

性别:{{ info.sex_desc }}

{% if pay_order_list %} {% for item in pay_order_list %} {% endfor %} {% else %} {% endif %}
订单编号 支付时间 支付金额 订单状态
{{ item.order_number }} {{ item.pay_time }} {{ item.total_price }} {{ item.status_desc }}
暂无订单
{% if comment_list %} {% for item in comment_list %} {% endfor %} {% else %} {% endif %}
评论时间 评分 评论内容
{{ item.created_time }} {{ item.score }} {{ item.content }}
暂无评论
{% endblock %}

templates/member/set.html

{% extends "common/layout_main.html" %}
{% block content %}
{% include "common/tab_member.html" %}

会员设置

{% endblock %} {% block js %} {% endblock %}

templates/member/comment.html

{% extends "common/layout_main.html" %}
{% block content %}
{% include "common/tab_member.html" %}
{% if list %} {% for item in list %} {% endfor %} {% else %} {% endif %}
头像 姓名 美餐 评论内容 打分
image {{ item.member_info.nickname }} {% for item_food in item.foods %} {{ item_food.name }}、 {% endfor %} {{ item.content }} {{ item.score }}
暂无数据
{% include 'common/pagenation.html' %}
{% endblock %}

config/base_setting.py

STATUS_MAPPING = {
    "1":"正常",
    "0":"已删除"
}

web/static/js/member/index.js

;
var member_index_ops = {
    init:function(){
        this.eventBind();
    },
    eventBind:function(){
        var that = this;
        $(".wrap_search .search").click(function(){
            $(".wrap_search").submit();
        });

        $(".remove").click( function(){
            that.ops( "remove",$(this).attr("data") );
        } );

        $(".recover").click( function(){
            that.ops( "recover",$(this).attr("data") );
        } );
    },
    ops:function( act,id ){
        var callback = {
            'ok':function(){
                $.ajax({
                    url:common_ops.buildUrl( "/member/ops" ),
                    type:'POST',
                    data:{
                        act:act,
                        id:id
                    },
                    dataType:'json',
                    success:function( res ){
                        var callback = null;
                        if( res.code == 200 ){
                            callback = function(){
                                window.location.href = window.location.href;
                            }
                        }
                        common_ops.alert( res.msg,callback );
                    }
                });
            },
            'cancel':null
        };
        common_ops.confirm( ( act == "remove" ? "确定删除?":"确定恢复?" ), callback );
    }

};

$(document).ready( function(){
    member_index_ops.init();
} );

你可能感兴趣的:(flask,python,后端)