Archived
重写&重构项目, 优化项目结构
This commit is contained in:
33 files changed
+344
-966
No files matched your search
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
# -- coding:utf-8 --
|
||||
# @Author: markushammered@gmail.com
|
||||
# @Development Tool: PyCharm
|
||||
# @Create Time: 2022/3/25
|
||||
# @File Name: __init__.py
|
||||
|
||||
|
||||
from flask import Flask
|
||||
from .main import main
|
||||
from .db.db import SQLite
|
||||
|
||||
|
||||
class Config:
|
||||
"""基类配置"""
|
||||
JSON_SORT_KEYS = False
|
||||
JSON_AS_ASCII = False
|
||||
|
||||
|
||||
def create_app():
|
||||
"""创建主app"""
|
||||
app = Flask(__name__)
|
||||
app.register_blueprint(main)
|
||||
app.config.from_object(Config)
|
||||
|
||||
return app
|
||||
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -- coding:utf-8 --
|
||||
# @Author: markushammered@gmail.com
|
||||
# @Development Tool: PyCharm
|
||||
# @Create Time: 2022/3/25
|
||||
# @File Name: __init__.py.py
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env python3
|
||||
# -- coding:utf-8 --
|
||||
# @Author: markushammered@gmail.com
|
||||
# @Development Tool: PyCharm
|
||||
# @Create Time: 2022/3/25
|
||||
# @File Name: db.py
|
||||
|
||||
|
||||
import sqlite3
|
||||
from typing import List
|
||||
|
||||
|
||||
class SQLite:
|
||||
"""操作SQLite数据库"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""
|
||||
初始化SQLite对象
|
||||
完成后会自动提交, 自动关闭
|
||||
"""
|
||||
self.__path = './app/db/data.db'
|
||||
self.__conn = sqlite3.connect(self.__path)
|
||||
self.__cursor = self.__conn.cursor()
|
||||
|
||||
def __del__(self) -> None:
|
||||
"""
|
||||
自动提交
|
||||
自动关闭连接
|
||||
:return:
|
||||
"""
|
||||
self.__conn.commit()
|
||||
self.__cursor.close()
|
||||
self.__conn.close()
|
||||
|
||||
@property
|
||||
def show_tables(self) -> list:
|
||||
"""
|
||||
列出所有在数据库内的表
|
||||
:return:
|
||||
"""
|
||||
self.__cursor.execute('select * from sqlite_master where type="table"')
|
||||
tables = self.__cursor.fetchall()
|
||||
lst = []
|
||||
for table in tables:
|
||||
lst.append(table[1])
|
||||
del tables
|
||||
return lst
|
||||
|
||||
def exists_name(self, name: str) -> bool:
|
||||
"""
|
||||
判断当前名称是否在数据库内
|
||||
调用self.fetch()方法
|
||||
:param name:
|
||||
:return:
|
||||
"""
|
||||
status = self.fetch(name, True)
|
||||
if status == ():
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def exists_table(self, table: str) -> bool:
|
||||
"""
|
||||
判断表是否在数据库内
|
||||
调用self.fetching_table()方法
|
||||
:param table:
|
||||
:return:
|
||||
"""
|
||||
tables = self.show_tables
|
||||
if table in tables:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def insert(self, name: str, times: int = 0) -> bool:
|
||||
"""
|
||||
插入数据
|
||||
:param name:
|
||||
:param times:
|
||||
:return:
|
||||
"""
|
||||
self.__cursor.execute(
|
||||
'insert into reqcount (name, times) values("%(name)s", %(times)s)' % {'name': name, 'times': times})
|
||||
return True
|
||||
|
||||
def delete(self, name: str) -> bool:
|
||||
"""
|
||||
删除数据
|
||||
暂时不会用到此接口
|
||||
:param name:
|
||||
:return:
|
||||
"""
|
||||
self.__cursor.execute('delete from reqcount where name="%(name)s"' % {'name': name})
|
||||
return True
|
||||
|
||||
def fetch(self, name: str, is_check: bool = False) -> tuple:
|
||||
"""
|
||||
抓取数据
|
||||
:param name:
|
||||
:param is_check:
|
||||
:return:
|
||||
"""
|
||||
self.__cursor.execute('select * from reqcount where name="%(name)s"' % {'name': name})
|
||||
data = self.__cursor.fetchall()[0]
|
||||
if not is_check:
|
||||
self.update(name, data[-1])
|
||||
return data
|
||||
|
||||
def update(self, name: str, times: int) -> bool:
|
||||
"""
|
||||
更新数据
|
||||
:param name:
|
||||
:param times:
|
||||
:return:
|
||||
"""
|
||||
self.__cursor.execute(
|
||||
'update reqcount set times=%(times)s where name="%(name)s"' % {'times': times + 1, 'name': name})
|
||||
return True
|
||||
|
||||
def fetching_table(self, table: str) -> List[dict]:
|
||||
"""
|
||||
抓取主题表的数据
|
||||
:param table:
|
||||
:return:
|
||||
"""
|
||||
status = self.exists_table(table)
|
||||
if status:
|
||||
tables = self.__cursor.execute('select * from %(table)s' % {'table': table})
|
||||
lst = []
|
||||
for data in tables:
|
||||
lst.append({'index': data[0],
|
||||
'base64': data[1],
|
||||
'width': data[2],
|
||||
'height': data[3]})
|
||||
del tables
|
||||
return lst
|
||||
else:
|
||||
return []
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
# -- coding:utf-8 --
|
||||
# @Author: markushammered@gmail.com
|
||||
# @Development Tool: PyCharm
|
||||
# @Create Time: 2022/3/25
|
||||
# @File Name: __init__.py.py
|
||||
|
||||
|
||||
from flask import Blueprint
|
||||
|
||||
main = Blueprint('main', __name__)
|
||||
|
||||
from . import views, errors
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python3
|
||||
# -- coding:utf-8 --
|
||||
# @Author: markushammered@gmail.com
|
||||
# @Development Tool: PyCharm
|
||||
# @Create Time: 2022/3/25
|
||||
# @File Name: errors.py
|
||||
|
||||
from . import main
|
||||
|
||||
|
||||
@main.app_errorhandler(404)
|
||||
def page_not_found(e):
|
||||
"""
|
||||
404页面未找到
|
||||
:param e:
|
||||
:return:
|
||||
"""
|
||||
return {'code': 404, 'msg': '页面未找到', 'data': []}, 404
|
||||
|
||||
|
||||
@main.app_errorhandler(500)
|
||||
def internal_server_error(e):
|
||||
"""
|
||||
500服务器内部错误
|
||||
:param e:
|
||||
:return:
|
||||
"""
|
||||
return {'code': 500, 'msg': '服务器内部错误', 'data': []}, 500
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
# -- coding:utf-8 --
|
||||
# @Author: markushammered@gmail.com
|
||||
# @Development Tool: PyCharm
|
||||
# @Create Time: 2022/3/25
|
||||
# @File Name: views.py
|
||||
|
||||
|
||||
from flask import abort
|
||||
from flask import jsonify
|
||||
from flask import request
|
||||
from flask import Response
|
||||
from flask import make_response
|
||||
from flask import render_template
|
||||
from . import main
|
||||
from ..db.db import SQLite as db
|
||||
from ..utils.view import view
|
||||
|
||||
|
||||
@main.route('/', methods=['GET', 'POST'])
|
||||
def index():
|
||||
"""
|
||||
主页
|
||||
:return:
|
||||
"""
|
||||
return render_template('index.html', remote_address=request.remote_addr)
|
||||
|
||||
|
||||
@main.route('/api/v1/<string:name>', methods=['GET', 'POST'])
|
||||
@main.route('/count/<string:name>', methods=['GET', 'POST'])
|
||||
def api_v1(name: str):
|
||||
length = request.args.get('length', type=int)
|
||||
theme = request.args.get('theme', type=str)
|
||||
if not bool(length):
|
||||
length = 7
|
||||
if not bool(theme):
|
||||
theme = 'lewd'
|
||||
if not db().exists_name(name):
|
||||
db().insert(name)
|
||||
if not db().exists_table(theme):
|
||||
abort(500)
|
||||
if 7 <= length <= 10:
|
||||
data = db().fetch(name)
|
||||
number = '0' * (length - len(str(data[-1]))) + str(data[-1])
|
||||
# 将设置的长度减去数据库内已有的数据库字符串长度剩下的结果为[0]的个数
|
||||
# 再将这个字符串后拼接上数据库内已有次数的字符串, 就可以得到最终的结果
|
||||
response = make_response(view(theme, int(length), name, number))
|
||||
response.headers['Content-Type'] = 'image/svg+xml; charset=utf-8'
|
||||
response.headers['cache-control'] = 'max-age=0, no-cache, no-store, must-revalidate'
|
||||
return response
|
||||
return abort(500)
|
||||
|
||||
|
||||
@main.route('/exists-table', methods=['GET', 'POST'])
|
||||
@main.route('/exists', methods=['GET', 'POST'])
|
||||
def show_tables() -> Response:
|
||||
"""
|
||||
返回已有表
|
||||
:return:
|
||||
"""
|
||||
tables = db().show_tables
|
||||
return jsonify({'code': 200, 'msg': '已有表', 'data': [tables]})
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Request Counter - Index</title>
|
||||
<!-- 设置图标 -->
|
||||
<link rel="icon" type="image/png" sizes="128x128" href="{{ url_for('static', filename='favicon.ico') }}"/>
|
||||
<link rel="apple-touch-icon" type="image/png" sizes="128x128"
|
||||
href="{{ url_for('static', filename='favicon.ico') }}"/>
|
||||
<style>
|
||||
.intro{
|
||||
text-align: center;
|
||||
}
|
||||
a{
|
||||
color: green;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="intro">
|
||||
<br>
|
||||
<br>
|
||||
<i>看到这句话就说明程序正常运行啦!! <a href="https://markusjoe.github.io/RequestCounter/" target="_blank">查看文档</a></i>
|
||||
<br>
|
||||
<i>服务端使用Flask开发没有使用异步编程</i>
|
||||
<br>
|
||||
<i><a href="http://127.0.0.1:5000/api/v1/main">点击查看本地部署示例</a></i>
|
||||
<br>
|
||||
<i><a href="https://requestcounter.herokuapp.com/count/RequestCounter">点击查看已部署好的调用示例</a></i>
|
||||
<br>
|
||||
<i><b>注: 调用支持POST 和 GET 方法请求</b></i>
|
||||
<br>
|
||||
<br>
|
||||
<i>项目开源协议: <b>Apache-2.0</b> 即:
|
||||
<br>
|
||||
你可以直接使用该项目提供的功能, 无需任何授权
|
||||
<br>
|
||||
你可以在注明来源版权信息的情况下对源代码进行任意分发和修改以及衍生
|
||||
</i>
|
||||
<br>
|
||||
<!-- 显示客户端的IP地址 -->
|
||||
<i><b>你的IP地址为: {{ remote_address }}</b></i>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="{{ general_width }}" height="{{ general_height }}" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>{{ title }} | {{ address }}</title>
|
||||
<g>
|
||||
{% for value in context %}
|
||||
<image x="{{ value.position }}" y="0" width="{{ value.width }}" height="{{ value.height }}"
|
||||
xlink:href="{{ value.base64 }}"></image>
|
||||
{% endfor %}
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 483 B |
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -- coding:utf-8 --
|
||||
# @Author: markushammered@gmail.com
|
||||
# @Development Tool: PyCharm
|
||||
# @Create Time: 2022/3/26
|
||||
# @File Name: __init__.py.py
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
# -- coding:utf-8 --
|
||||
# @Author: markushammered@gmail.com
|
||||
# @Development Tool: PyCharm
|
||||
# @Create Time: 2022/3/25
|
||||
# @File Name: __init__.py.py
|
||||
|
||||
|
||||
import os
|
||||
import requests
|
||||
|
||||
|
||||
def download():
|
||||
res = requests.get('http://resource-base.herokuapp.com/download/data.db')
|
||||
with open('./app/db/data.db', 'wb') as fp:
|
||||
fp.write(res.content)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if not os.path.exists('./app/db/data.db'):
|
||||
print('数据库文件未找到, 正在下载中')
|
||||
download()
|
||||
print('下载完成')
|
||||
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python3
|
||||
# -- coding:utf-8 --
|
||||
# @Author: markushammered@gmail.com
|
||||
# @Development Tool: PyCharm
|
||||
# @Create Time: 2022/3/25
|
||||
# @File Name: view.py
|
||||
|
||||
|
||||
from ..db.db import SQLite as db
|
||||
from flask import render_template
|
||||
from typing import Tuple
|
||||
|
||||
|
||||
def view(theme: str,
|
||||
length: int,
|
||||
name: str,
|
||||
count: str
|
||||
) -> str or Tuple[bool, str]:
|
||||
"""
|
||||
渲染模板
|
||||
:param theme:
|
||||
:param length:
|
||||
:param name:
|
||||
:param count:
|
||||
:return:
|
||||
"""
|
||||
datas = db().fetching_table(theme)
|
||||
context = []
|
||||
for i in count:
|
||||
if i == '0':
|
||||
context.append({'base64': datas[0]['base64'],
|
||||
'width': datas[0]['width'],
|
||||
'height': datas[0]['height']})
|
||||
elif i == '1':
|
||||
context.append({'base64': datas[1]['base64'],
|
||||
'width': datas[1]['width'],
|
||||
'height': datas[1]['height']})
|
||||
elif i == '2':
|
||||
context.append({'base64': datas[2]['base64'],
|
||||
'width': datas[2]['width'],
|
||||
'height': datas[2]['height']})
|
||||
elif i == '3':
|
||||
context.append({'base64': datas[3]['base64'],
|
||||
'width': datas[3]['width'],
|
||||
'height': datas[3]['height']})
|
||||
elif i == '4':
|
||||
context.append({'base64': datas[4]['base64'],
|
||||
'width': datas[4]['width'],
|
||||
'height': datas[4]['height']})
|
||||
elif i == '5':
|
||||
context.append({'base64': datas[5]['base64'],
|
||||
'width': datas[5]['width'],
|
||||
'height': datas[5]['height']})
|
||||
elif i == '6':
|
||||
context.append({'base64': datas[6]['base64'],
|
||||
'width': datas[6]['width'],
|
||||
'height': datas[6]['height']})
|
||||
elif i == '7':
|
||||
context.append({'base64': datas[7]['base64'],
|
||||
'width': datas[7]['width'],
|
||||
'height': datas[7]['height']})
|
||||
elif i == '8':
|
||||
context.append({'base64': datas[8]['base64'],
|
||||
'width': datas[8]['width'],
|
||||
'height': datas[8]['height']})
|
||||
elif i == '9':
|
||||
context.append({'base64': datas[9]['base64'],
|
||||
'width': datas[9]['width'],
|
||||
'height': datas[9]['height']})
|
||||
|
||||
for p, i in zip(context, range(0, length)):
|
||||
p['position'] = i * p['width'] # 设置每张图片对应的位置
|
||||
|
||||
general_width = datas[0]['width'] * length # 计算出图片总长度
|
||||
general_height = datas[0]['height'] # 总宽度
|
||||
|
||||
return render_template('view.html',
|
||||
context=context,
|
||||
title=name,
|
||||
general_height=general_height,
|
||||
general_width=general_width)
|
||||
Reference in New Issue
Block a user