上篇介绍了如何部署安装开发环境。从这篇开始详细描述一步步开发过程。
python的web框架flask是个很轻量级的,安装方便,可是官方网站能提供的文档,不是很详细。我从头开始详细描述我本次的开发过程。
数据库采用的Mysql,ORM框架采用的flask-sqlalchemy,flask-sqlalchemy是对于sqlalchemy框架的封装。更好的跟flask框架融合。之前开发公司项目一直使用的是.net,在.NET里面有DataTable类,相当于SQL查出来的结果集跟对象之间并没有直接联系。后面我会用专门的篇幅总结flask-sqlalchemy的专门知识。
首先要知道python项目包的概念可以理解为目录,每个python目录都一个_init_.py文件,这个具体怎么个流程我这就不细研究了。
1)先看我这个项目的目录结构。
这个文件目录参考了以前公司开发项目的结构。
2)开发项目涉及到
web框架:flask
ORM框架:flask-sqlalchemy
Log插件:logzero
EXCEL处理插件:xlrd
查看本机安装的python插件情况,可以在cmd下运行pip freeze.
3)安装各个插件,如果在linux下很可能已经安装了python2.7版本。在安装python3以后,安装其他插件时需要使用pip3命令。
在cmd下执行
pip install -upgrade pip (更新pip程序)
pip install flask (安装flask框架)
pip install flask-sqlalchemy (安装flask-sqlalchemy框架)
pip install pymysql (安装python连接数据库插件)
pip install logzero (安装logzero日志插件)
pip install xlrd (安装xlrd插件,读取EXCEL插件)
4)先编辑runserver.py
from mock import app
if __name__ == '__main__':
#JSON的汉字是否以ASCII码输出,选择false
app.config['JSON_AS_ASCII']=False
app.run(debug=True)
5)再编辑mock下的_init_.py
# -*- coding: utf-8 -*-
from flask import Flask,redirect,url_for
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
#通过FLASK生成app
app=Flask(__name__)
#这个根据情况而定,CORS(app)解决跨域访问问题,这块没有仔细研究
CORS(app)
#flask的配置通过mock.setting来读取
app.config.from_object('mock.setting')
#通过app创建数据库访问对象db
db = SQLAlchemy(app)
#加载model类
import mock.model.mockmodel
#加载视图层
import mock.controller.SearchController
import mock.controller.Uploadexcel
6)Model层具体如下,这里大概说明一下业务关系。
songs表示歌曲,对应songs表。
artists表示歌手表,对应artists表。
一首歌可以被多个歌手唱,一个歌手也可以唱多首歌,所以歌曲和歌手之间的关系是多对多。
多对多的关系保存在artist_songs表中。因为artist_songs表会在后面配置多对多关系时使用,所以放在最前面。
还有一个类lyric_copies,是歌词版权,表示一首歌可能会有多种版权分配方式,所以是一对多的关系。
这里先呈列代码,后面详细篇幅介绍flask-sqlalchemy的使用。
from mock import db
artist_songs = db.Table('artist_songs',
db.Column('song_id', db.Integer, db.ForeignKey('songs.id')),
db.Column('artist_id', db.Integer, db.ForeignKey('artists.id'))
)
class songs(db.Model):
__tablename__ = 'songs'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(255), nullable=True)
lyrics = db.Column(db.Text(), nullable=True)
created_at = db.Column(db.DateTime, nullable=False)
artists=db.relationship('artists', secondary=artist_songs,backref = db.backref('artists'),lazy="select")
lyric_copies=db.relationship('lyric_copies',backref='songs',lazy='select')
def jsonstr(self):
artist=[]
if self.artists is not None and len(self.artists)!=0:
for art in self.artists:
artist.append(art.name)
lyricarr=[]
if self.lyric_copies is not None and len(self.lyric_copies)!=0:
for lyr in self.lyric_copies:
lyricarr.append(lyr.jsonstr())
jsondata = {
'ID': self.id,
'title': self.title,
'artist': artist,
'lyric':self.lyrics,
'copyrights':{
'lyric':lyricarr
}
}
return jsondata
class artists(db.Model):
__tablename__ = 'artists'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=True)
gender = db.Column(db.Integer, nullable=True)
location = db.Column(db.String(255), nullable=True)
created_at = db.Column(db.DateTime, nullable=False)
updated_at = db.Column(db.DateTime, nullable=False)
class lyric_copies(db.Model):
__tablename__ = 'lyric_copies'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=True)
created_at = db.Column(db.DateTime, nullable=False)
updated_at = db.Column(db.DateTime, nullable=False)
song_id = db.Column(db.Integer, db.ForeignKey('songs.id'),nullable=False)
7)Controller层的处理查询需求的searchcontroller.py
from mock import app
from flask import jsonify,request
from mock.Utility.RequestHelper import RequestHelper
from mock.Utility.logger import logger
from mock.BSL.SongsBSL import SongsBSL
@app.route('/search', methods=['GET', 'POST'])
def search():
try:
keyvalue=RequestHelper.getValue(request, 'keyvalue')
pagesize=RequestHelper.getValue(request,'pagesize')
pageindex=RequestHelper.getValue(request,'pageindex')
resultdata=[]
if pagesize =='':
pagesize=20
if pageindex =='':
pageindex=1
songsbsl=SongsBSL()
songlist=songsbsl.QuerySongListByORCondition(keyvalue)
songitems=songlist.paginate(int(pageindex), int(pagesize),False)
if songitems is not None and len(songitems.items)!=0:
for ss in songitems.items:
result.append(ss.jsonstr())
return jsonify(resultdata)
except Exception as e:
logger.error(str(e))
return jsonify(resultdata)
8)业务逻辑层的SongsBSL.py
from mock import db
from mock.model.mockmodel import songs, artists, artist_songs
from sqlalchemy.sql.expression import or_, and_
class SongsBSL():
def QuerySongListByORCondition(self,keyvalue):
return songs.query.join(artist_songs).join(artists).filter(or_(songs.title.like('%'+keyvalue+'%') , artists.name.like('%'+keyvalue+'%')))
9)工具类中的RequestHelper.py
class RequestHelper:
@staticmethod
def getValue(request,parm):
if request.method == 'POST':
result=request.form.get(parm)
else:
result=request.args.get(parm)
if result is None:
return ''
else:
return result.encode('utf-8').decode('utf-8')
在这里我先把基本的主要代码先罗列上来,具体技术细节后面的篇幅单独拿出来讲。