Flask自学分享

写在前面

最近两个月,学会了微信小程序,学会了Flask,接着又学会了VUE前端开发,学会了docker,gunicorn,nginx部署,独立Web开发的能力终于GET了。

内心喜悦,写文总结,记录分享。本文主要针对入门学习,希望对大家有所帮助。

作为程序员,Web开发确实很有必要去学习。因为整个互联网的核心技术就是Web开发技术。学会了Web开发,对于整个互联网的认知,对于整个编程世界的认知,都会有非常大的提升。

Flask框架

Python三大主流Web框架:Django,Flask,Tornado。

对于本人,Django入门艰难,Tornado没有接触,Flask一见钟情。

Flask,拉起一个网站,简直太简单了,简单即是美,怎不惹人爱。

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

Flask,拉起一个API服务后端,亦是如此简单,如此优雅。

from flask import Flask
from flask import jsonify
app = Flask(__name__)

@app.route('/api/user',methods=['GET'])
def get_user():
    return jsonify(code=200, msg="用户查询成功!",username = '张三',userphone = '18288889999')


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

Flask做API服务后端的入门学习

做API服务后端,主要是三块内容:路由,数据库,身份验证。(不需要 渲染 这块东西了)

from flask import Flask
from flask import jsonify
from flask import request
from Tools.dbmanager import DBManager
from Tools.decoratormanager import session_jwt_verification

app = Flask(__name__)


@app.route("/bumen",methods=['GET'])
@session_jwt_verification
def goto_bumen_search():
    ###############查询部门###############
    sqlstring0 = "SELECT id,bumenname,bumentips FROM jr_bumen"
    data0 = DBManager().executeQueryall(sqlstring0)
    if  data0 == False:
        return_data = dict()
        return_data['code'] = 5000
        return_data['msg'] = "数据库连接异常!"
        return jsonify(return_data)
    if  data0 == None:
        return_data = dict()
        return_data['code'] = 5001
        return_data['msg'] = "没有部门数据!"
        return jsonify(return_data)
    if  data0 != None:
        return_data = dict()
        return_data['code'] = 200
        return_data['msg'] = "查询成功!"
        return_data['bumendatas'] = data0
        return jsonify(return_data)



@app.route("/bumen",methods=['POST'])
@session_jwt_verification
def goto_bumen_add():
    data = request.get_json()
    bumen_name = data['bumenName']
    bumen_tips = data['bumenTips']
    ###############新增部门###############
    sqlstring0 = f"INSERT INTO jr_bumen (bumenname,bumentips) VALUES ('{bumen_name}','{bumen_tips}')"
    data0 = DBManager().executeQueryID(sqlstring0)
    if  data0 == False:
        return_data = dict()
        return_data['code'] = 5000
        return_data['msg'] = "数据库连接异常!"
        return jsonify(return_data)
    if  data0 != None:
        return_data = dict()
        return_data['code'] = 200
        return_data['msg'] = "部门添加成功!"
        return_data['bumenid'] = data0
        return jsonify(return_data)


@app.route("/bumen",methods=['PUT'])
@session_jwt_verification
def goto_bumen_alter():
    data = request.get_json()
    bumen_id = data['bumenId']
    bumen_name = data['bumenName']
    bumen_tips = data['bumenTips']
    ###############更新部门###############
    sqlstring0 = f"UPDATE jr_bumen SET bumenname='{bumen_name}',bumentips='{bumen_tips}' WHERE id= {bumen_id}"
    data0 = DBManager().executeQueryNO(sqlstring0)
    if  data0 == False:
        return_data = dict()
        return_data['code'] = 5000
        return_data['msg'] = "数据库连接异常!"
        return jsonify(return_data)
    if  data0 == True:
        return_data = dict()
        return_data['code'] = 200
        return_data['msg'] = "部门修改成功!"
        return jsonify(return_data)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

1.关于数据库

上例中的dbmanager 是本人自己写的数据库处理类,之前做过分享。
文章链接:《python操作mysql数据库的精美实用模块》

如果要用ORM,那就上Flask-SQLAlchemy库。

(ORM,相关知识,自行百度)

2.关于身份验证

上例中的dsession_jwt_verification装饰器,是自定义的,用了第三方库:pyjwt。
(JWT,相关知识,自行百度)

from flask import request
from flask import jsonify
from flask import g
from functools import wraps

import jwt
############################################################
# 装饰器管理模块
############################################################
def session_jwt_verification(view_func):
    @wraps(view_func)  # wraps函数的作用是将wrapper内层函数的属性设置为被装饰函数view_func的属性
    def verify_view_func(*args, **kwargs):
        try:
            session_jwt = request.headers['session-jwt']
            payload = jwt.decode(session_jwt, "my_jwt_secret", algorithms=['HS256'])
            session_data = payload.get('userid')
            g.userid = session_data
        except Exception:
            return jsonify(code=5901, msg="身份认证失败!")
        ###################################################################################
        return view_func(*args, **kwargs)
    ###################################################################################
    return verify_view_func
3.关于路由

实际项目中,路由这里有个问题,当我们的项目越来越大,API越来越多时,不可能把所有路由都写在一个主文件里面吧,这时就需要想办法拆分路由了。

什么办法呢?就是蓝图BluePrint。对,蓝图的作用就是拆分路由。对于蓝图,有这个理解就够了。

再配合工厂函数(对app进行统一加工处理的函数),最后的主文件变成了这样:

from flask import Flask

from Apis.login import login_api
from Apis.userdata import userdata_api

from Tools.config import config_map
####################################################################################################
# 工厂函数,对app进行加工处理
def create_app(config_name):
    app =Flask(__name__)
    app.config.from_object(config_map[config_name])

    ###注册API蓝图,并指定其对应的前缀(url_prefix)#######################
    app.register_blueprint(login_api, url_prefix="/api/login")
    app.register_blueprint(userdata_api, url_prefix="/api/userdata")

    ###初始化app的ORM,根据实际需要开启###################################
    # from app.models import db
    # db.init_app(app)

    ###初始化app的跨域,根据实际需要开启###################################
    # from flask_cors import CORS
    # cors = CORS()
    # cors.init_app(app)

    ###初始化app的邮件,根据实际需要开启###################################
    # from flask_mail import Mail
    # mail = Mail()
    # mail.init_app(app)

    return app



app = create_app(config_name='development')
#####首页视图函数,留着方便测试#############################################################
@app.route('/')
def index():
    return "Jrsoft Api Server"

##################################################################################
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

整个项目的文件目录是这样:

flask-example/
├── Apis
│   ├── login.py
│   └── userdata.py
├── Tools
│   ├── config.py
│   ├── dbmanager.py
│   └── decoratormanager.py
└── main.py
4.其他一些说明

Flask做API服务后端,相关的知识点还是蛮多的,需要自己找资料,逐一消化理解。核心内容就是上述三块:路由,数据库,身份验证。

当然,做API服务后端,还有一些其他框架,比较火爆强劲的就有FastAPI,大家可以了解一下,长得跟Flask有点像,但底层跟Flask不一样。(反正我没用,还是用的Flask)

还有Flask项目本身的开发大神 李辉 做的API框架:APIFlask,可以关注一下,是基于Flask开发的。(这个框架成熟后,我会用起来)

微信小程序的入门学习

好了,后端Flask搞定,咱接着说前端,先说微信小程序吧,然后再说Vue。

微信小程序,其官方文档就很详尽了,基本上看官方文档就足够了,当然根据自身情况,再去B站找些视频看看,辅助学习就可以了,没必要买书了。

链接在此:微信小程序官方文档

官方文档之中,有一份《小程序开发指南》,其实就是新手入门指南。入门必看!多看几遍!随着自身项目,边看边做边学,基本就会了。

而开发指南之中,又有一小节,文档之中一笔带过,但是你绝不可错过,叫【2.3.6 官方样式库】。

为了减轻开发者样式开发的工作量,我们提供了WeUI.wxss基础样式库。

WeUI是一套与微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一。包含button、cell、dialog、progress、toast、article、actionsheet、icon等各式原生。

具体使用文档可参考:https://github.com/Tencent/weui-wxss

作为独立开发者,假如没有这种东西,难道让我们自己去写样式去搞UI设计吗?这要开发到何年马月!

类似WeUI,还有一个有赞出品的UI 组件库,也非常有名,美观而好用,叫:Vant
Vant的官网:https://vant-contrib.gitee.io/vant-weapp
文档很详尽,入手很简单,自己去看吧。

Vue的入门学习

Flask做API服务后端搞定了,微信小程序也学会搞定了,想着是时候回头搞网站了吧。

Flask是web框架,本就是搞网站用的,搞网站就要用到Flask的网页渲染功能。

Flask的网页渲染功能,主要靠的就是:Jinja2模板引擎和render_template渲染函数。

学这块内容时,我是比较烦的,可能习惯了以前从事游戏开发时前后端分离的开发思维,这种前端夹着后端,傻傻分不清了,学着就有点难受,也不好学进去。

想想我都用Flask做API服务后端,WEB开发前后端分离又是大势所趋,索性Flask的渲染不学了,火热的前端框架Vue搞起了!

要学Vue,当然先要学Node.js,要会NPM。这Node.js的NPM就如同Python的pip,都是包管理工具。

Vue之下,类似微信小程序的WeUI和Vant,有一个饿了么出品的UI组件库,也非常有名,叫:ElementUI。

Vue有Vue2和Vue3两个版本,我直接用的Vue3,对应的ElementUI版本叫:ElementUI-plus。

ElementUI-plus的官网:https://element-plus.gitee.io/zh-CN/

另外,其实类似WeUI,Vant,ElementUI这样的UI样式库和组件库,还有不少,如:贤心的LayUI,阿里的 Ant Design......

在这里,真的要感谢这些UI样式库和组件库的分享公司,团队或大神,没有这些样式库和组件库,像我这样的个体开发者真的都不知道怎么在web开发上继续下去。

之前,我在web开发上的学习,就是卡在了前端页面的构建上,内心形成了一种恐惧。而自从了解到有这些样式库和组件库的存在,前端瞬间变得轻松简单了,开发瞬间变得美好起来。

Docker的入门学习

前后端搞定,代码开发完成,最后当然要放到真正运行的服务器上,这就是部署了。

高级的部署方法是基于容器进行部署。Docker 就是目前最流行的容器平台。

(Docker ,相关知识,自行百度)

微信小程序的部署,直接上传代码即可,下面主要分享Flask+Vue的网站部署

1.项目目录结构
myweb_project/
│
├── flask
│   ├── Dockerfile
│   ├── gunicorn.config.py
│   └── flask_app # flask项目的代码
│
├── mysql
│   ├── Dockerfile
│   └── myweb.sql
│
├── nginxvue
│   ├── dist    # 打包的vue项目
│   ├── Dockerfile
│   └── nginx.conf
│
└──docker-compose.yml
2.Docker+Gunicorn 部署 flask后端

gunicorn.config.py文件如下:

import multiprocessing
bind = '0.0.0.0:9191' # 监听内网端口80
backlog = 512
timeout = 30
worker_class = 'gevent' # 工作模式协程
workers = multiprocessing.cpu_count() * 2 + 1 # 并行工作进程数
threads = 2               # 指定每个工作者的线程数


pidfile = 'gunicorn.pid' # 设置进程文件目录
loglevel = 'info'   # 设置日志记录水平
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'
accesslog = "gunicorn_access.log"      # 访问信息日志文件
errorlog = "gunicorn_error.log"        # 错误信息日志文件
reload=True  # 代码发生变化是否自动重启

Dockerfile文件如下:

FROM python:3.8
WORKDIR /Project/jrsoftdemo
COPY . .
RUN pip install -r Tools/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
CMD gunicorn  -k gevent   -w 5   -b 0.0.0.0:8080   backend:app
3.Docker+Nginx 部署 Vue前端

nginx.conf文件如下:

server {
    listen       8080;
    server_name  localhost;
    access_log  /var/log/nginx/host.access.log  main;
    error_log  /var/log/nginx/error.log  error;

    location / {  # 直接匹配端口返回前端
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    location /api/ {  # 匹配api的,转发给后端,
        rewrite  /api/(.*)  /$1  break;
        proxy_pass http://192.168.99.100:9999;  # 这里是宿主机的ip
    }
}

Dockerfile文件如下:

# 设置基础镜像
FROM nginx

# 将dist文件中的内容复制到 /usr/share/nginx/html/ 这个目录下面
COPY dist/  /usr/share/nginx/html/

#用本地的 nginx.conf 配置来替换nginx镜像里的默认配置
COPY nginx.conf /etc/nginx/conf.d/default.conf

4.Docker部署 mysql数据库

如果你的项目,数据库也需要Docker部署,当然也是可以的。
Dockerfile文件如下:

FROM mysql:5.7.20

部署成功之后,数据库软件通过IP连入,便可查看管理。

5.Docker的相关命令
# 创建镜像
docker build -t  jrsoftflask  .  

# 启动生产环境
docker run -p 9999:9191  --name jrsoft_demo  -d jrsoftflask

# 查看镜像
docker images

# 删除镜像
docker rmi -f e7cd0fde3f42

# 进入docker镜像环境
docker run -it jrsoftflask /bin/bash

# 列出运行容器
docker ps

# 列出全部容器
docker ps -a

# docker远程服务器部署——方案一:tar打包法
# 生成tar
docker save jrsoftflask>images.tar
# 加载tar
docker load < images.tar

# docker远程服务器部署——方案二:镜像云仓库法
# 将本地镜像推到[远程仓库]--DockerHub/阿里云Docker仓库/腾讯云Docker仓库
docker push 178.104.162.39/dev/vdi-controller:arm0324
# 从[远程仓库]拉取镜像--DockerHub/阿里云Docker仓库/腾讯云Docker仓库
docker pull 178.104.162.39/dev/vdi-controller:arm0324
6.docker-compose编排

像Flask+微信小程序,只需要用一个docker容器部署Flask就可以了,自然不需要docker-compose编排。

而像Flask+Vue项目,用到多个docker容器,那用docker-compose编排,一键拉起,自然更加方便。

docker-compose.yml文件如下:

version: '3'
services:
  mysql:
    build: ./mysql
    ports:
      - "3306:3306"
    container_name: mysql
    environment:
      - MYSQL_ROOT_PASSWORD=mypws123456789
    restart: always

  flask:
    build: ./flask
    ports:
      - "9999:9191"
    container_name: flask
    restart: always
    volumes:
     - "./flask/lab_app:/root/lab_app"


  nginx:
    build: ./nginxvue
    ports:
      - "8080:8080"
    container_name: nginxvue
# 启动命令
docker-compose up -d
7.注意事项

Docker部署,需要注意每个容器的IP和端口,假若设置不对就连不上了。

在docker-compose编排的时候,可进行相应的网络设置,上面文件并未涉及,大家可自行研究。

自学方法

1.git和github

现在的程序员,git基本必学了,没什么好说的。一般用用的话,掌握几条命令就可以了

# 创建仓库
git init

# 添加到暂存区
git add .

# 提交到仓库
git commit -m '提交注释'

# 关联远程仓库
git remote add origin git@github.com:......

# 推送到远程仓库
git push -u origin master

# 克隆远程仓库
git clone git@github.com:......

学习git,自然会用上github。github上好东西太多了,想找什么源码,尽管去上面搜索好了。

所以,这里有个入门捷径:先去github,搜几个简单的项目源码,下载下来进行学习,看看别人都是怎么做的,最简单的项目是怎么搭建的,如此入门再好不过了!

后面有时间有机会,我也会写几个入门项目源码,上传到github,届时分享给大家。

2.自己的项目

看别人的文章,看别人的视频,看别人的源码,终究是顺着别人的思维,看的时候貌似都会了,其实往往离真正会做还有一段距离。

所以,这里有个入门捷径:学东西前,先有一个自己的项目,越现实越具体越好。
不管是自己主动构想的项目,还是他人被动赋予的项目,都很好,只要有了项目,便有了明确的目标。
然后边做边学,边学边做,学以致用,知行合一,如此最快,做才是真正的得到!

3.目标拆分法

目标往往很大,任务往往艰巨。不要怕,拆分他!

目标拆分法是做事万能法,不管是做项目,还是学习,不管是写程序,还是写小说......

目标越大,越需要拆分,拆分成一个个小目标,一个个可执行的不让人恐惧的小目标。

然后一个小目标一个小目标的去完成,像做游戏任务一样,像玩游戏闯关一样,按部就班,逐个击破即可。

这目标拆分法,也是管理学中的方法,也是游戏设计中的一大核心要义。

游戏有四要素:目标,规则,反馈,自愿参与。

你看,你将学习目标拆分成多个可执行的小目标后,还可以给每个小目标设定完成奖励,如此一来,你可以将学习转化为游戏一般好玩,这叫学习游戏化。

写在最后,网站开发,我的心愿

大约10年以前,不做游戏策划之后,便萌生了一个想法:要学会网站开发,做自己想做的网站。

而在正式转做程序员之后,这个想法也便随之变得愈加强烈和执着,已然成为了人生的必达目标,人生的一个心愿。

而且,时常心想:一个程序员,如果连网站开发都不会,当别人问你什么工作时,好意思跟别人说自己是程序员,是软件开发工程师吗?

所以,很早以前,便看了html,css,javascript,但是看懂了又如何?真正搞起网站来,依然一脸懵逼。

后来,为了搭建网站,也接触了wordpress等等各种搭建网站的工具,但这些毕竟都只是工具,并不是自己想要的能力——真正网站开发的能力。

后来会了python,便开始学python的web框架django,可是对我来说django似乎太复杂了,起手学了两次,每次花了两三天还感觉门都没摸着,也便兴味索然,算了算了。

后来工作之中,同事请我帮忙搭建一个API服务,那时我也不真正清楚什么是API服务,但我自信我大python啥不能干,网上一搜,短短几行代码便能搭建,so easy,便应下了同事的任务,帮忙完成了这个API服务。而这一次任务中,用的正是python的另一个web框架——flask。

flask,短短几行代码,简单明了,便能搭建api服务,便能搭建网站,简直太棒了,一见钟情。

于是,正式开始学习flask,以书本《Flask Web开发》(米格尔格林贝格 著)为主要教材,以B站大神们分享的flask视频为辅助学习。

《Flask Web开发》,逐字逐句阅读,逐行代码敲下,学了大半个月,仿佛都学下来了,其实很多概念并不清晰,很多东西把握不住。自己很清楚,真正动手去做,根本没把握独自开发一个网站,所以说到底,知识还是没有内化,功夫还是没有学到。于是,停了停,又放了一段时间。

后来,那个同事又找我帮忙做微信小程序。微信小程序开发,我也是摸了好几次,也想学也是一直学不会,但现在有了flask的半吊子功夫,心里是有点底的,知道整体是怎么搭建的,都需要哪些知识技能,而且我内心太喜欢这种全新的实际项目了,因为我知道,在这种实际项目上,边做边学,又有项目的现实约束,学东西才是最快的。

于是,接下来,大概一个月,我真正学会了微信小程序,学会了Flask,接着一个月,又学会了VUE前端开发,学会了docker,gunicorn,nginx部署,当然称不上完全了解和精通,但独立搭建网站已经没有问题了,更深入的原理知识根据实际需求再去了解即可。总之,当前的程度对我来说基本足够了,此生一个心愿也算了了。

心愿已了,技能获得,内心欢喜,写下此文,以作总结,留做记录,分享于此。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容