Flask 会员列表展示

news2024/11/15 8:24:55

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

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: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

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中过渡使用

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

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


搜索功能是在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" %}
<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>

{#                      <option value="1"> 正常 </option>#}
{#                      <option value="0">已删除</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 %}

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

下拉选择框中的选项是通过循环生成的,循环遍历了一个名为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可能是用来表示页码的参数。根据代码中的注释,它可能用于搜索功能中的分页功能。

<input type="hidden" name="p" value="{{ search_con['p'] }}"> 总结来说,该段代码用于传输分页的数据信息,p表示page


<a href="{{ buildUrl('/member/info') }}?id={{ item.id }}">
<i class="fa fa-eye fa-lg"></i>

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

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

问题3: <tr><td colspan="5">暂无数据</td></tr> 是什么意思?

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

以下是一个示例:

<table border="1">
  <tr>
    <td>姓名</td>
    <td>年龄</td>
    <td>性别</td>
  </tr>
  <tr>
    <td colspan="3">暂无数据</td>
  </tr>
</table>

在上述示例中,表格中的第二行使用了<tr><td colspan="3">暂无数据</td></tr>来创建一行,并且该行的单元格跨越了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表格示例:

<table>
  <tr>
    <td>单元格1</td>
    <td>单元格2</td>
  </tr>
  <tr>
    <td>单元格3</td>
    <td>单元格4</td>
  </tr>
</table>

在上面的示例中,有两个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" %}
<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 %}

templates/member/set.html

{% 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 %}

templates/member/comment.html

{% 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 %}

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();
} );

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1360700.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MongoDB数据类型详解

BSON 协议与数据类型 MongoDB 为什么会使用 BSON&#xff1f; JSON 是当今非常通用的一种跨语言 Web 数据交互格式&#xff0c;属 ECMAScript 标准规范的一个子集。JSON &#xff08;JavaScript Object Notation&#xff0c;JS 对象简谱&#xff09;即 JavaScript 对象表示法…

日程安排小程序实战教程

日常中我们经常有一些事情需要提醒自己&#xff0c;使用日历的形式比较符合实际的使用习惯。本篇我们就利用微搭低代码工具带着大家开发一款日程安排的小程序。 1 创建数据源 登录微搭低代码控制台&#xff0c;打开数据模型&#xff0c;点击创建 输入数据源的名称日程安排 …

vue封装组件(一)标签和下拉框组合实现添加数据

背景: 最近接入短剧内容&#xff0c;需要添加短剧合作方。在详情页需要支持添加组件 方案一&#xff1a;标签tag加上输入框实现添加数据。图片见下 这个是刚开始做的&#xff0c;后来产品觉得这样会造成随意修改数据&#xff0c;需要改成下拉框形式添加 方案二&#xff1a;标签…

【人工智能】深入了解人工智能的核心算法与应用实践

人工智能 学习AI要看的第一本书人工智能应当以人为本人工智能&#xff08;第3版&#xff09;通晓六点&#xff0c;明白人工智能是怎么回事基本概念和历史基础知识基于知识的系统高级专题现在和未来安全和编程 人工智能已经是基础学科 学习AI要看的第一本书 人工智能知识对于当…

PLC分段传送带控制示例

一、为了节约用电&#xff0c;将长长的传送带进行分段&#xff0c;哪断上有物品&#xff0c;哪断才运行 二、每一断末尾都有传感器&#xff0c;传感器能感受到物体有没有到传送带的末尾 三、这个传感器是接近开关 四、控制流程 五、IO地址分配 六、按下启动按钮后&#xff0c;…

【Linux软件包管理器】yum详解

目录 1、什么是软件包 2、yum的操作 1&#xff09;yum源 2&#xff09;三板斧 ① yum list ② yum install [软键名] ③ yum remove [软件名] 1、什么是软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了,…

自存react crash course(1)

1.创建一个react 项目 确保有node.js 创建名为react-task-tracker的react项目 npx create-react-app react-task-tracker 启动项目 npm start2.项目结构 所有组件都是放在src下面的 3. jsx // jsx语法 和html很像&#xff0c;class用的是className来使用css的样式<div…

【unity】Obi插件架构组成(参数详细解释)——解算器四面板设置、三种更新器、参与者介绍

文章目录 一、架构&#xff08;Architecture&#xff09;1.1 Obi解算器&#xff08;ObiSolver&#xff09;1.2 ObiUpdater1.3 ObiActorBlueprint1.4 Obi参与者&#xff08;ObiActor&#xff0c;如ObiRope等&#xff09; 二、Obi解算器&#xff08;ObiSolver&#xff09;2.1 解算…

vue3学习 【2】vite起步和开发工具基本配置

vite的简介 官方文档 刚起步学习&#xff0c;所以我们只需要按照官方文档的入门流程即可。推荐阅读一下官网的为什么使用vite vite目前需要的node版本是18&#xff0c;可以参考上一篇文章的安装nvm&#xff0c;用来进行多版本的node管理。 vite安装与使用 npm create vitela…

24年初级会计资格考试报名信息采集流程共10大步骤,千万不要搞错

2024年初级会计资格考试报名信息采集流程共10大步骤&#xff0c;不要搞错哦&#xff1b; 第一步&#xff1a;输入证件号、点击登录 第二步&#xff1a;阅读采集须知 第三步&#xff1a;填写个人信息&#xff08;支付宝搜索"亿鸣证件照"或者微信搜索"随时照&q…

C# Onnx Chinese CLIP 通过一句话从图库中搜出来符合要求的图片

目录 效果 生成图片特征 查找踢足球的人 测试图片 模型信息 image_model.onnx text_model.onnx 项目 代码 Form1.cs Clip.cs 下载 C# Onnx Chinese CLIP 通过一句话从图库中搜出来符合要求的图片 效果 生成图片特征 查找踢足球的人 测试图片 模型信息 image_mod…

Java/JDK下载安装与环境配置

Java由Sun Microsystems&#xff08;现在是Oracle的子公司&#xff09;于1995年首次发布。它是一种面向对象的编程语言&#xff0c;广泛应用于Web开发、移动应用程序开发、桌面应用程序开发和企业级应用程序开发等领域。 Java语言的主要特点是跨平台、可移植性强、安全性高和具…

【AI视野·今日Sound 声学论文速览 第三十九期】Tue, 2 Jan 2024

AI视野今日CS.Sound 声学论文速览 Tue, 2 Jan 2024 Totally 7 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Enhancing Pre-trained ASR System Fine-tuning for Dysarthric Speech Recognition using Adversarial Data Augmentation Authors Huimen…

《微机原理与应用》期末考试题库(附答案解析)

第1章 微型计算机概述 1.微型计算机的硬件系统包括___A _____。 A&#xff0e;控制器、运算器、存储器和输入输出设备 B&#xff0e;控制器、主机、键盘和显示器 C&#xff0e;主机、电源、CPU和输入输出 D&#xff0e;CPU、键盘、显示器和打印机 2.微处…

LLM Agent零微调范式 ReAct Self Ask

前三章我们分别介绍了思维链的使用&#xff0c;原理和在小模型上的使用。这一章我们正式进入应用层面&#xff0c;聊聊如何把思维链和工具使用结合得到人工智能代理。 要回答我们为什么需要AI代理&#xff1f;代理可以解决哪些问题&#xff1f;可以有以下两个视角 首先是我们…

算法训练day60|单调栈part0

参考&#xff1a;代码随想录 84.柱状图中最大的矩形 要求当前柱形的左右两边第一个比他小的位置 对于高度为5的柱子&#xff08;index为2&#xff09; mid 他的左边第一个比他小的柱子为1&#xff0c;index为1 left 他的右边第一个比他小的柱子高度为2&#xff0c;index为4…

Springcloud 微服务实战笔记 Eureka

服务治理 服务注册 在服务治理框架中&#xff0c;通常都会构建一个注册中心&#xff0c;每个服务单元向注册中心登记自己提供的服务&#xff0c;将主机与端口号、版本号、通信协议等一些附加信息告知注册中心&#xff0c;注册中心按服务名分类组织服务清单。当服务启动后&…

DBeaver 连接mysql 报错 Public Key Retrieval is not allowed

问题描述 一段时间没有用本地数据库&#xff0c;使用dbeaver连接mysql报错&#xff1a;Public Key Retrieval is not allowed 原因分析&#xff1a; Public Key Retrieval is not allowed&#xff1a;不允许进行公钥检索。 解决方案&#xff1a; 在编辑连接中找到allowPu…

swift ——多行文字前面内容省略

首先来说一说ios中的 lineBreakModelineBreakMode : 设置文字过长时的显示截断样式 可选值如下 byWordWrapping &#xff1a; 以单词为单位换行&#xff0c;以单词为单位截断。byCharWrapping &#xff1a;以字符为单位换行&#xff0c;以字符为单位截断。byClipping &#x…

Note: A Journey Across Canada

A Journey Across Canada 一场横穿加拿大的旅行 across journey After a quiz last autumn, Kuang crossed the continent eastward to Toronto to visit his schoolmate, the distance measuring approximately 5000 kilometers. 去年秋天一次考试后&#xff0c;Kuang向东穿…