Python:flask框架web开发实践

896人浏览 / 0人评论 / 添加收藏

python在网络方面的应用非常广泛,这里我们关注一下网站服务器及web开发部分。python几行代码就可以搭建一个web服务器,然后使用python语言来开发后台服务。之前的文章我对web服务做了较为详细的介绍,这个服务主要包括http的各种类型请求,如get、post等常规请求。对于web开发,不同页面之间的跳转、数据传输通信、网页存储、缓存等是基础知识,如果采用原生python来写估计难度还是很大的,所以感谢前人栽树,有了一些成熟的框架模块,我们再来使用时就非常方便。当然至于python用于web服务的性能如何,这里我们不做讨论。在web开发框架部分,较为知名的包括django、flask等框架。

Flask是一个用Python编写的Web应用程序框架。它由Armin Ronacher开发,他领导一个名为Pocco的国际Python爱好者团队。Flask基于Werkzeug WSGI工具包和Jinja2模板引擎。两者都是Pocco项目。对于Flask框架的应用基础和使用经验,网络上有许多可以文章可以参考。我们以上手实践为主,来使用flask搭建一个较为简单的web网站。

(1)flask安装

flask是第一个第三方库。与其他模块一样,安装时可以直接使用python的pip命令实现。

首先要保证安装好python的开发环境,建议安装python3。笔者安装的版本是3.9

开发IDE使用的是vscode,当然你也可以使用pycharm、idea、spyder等等都可以。

flask的安装命令:pip install flask

(2)flask搭建服务器

flask是web开发框架,简单易学,因此用flask来搭建web服务也非常简单。

新建一个项目,命名为web,然后新建一个python文件,命名为main.py。在代码中输入如下代码:

from flask import  Flask
app=Flask(__name__)

@app.route('/')
def index():
    return 'welcome to my webpage!'

if __name__=="__main__":
    app.run(port=2020,host="127.0.0.1",debug=True)

这样一个flask的web项目就完成了。

在当前目录下,在终端termianl中输入命令:python main.py就可以运行起来了。效果如下:

不过要在return里语句加入html长串代码,显然不合适,所以需要使用flask库里的Jinja2模板引擎,调用flask模块里的render_template方法,将静态的html文件传入,同时也可以将数据传输到html文件中显示。此时我们修改一下上述案例代码,形成一个相对完善的一个demo。

(3)flask开发简单网站

到此为止,我们使用flask框架实现了一个网页的开发,还可以传输数据。但网站肯定是由多个网页构成的,多个网页之间还要实现相互链接访问。下面我们在上述基础上增加两个网页,来说明多网页开发和链接的方法。

蓝图是flask框架为解决项目框架搭建的工具。我们将一个网站所有的路由文件都放在main.py服务器文件中,简单的业务处理是没问题,但随着业务量需求增多,在不断扩展时将所有路由配置都放在一个文件里肯定是不行了,需要分业务来配置路由及模型,此时就可以使用flask框架提供的blueprint类来实现。案例包括首页、用户注册、新闻、产品介绍业务,由此我们可以将这几个业务分开单独各成一个路由处理文件。

首先在web目录下新建三个py文件,分别命名为user.py、news.py、product.py。每个文件处理对应的业务。在每个文件里都使用blueprint模块,以user.py为例,使用的方法如下:

from flask import Blueprint, render_template, session, url_for,request
from werkzeug.utils import redirect

user=Blueprint('user',__name__) #蓝图使用方法,参数里给定文件名,还可以给定url前缀
@user.route('/login') #使用user的路由配置
def loginpage():
   return render_template("login.html")

@user.route('/loginProcess',methods=['POST','GET']) #使用user 的路由配置
def loginProcesspage():
   if request.method=='POST':
      nm=request.form['nm']
      pwd=request.form['pwd']
      if nm=='wlx' and pwd=='111':
        session['username']=nm
        print(session['username'])
        return redirect(url_for('index'))
      else:
        return 'the username or userpwd does not match!'
 

news.py代码如下:

from flask import Blueprint, render_template
import sys
sys.path.append("../..")
from dbUtil import DBUtils
news=Blueprint('news',__name__) #news蓝图
 
@news.route('/news')
def newspage():
   db=DBUtils('web.db')
   sql='select * from news'
   newslist=db.db_action(sql,1)
   return render_template("news.html",data=newslist)

@news.route('/news/edit')
def newsEditpage():
   return '/news/edit'

product.py代码如下:

from flask import Blueprint, render_template
product=Blueprint('product',__name__)

@product.route('/product')
def productpage():
   return render_template("product.html")

主代码main.py如下:

from flask import Flask, render_template, url_for, request, redirect, session
from news import news #导入news蓝图
from user import user #导入user蓝图
from product import product #导入product蓝图
 
app=Flask(__name__)
app.secret_key='any random string'
urls=[news,user,product] #将三个路由构建数组
for url in urls:
   app.register_blueprint(url) #将三个路由均实现蓝图注册到主app应用上
 
@app.route('/')
def index():
   userinfo=''
   return render_template("index.html",data=userinfo)
 
if __name__=="__main__":
   print(app.url_map) #打印url结构图
   app.run(port=2020,host="127.0.0.1",debug=True)

保存好几个文件后,从main.py中执行启动服务,在浏览器地址栏里可以顺利浏览本案例实现的网站,这已经测试正常通过。

蓝图模块非常有利于网站业务逻辑的部署,大大提高维护有效性,尤其是在复杂业务处理时分而治之思想非常有效。另外在页面开发过程中,还有网页页面的一些共享需要,比如对于一个网站,页面头部和底部基本都是相同的,有时候侧边导航栏也是一样的,那在开发时就没有必要每个页面都重新写一遍相同内容的代码。我们可以将这些公用相同的内容做成模板,在需要的页面里调用即可。

备注:对于数据库,采用的是slite3。数据名:web,表名称:news

数据库的操作文件dbUtil.py源码如下:

class DBUtils:
def __init__(self, dbName): # 连接数据库
   import sqlite3
   self.conn = sqlite3.connect(dbName)
 
def db_action(self, sql, actionType=0): # 进行相关业务操作
   try:
      res = self.conn.execute(sql)
      if actionType == 1: # 当操作类型为1时代表为查询业务,返回查询列表
        return res.fetchall()
      else: # 当操作类型不为1时代表为新增、删除或更新业务,返回逻辑值
        return True
   except ValueError as e:
      print(e)
 
def close(self): # 关闭数据库
   self.conn.commit()
   self.conn.close()
 
def initDB():
   #1.创建数据库
   # db=DBUtils('web.db')
   # #2.创建新闻表
   # sql='create table news (newsid int, content text, author text)'
   # if db.db_action(sql,0)==True:
   # print("创建新闻表成功!")
   # else:
   # print("try again1")
   # #3.新增新闻
   # sql= "insert into news values(1,'武汉疫情非常严重,口罩等急需物品短缺','cao')," \
   # "(2,'全国人民都给武汉加油,疫情肯定会控制住','cao')"
   # if db.db_action(sql,0)==True:
   # print("新增新闻表成功!")
   # else:
   # print("try again1")
   db=DBUtils('web.db') #链接web数据库
   sql='select * from news' #组装查询sql语句
   newslist=db.db_action(sql,1) #查询处理并返回列表
   print('newslist:',newslist)
   db.close()
 
if __name__ == '__main__':
   initDB()

在initDB()函数中,有创建表和新增数据语句,打开后执行即可生成数据库和表。

全部评论