今天晚上吃完饭,忽然觉得这段时间写网站总是简单功能费好久时间才能搞定,想想多对多数据库一直以来都没怎么搞过,再过段时间可能就忘了,那就开发个简单的物品需求关系内容吧,主要是走流程不上线。
虽然是走流程,我还是采用了阿里云CENTOS7服务器加pycharm远程开发的方式直接在云服务器上开搞了,力求贴近现场。
需求主要是一个表格类似这样
其实也就是三十几个人每个人可以报不同的物品,那么用FLASK写一个申报网站:
- 因为本次重点在多对多数据库方面,为了简化流程人员的注册和物品的注册都很简单
首先是根目录下的setting 配置文件,
class Config(object):
DEBUG=1
SQLALCHEMY_DATABASE_URI="mysql+pymysql://root:gxxxe@47.xxx.xx.xxx:3306/mysqllaobao"
SQLALCHEMY_TRACK_MODIFICATIONS=False
EVN='development'
SECRET_KEY = 'ASDFJASKDaskdlfjla123'
- 然后是,入口app.py,因为做了分离,所以这个入口几乎也是万能的,新项目直接配套沾走环境一致也能用
from flask import Flask
from apps import creat_app
from exts import db
from flask_script import Manager
from flask_migrate import Migrate,MigrateCommand
from apps.modles import *
app = Flask(__name__)
app=creat_app(app)
manage = Manager(app=app)
migrate = Migrate(app=app,db=db)
manage.add_command('db',MigrateCommand)
if __name__ == '__main__':
manage.run()
- 根目录下laobao.txt 这个是环境配置文件,用下面这个命令可以安装对应环境
pip instal -r laobao.txt
文件内容如下:
alembic==1.7.1
backcall==0.2.0
Bootstrap-Flask==1.8.0
click==8.0.1
colorama==0.4.4
decorator==5.1.0
dominate==2.6.0
easygui==0.98.2
Flask==1.1.2
Flask-Admin==1.5.8
Flask-Bootstrap==3.3.7.1
Flask-Migrate==2.5.3
Flask-Script==2.0.6
Flask-SQLAlchemy==2.5.1
greenlet==1.1.1
importlib-metadata==4.8.1
importlib-resources==5.2.2
ipython==7.27.0
itsdangerous==2.0.1
jedi==0.18.0
Jinja2==3.0.1
Mako==1.1.5
MarkupSafe==2.0.1
matplotlib-inline==0.1.3
paho-mqtt==1.5.1
parso==0.8.2
pickleshare==0.7.5
prompt-toolkit==3.0.20
Pygments==2.10.0
PyMySQL==1.0.2
SQLAlchemy==1.4.23
traitlets==5.1.0
typing-extensions==3.10.0.2
visitor==0.1.3
wcwidth==0.2.5
Werkzeug==2.0.1
WTForms==2.3.3
zipp==3.5.0
4./apps/init 里边是工厂函数,也是不用太管的玩意,
from setting import Config
from exts import db
from apps.views import user_bp
def creat_app(app):
app.config.from_object(Config)
app.register_blueprint(user_bp)
db.init_app(app)
return app
- /exts/init 数据库映射扩展
from flask_sqlalchemy import SQLAlchemy
db=SQLAlchemy()
- /apps/modles.py 模型位置 ,三个模型 一个人的就一个名字
一个东西的也一个名字,一个关系模型
这里注意:关系模型类我命名是GanXi 这种驼峰名字结果映射到数据库中的表名字是:guan_xi 这样,这,好坑居然带个地划线。。。
from exts import db
from datetime import datetime
class Person(db.Model):
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
name = db.Column(db.String(20),nullable=False)
thing=db.relationship('Thing',backref='person',secondary='guan_xi')
def __str__(self):
return self.u_id
class Thing(db.Model):
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
name = db.Column(db.String(20),nullable=False)
def __str__(self):
return self.t_id
class GuanXi(db.Model):
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
u_id = db.Column(db.Integer,db.ForeignKey('person.id'))
t_id = db.Column(db.Integer,db.ForeignKey('thing.id'))
numbers= db.Column(db.String(20),nullable=False)
def __str__(self):
return self.g_id
- 构建逻辑把。。首先视图函数首页,
from flask import render_template ,request,session,redirect,g
from flask import Blueprint
from exts import db
from apps.modles import *
user_bp = Blueprint('user',__name__)
@user_bp.route('/')
def start():
return render_template('index.html')
index.html为:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
<h1>用户登记</h1>
<input type="text" name="name" placeholder="姓名">
<br>
<input type="submit" value="提交">
<br>
</form>
<form action="/wupinlogin" method="post">
<h1>物品登记</h1>
<input type="text" name="name" placeholder="品名">
<br>
<input type="submit" value="提交">
<br>
</form>
<form action="/goumai" method="post">
<h1>物品登记</h1>
<input type="text" name="name" placeholder="客户">
<br>
<input type="text" name="thing" placeholder="物品">
<br>
<input type="text" name="numbers" placeholder="数量">
<br>
<input type="submit" value="提交">
<br>
</form>
<a href="/chaxun">查询页面</a>
</body>
</html>
页面效果这样,灰常简单 8. 第三个页面应该是购买记录,忘记改了,算了就这么地吧。配套三个路由如下,虽然很长,但基本一个逻辑。
@user_bp.route('/login',methods=['GET','POST'])
def login():
if request.method == 'POST':
name = request.form.get('name')
print(name)
person=Person()
person.name=name
db.session.add(person)
db.session.commit()
return 'nihao'
return render_template('index.html')
@user_bp.route('/wupinlogin',methods=['GET','POST'])
def wupinlogin():
if request.method == 'POST':
name = request.form.get('name')
print(name)
thing=Thing()
thing.name=name
db.session.add(thing)
db.session.commit()
return '东西'
return render_template('index.html')
@user_bp.route('/goumai',methods=['GET','POST'])
def goumai():
if request.method == 'POST':
name = request.form.get('name')
thing = request.form.get('thing')
numbers = request.form.get('numbers')
guanxi=GuanXi()
guanxi.u_id=Person.query.filter(Person.name==name).first().id
guanxi.t_id = Thing.query.filter(Thing.name == thing).first().id
guanxi.numbers = numbers
db.session.add(guanxi)
db.session.commit()
return '东西'
return render_template('index.html')
- 查询路由,这个路由相对要复杂一些,HTML那里采用GET方式传参数,这边路由接收。
@user_bp.route('/chaxun',methods=['GET','POST'])
def chaxun():
person=Person.query.all()
thing = Thing.query.all()
name = request.args.get('name')
wupin = request.args.get('wupin')
if name :
person=Person.query.filter(Person.name==name).first()
for i in person.thing :
print(i.name)
print(GuanXi.query.filter(GuanXi.t_id==i.id).first().numbers)
return '啊不写页面了,打印能看见就得了'
else :
print('没有查询用户')
if wupin :
things = Thing.query.filter(Thing.name == wupin).first()
print('本次查询的是:')
for i in things.person:
print(i.name)
print(GuanXi.query.filter(GuanXi.t_id == i.id).first().numbers)
print('查询完毕')
return '唔,不写不写'
else:
print('没有查询物品')
return render_template('chaxun.html',person=person,thing=thing)
配套chaxun.html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for i in person %}
<a href="/chaxun?name={{ i.name }}">{{ i.name }}</a><br>
{% endfor %}
{% for i in thing %}
<a href="/chaxun?wupin={{ i.name }}">{{ i.name }}</a><br>
{% endfor %}
</body>
</html>
很多内容写在注释里了,注意看下。
避坑指南:在网页提交内容的时候尽量避免中文名的出现,毕竟有的时候中文会有乱码坑,所以变通的做法是HTML页面显示的用户以及物品的名字,传送的是对应的ID号,这样比较稳妥,反正查询的时候对应着id更方便些
|