社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python副业私活600元,用Flask做一个查询Excel的网站

蚂蚁学Python • 3 年前 • 507 次点击  

前言

这次的接单的任务是用flask开发一个简单的数据查询展示网站。单子最早是在端午节假期发的,那个时候就想接下来干,奈何对Linux服务器部署一无所知,只能放弃了。8号这个单子又发出来了,再一次勾起了我想尝试一下的欲望,后来在蚂蚁的鼓励下,本着对Linux无知者无畏的精神和忐忑的心情接了下来。

需求分析

通过对客户需求文档分析和与客户沟通后,大致有以下几个需求:

  • 写一个web页面,支持两个查询
  • 处理Excel数据,并根据web查询条件返回相应的数据
  • 部署到Linux服务器,映射客户自己的域名

思路整理

  • 先写前端页面,因为首页即数据查询页,为了方便后续代码编写,选择用模板继承
  • 其次后端用pandas处理Excel,整理好数据后传到前端
  • 百度搜索flask任务怎么在Linux服务器上部署

代码实现

1.前端

1.1 写header和footer的HTML模板
# header模板
html>
<html lang="ch-zn">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数据查询系统title>
    <link rel="stylesheet" href="../static/bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="../static/bootstrap/js/bootstrap.min.js">
    <link rel="stylesheet" href="../static/css/index.css">
head>

<body>
    <div class="box">
        <div class="search-box">
            <form class="table-box" action="/" method="post">

                <h3>下单账号:h3>
                <label for="exampleInputUsername">label>
                <input type="text" placeholder="请输入账号" name="input" id="exampleInputUsername" >
                <button type="submit" class="btn btn-primary">奖励周边查询button>
                
                <button type="submit" class="btn btn-secondary" formaction="/pic">抽卡查询button>
            form>
        div>
# footer模板
div>
body>

html>

为了快速搭建,使用了bootstrap5.

1.2写index、table和pic的HTML

使用模板引入,构造需求web页面

# index.html
{% include 'header.html' %}
{% include 'footer.html' %}
# table.html
{% include 'header.html' %}
{% for message in get_flashed_messages() %}
    <div class=flash>{{ message }}div>
{% endfor %}
<div class="search-table">
    <table class="table table-striped table-hover table-bordered">
        <thead>
        <tr class="table-dark">
            {% for i in labels %}
            <th scope="col">{{ i }}th>
            {% endfor %}
        tr>
        thead>
        <tbody>
        <tr>
            {% for j in contents %}
            <td>{{ j[0] }}td>
            {% endfor %}
        tr>
        tbody>
    table>
div>
{% include 'footer.html' %}
# pic.html
{% include 'header.html' %}
<div class="pic">
    <div class="r">
        <div class="title">
        <h4>ID:{{data['user_id']}}h4>
        <p class="counts-part">【R】{{data['quantity'][0]}}、{{data['deduplication'][0]}}/{{data['total']}}p>
    div>
        <ul>
            {% for name in data['category']['R'][1] %}
            <li>
                <img src="{{data['category']['R'][1][name]}}" alt="">
                <p>{{name}} ({{data['category']['R'][2][name]}})p>
            li>
            {% endfor %}
         ul>
    div>
    <div class="sr">
         <p class="counts-part">【SR】{{data['quantity'][1]}}、{{data['deduplication'][1]}}/{{data['total']}}p>
        <ul>
            {% for name in data['category']['SR'][1] %}
            <li>
                <img src="{{data['category']['SR'][1][name]}}" alt="">
                <p>{{name}} ({{data['category']['SR'][2][name]}})p>
            li>
            {% endfor %}
        ul>
    div>
     <div class="ssr">
          <p class="counts-part">【SSR】{{data['quantity'][2]}}、{{data['deduplication'][2]}}/{{data['total']}}p>
        <ul>
            {% for name in data['category']['SSR'][1] %}
            <li>
                <img src="{{data['category']['SSR'][1][name]}}" alt="">
                <p>{{name}} ({{data['category']['SSR'][2][name]}})p>
            li>
            {% endfor %}
        ul>
    div>
     <div class="ur">
          <p class="counts-part">【UR】{{data['quantity'][3]}}、{{data['deduplication'][3]}}/{{data['total']}}p>
        <ul>
            {% for name in data['category']['UR'][1] %}
            <li>
                <img src="{{data['category']['UR'][1][name]}}" alt="">
                <p>{{name}} ({{data['category']['UR'][2][name]}})p>
            li>
            {% endfor %}
        ul>
    div>
div>
{% include 'footer.html' %}
1.3写css样式

由于bootstrap的样式不能完全满足需求,还需要自己再写一点,对html的布局进行调整。

* {
    margin0;
    padding0;
    box-sizing: border-box;
}

.box {
    width100vw;
    height100vh;
    background-imageurl('../image/bg.png');
    background-repeat: no-repeat;
    background-size: cover;
}

.search-box {
    height120px;
    margin0 auto 30px;
    text-align: center;
    padding-top50px;
    border-bottom2px solid #666;
}
.table{
    width1000px;
    margin0 auto;
    text-align: center;
    font-family: Microsoft YaHei;
    height:80px;
}
.table-box input {
    display: inline-block;
    width 200px;
    font-size14px;
    height35px;
    margin-right20px;
}

.table-box button {
    display: inline-block;
    width100px;
    height:35px;
    line-height:21px;
    text-align:center;
}
.table-box h3{
    display: inline-block;
    vertical-align: middle;
    font-size25px;
}
.btn-primary{
    font-size:12px;
}
.pic{
    width:1360px;
    height:100vh;
    background-colorrgba(255,255,255,.3);
    margin:50px auto 0;
    text-align:center;
}

.pic ul{
    border-top#4f5050 solid 2px;
    padding-top:10px;
    padding-left0;
}
.pic li{
    display: inline-block;
    background-color:#fff;
    text-decoration: none;
    list-style: none;
}
.pic li:nth-child(-n+7){
    margin-right20px;
}
.pic li img{
    width:140px;
}
.pic li p {
    height:30px;
    line-height:26px;
    text-align:center;
    margin-bottom:0;
    font-size12px;
}
.pic .title h4{
    float:left;
    margin-left35px;
    height:45px;
    line-height:70px;
    font-size:20px;
}
.pic .title p{
    float:right;
    margin-right35px;
    height:45px;
    line-height:70px;
}
.pic .title{
    height:50px;
}
.pic .counts-part{
    text-align:right;
    margin-right35px;
}
.flash{
    text-align:center;
    width:350px;
    height:50px;
    margin0 auto;
    line-height:50px;
    background-colorrgba(2111919,.5);
    border-radius5px;
    color#fff;
    letter-spacing1px;
}

2.后端

2.1数据展示
@app.route('/', methods=['GET', 'POST'])
def  get_table_data():
    df = pd.read_excel('./data/第一个表.xlsx')
    if request.method == 'POST':
        order_account = request.form.get('input')
        if len(order_account) != 0:
            df = df[df['下单账号'] == int(order_account)]
            dict_value = df.fillna('').to_dict(orient='list')
            labels = dict_value.keys()
            contents = dict_value.values()
            return render_template('table.html', labels=labels, contents=contents)
        else:
            flash('查询内容不能为空,请输入需要查询的账号!')
            return render_template('table.html')
    return render_template('index.html')
2.2图片展示
@app.route('/pic', methods=['GET', 'POST'])
def get_pic_data():
    df = pd.read_excel('./data/第二个表.xlsx')
    if request.method == 'POST':
        order_account = request.form.get('input')
        if len(order_account) != 0:
            df = df[df['下单账号'] == int(order_account)]
            user_id = df['ID'].values[0]  # 获取用户id
            total = len(''.join(df['拥有'].to_list()).split('、'))  # 计算总数
            gif_dict = {'category': {
                'R': [],
                'SR': [],
                'SSR': [],
                'UR': []
            }, 'user_id': user_id, 'total': total, 'quantity': [], 'deduplication': []}
            list_r, list_sr, list_ssr, list_ur = [], [], [], []
            img_r, img_sr, img_ssr, img_ur = {}, {}, {}, {}
            base_folder = r'../images'  # 图片文件路径
            for i in ''.join(df['拥有'].to_list()).split('、'):
                filename = i + '.gif'
                if i.startswith('【R】'):
                    list_r.append(i)
                    img_url = '{base_folder}/{filename}'.format(base_folder=base_folder, filename=filename)
                    img_r[i] = img_url
                elif i.startswith('【SR】'):
                    img_url = f'{base_folder}/{filename}'
                    img_sr[i] = img_url
                    list_sr.append(i)
                elif i.startswith('【SSR】'):
                    list_ssr.append(i)
                    img_url = f'{base_folder}/{filename}'
                    img_ssr[i] = img_url
                elif i.startswith('【UR】'):
                    list_ur.append(i)
                    img_url = f'{base_folder}/{filename}'
                    img_ur[i] = img_url
            gif_dict['category']['R'].append(list_r)
            gif_dict['category']['SR'].append(list_sr)
            gif_dict['category']['SSR'].append(list_ssr)
            gif_dict['category']['UR'].append(list_ur)
            gif_dict['category']['R'].append(img_r)
            gif_dict['category']['SR'].append(img_sr)
            gif_dict['category']['SSR'].append(img_ssr)
            gif_dict['category']['UR'].append(img_ur)
            for k in (list_r, list_sr, list_ssr, list_ur):
                gif_dict['quantity'].append(len(k))  # 有的数量
                gif_dict['deduplication'].append(len(set(k)))  # 去重数量
            for k1 in gif_dict['category'].keys():  # 计算文件名对应的元素个数
                result = Counter(gif_dict['category'][k1][0])
                gif_dict['category'][k1].append(dict(result))  # 将结果转成字典添加到gif字典
                gif_dict['category'][k1].append(dict(result))
                gif_dict['category'][k1].append(dict(result))
                gif_dict['category'][k1].append(dict(result))
            print(gif_dict)
            return render_template('pic.html', data=gif_dict)
        else:
            flash('查询内容不能为空,请输入需要查询的账号!')
            return render_template('table.html')
    return render_template('index.html')
2.3后端完整代码
from flask import Flask, render_template, request, flash, url_for, redirect
import pandas as pd
from collections import Counter

app = Flask(__name__, static_folder='/')
app.config['SECRET_KEY'] = 'asdfghj3223'


@app.route('/', methods=['GET', 'POST'])
def get_table_data():
    df = pd.read_excel('./data/第一个表.xlsx')
    if request.method == 'POST':
        order_account = request.form.get('input')
        if len(order_account) != 0:
            df = df[df['下单账号'] == int(order_account)]
            dict_value = df.fillna('').to_dict(orient='list')
            labels = dict_value.keys()
            contents = dict_value.values()
            return render_template('table.html', labels=labels, contents=contents)
        else:
            flash('查询内容不能为空,请输入需要查询的账号!')
            return render_template('table.html')
    return render_template('index.html')


@app.route('/pic', methods=['GET', 'POST'])
def get_pic_data():
    df = pd.read_excel('./data/第二个表.xlsx')
    if request.method == 'POST':
        order_account = request.form.get('input')
        if len(order_account) != 0:
            df = df[df['下单账号'] == int(order_account)]
            user_id = df['ID'].values[0]  # 获取用户id
            total = len(''.join(df['拥有'].to_list()).split('、'))  # 计算总数
            gif_dict = {'category': {
                'R': [],
                'SR': [],
                'SSR': [],
                'UR': []
            }, 'user_id': user_id, 'total': total, 'quantity': [], 'deduplication': []}
            list_r, list_sr, list_ssr, list_ur = [], [], [], []
            img_r, img_sr, img_ssr, img_ur = {}, {}, {}, {}
            base_folder = r'../images'  # 图片文件路径
            for i in ''.join(df['拥有'].to_list()).split('、'):
                filename = i + '.gif'
                if i.startswith('【R】'):
                    list_r.append(i)
                    img_url = '{base_folder}/{filename}'.format(base_folder=base_folder, filename=filename)
                    img_r[i] = img_url
                elif i.startswith('【SR】'):
                    img_url = f'{base_folder}/{filename}'
                    img_sr[i] = img_url
                    list_sr.append(i)
                elif i.startswith('【SSR】'):
                    list_ssr.append(i)
                    img_url = f'{base_folder}/{filename}'
                    img_ssr[i] = img_url
                elif i.startswith('【UR】'):
                    list_ur.append(i)
                    img_url = f'{base_folder}/{filename}'
                    img_ur[i] = img_url
            gif_dict['category']['R'].append(list_r)
            gif_dict['category']['SR'].append(list_sr)
            gif_dict['category']['SSR'].append(list_ssr)
            gif_dict['category']['UR'].append(list_ur)
            gif_dict['category']['R'].append(img_r)
            gif_dict['category']['SR'].append(img_sr)
            gif_dict['category' ]['SSR'].append(img_ssr)
            gif_dict['category']['UR'].append(img_ur)
            for k in (list_r, list_sr, list_ssr, list_ur):
                gif_dict['quantity'].append(len(k))  # 有的数量
                gif_dict['deduplication'].append(len(set(k)))  # 去重数量
            for k1 in gif_dict['category'].keys():  # 计算文件名对应的元素个数
                result = Counter(gif_dict['category'][k1][0])
                gif_dict['category'][k1].append(dict(result))  # 将结果转成字典添加到gif字典
                gif_dict['category'][k1].append(dict(result))
                gif_dict['category'][k1].append(dict(result))
                gif_dict['category'][k1].append(dict(result))
            print(gif_dict)
            return render_template('pic.html', data=gif_dict)
        else:
            flash('查询内容不能为空,请输入需要查询的账号!')
            return render_template('table.html')
    return render_template('index.html')


if __name__ == '__main__':
    app.run(debug=True)

这个项目最好的办法是用JavaScript写Ajax,因为在写的时候就像是在逆向爬虫数据解析的过程,但是Ajax还没有学到,只能退而求其次,好在数据量不大,而且也只是客户自己用,无伤大雅。

3.部署

通过和客户的进一步沟通,得知客户使用的是腾讯云的Linux服务器

既然有了目标,就有搜索的方向,通过在百度上一翻搜寻,最终找到了,宝塔面板。即先给服务器装上宝塔面板,装好以后服务器类似于一个桌面操作系统,使用起来就方便很多了。其次在应用商店安装python项目管理器,利用python项目管理器安装python环境以及相应的依赖。最后上传项目文件,使用python项目管理器部署项目,并选择域名映射。网上的教程很多,这里不再赘述,有兴趣的可以自己研究下,总之,非常nice。

效果展示

首页
奖励周边查询页
抽卡查询页
错误提示页
项目结构

写在最后

这里强烈推荐一下蚂蚁的python课程,全都面向实战,不注水,全干货。就这个项目而言,bootstrap和flask课程里都有,学过的,做出来没有任何问题。同时也感谢蚂蚁学Python-VIP 4群@氵斤@大鱼@偶是饭盒@freshj@哦@王伟敬@对方正在输出中....等各位大佬在部署阶段给予的建议。

每天锁定蚂蚁老师抖音直播间,给你介绍Python副业的玩法:


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/135727
 
507 次点击