絕對乾貨,實例帶你瞭解python-web之flask框架

侃侃

 最近挺長時間沒碼代碼了,覺得是時候該來寫篇總結性文章了,但是想了好久都沒找到有啥可寫的。後面翻了一下以前寫的博客,好像有關於python-web的博文一篇都沒有,那麼就從這篇開始吧。

 我接觸python-web是從建立自己博客的念頭開始的,那時候總想有個自己狂拽酷炫吊炸天的網站,但是怎麼建立用什麼做一頭霧水,磕磕絆絆的搞了半個多月算是懵懵懂懂的入門了。

 據我瞭解的python-web框架有flaskdjango,而這兩者的區別呢,我也不是很懂,我沒用過django,只是大慨知道flask跟django呢,在我個人看來一個就像是毛坯房,一個是精裝房,看個人喜好吧。

毛坯房
精裝房

 首先我比較喜歡折騰,所以肯定首選是flask,可塑性高,方便簡單。再者呢,還不是因爲窮!你看這精裝房,你看這配飾,多高級!

 哈哈哈,說些玩笑話,其實還是因爲看了下兩者源碼的對比,發現flask好像比較簡潔明瞭,頭不會那麼快禿。

 好了,步入正題,該文我將會簡單的使用flask來進行一些總結,最後再大概說一下怎麼在雲服務器上運行flask並佈置網站。

簡單嘗試

 第一步不用說肯定是pip install flask,使用國內源比較快。

pip install -i https://pypi.doubanio.com/simple

 接着看圖示。
1

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/5/6 19:55
# @Author  : Cxk
# @File    : run.py

from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
    return 'Hello Cxk!
if __name__ == '__main__':
    app.run(debug=True)

 可以看到只要幾步就可以在一個網頁顯示字符,大概分爲四個步驟,導入包,創建實例,創建路由函數,調用實例。
 在這裏我就只跟大家講講什麼叫路由,實際上它就是一個裝飾器,@app.route(’/’),把函數綁定到固定的url上面,例如現在是(’/’),默認是http://127.0.0.1:5000/主頁面,當我們在上面加個名字,那麼當你打開http://127.0.0.1:5000/時它是不會顯示的。例如我們創建@app.route(’/cxk’),我們再試一試。2

Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

 不出意外,我們把默認路由去了改爲(’/cxk’)打開頁面顯示沒找到。而我們手動給它加上/cxk後可以看到又回到了剛纔的主頁面,其實路由就是用來區分不同網頁,下面我們再來試試返回一個網頁,剛剛我們只是返回一個字符串。
 首先現在項目文件下建立,兩個文件夾,一個static,一個templates。在這裏插入圖片描述 static是存放靜態文件的文件夾,templates是用來存放網頁源代碼的文件夾,static我們暫時用不到,先在templates下創建一個網頁文件index.html。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
Hello,CXk!
</body>
</html>

 然後我們將源碼改一下,加一個 render_template模板。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/5/6 19:55
# @Author  : Cxk
# @File    : run.py

from flask import Flask, render_template
app = Flask(__name__
@app.route('/')
def index():
    return render_template('index.html')
@app.route('/cxk')
def cxk():
    return 'Hello,CXk!'
if __name__ == '__main__':
    app.run(debug=True)

在這裏插入圖片描述
在這裏插入圖片描述
 有沒發現,兩個文字雖然一樣,但是網頁中的字體比較好看,還有網頁頂端的title,直接返回字符串title它是直接給你一個url名,而網頁是自己設置的

進階使用

 有了以上基礎,我們就可以來做比較有意義的東西了,接口。這裏呢,我拿三端登錄作爲例子,所謂三端呢,就是網頁端,pc端,微信小程序端,對應–網頁,電腦,手機。

設置接口

 上面忘講了前後端數據傳遞,這裏傳遞頁面時我加上兩個參數,在前端頁面上顯示賬號:密碼:,分別對應到頁面上的
{{name}},{{password}},事實就是這麼簡單,{{}},兩個大括號的事,想了解更多自己百度下。

 我直接判斷如果帳號密碼是123456那麼就登錄成功,反之則失敗。返回則是json格式數據,在網頁端其實我們可以直接返回其他頁面,但是爲了在pc端跟小程序好處理,這裏我們返回json格式比較好。

<input id="username" type="text" name='username' autocomplete="off" placeholder={{name}}>
<input id="password" type="password" name='password' autocomplete="off" placeholder={{password}}>
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/5/6 19:55
# @Author  : Cxk
# @File    : run.py

from flask import Flask, render_template,request
import json
app = Flask(__name__)
@app.route('/')
def index():
    name='帳號:'
    password='密碼:'
    return render_template('index.html',name=name,password=password)

@app.route('/login', methods=['POST'])
def login():
    try:
        # 小程序獲取post數據
        if request.data:
            data = request.data.decode('utf-8')
            data_json = json.loads(data)
            username = data_json['username']
            password = data_json['password']

        #網頁以及PC端
        else:
            username = request.form.get('username')
            password = request.form.get('password')
        if username == '123456' and password == '123456':
            return json.dumps({"code":200,"msg": "登錄成功"},ensure_ascii=False)
        else:
            return json.dumps({"code": 404, "msg": "登錄失敗"}, ensure_ascii=False)
    except:
        return json.dumps({"code": 500, "msg": "後臺錯誤"}, ensure_ascii=False)
        

if __name__ == '__main__':
    app.run(debug=True)

網頁端

 這裏是我網上隨便找的一個登錄界面,挺好看的,我自己改版了下,圖片資源放在static下images文件夾下,下面是三個資源文件,分別是backgroud.png,password.png,login.png,emil.png
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>登錄</title>
    <style>
        * { margin: 0; padding: 0; }
        html { height: 100%; }
        body { height: 100%; background: #fff url(static/images/backgroud.png) 50% 50% no-repeat; background-size: cover;}
        .dowebok { position: absolute; left: 50%; top: 50%; width: 430px; height: 550px; margin: -300px 0 0 -215px; border: 1px solid #fff; border-radius: 20px; overflow: hidden;}
        .logo { width: 75px; height: 75px; margin: 50px auto 50px; background: url(static/images/login.png) 0 0 no-repeat; }
        .form-item { position: relative; width: 360px; margin: 0 auto; padding-bottom: 30px;}
        .form-item input { width: 288px; height: 48px; padding-left: 70px; border: 1px solid #fff; border-radius: 25px; font-size: 18px; color: #fff; background-color: transparent; outline: none;}
        .form-item button { width: 360px; height: 50px; border: 0; border-radius: 25px; font-size: 18px; color: #1f6f4a; outline: none; cursor: pointer; background-color: #fff; }
        #username { background: url(static/images/emil.png) 11px 3px no-repeat; }
        #password { background: url(static/images/password.png) 11px 3px no-repeat; }
        .reg-bar { width: 360px; margin: 20px auto 0; font-size: 14px; overflow: hidden;}
        .reg-bar a { color: #fff; text-decoration: none; }
        .reg-bar a:hover { text-decoration: underline; }
        .reg-bar .reg { float: left; }
        .reg-bar .forget { float: right; }
        .dowebok ::-webkit-input-placeholder { font-size: 18px; line-height: 1.4; color: #fff;}
        .dowebok :-moz-placeholder { font-size: 18px; line-height: 1.4; color: #fff;}
        .dowebok ::-moz-placeholder { font-size: 18px; line-height: 1.4; color: #fff;}
        .dowebok :-ms-input-placeholder { font-size: 18px; line-height: 1.4; color: #fff;}

        @media screen and (max-width: 500px) {
            * { box-sizing: border-box; }
            .dowebok { position: static; width: auto; height: auto; margin: 0 30px; border: 0; border-radius: 0; }
            .logo { margin: 50px auto; }
            .form-item { width: auto; }
            .form-item input, .form-item button, .reg-bar { width: 100%; }
        }
    </style>
</head>
<body>
    <div class="dowebok">
        <div class="logo"></div>
  <form action="login" method="post">
        <div class="form-item">
            <input id="username" type="text" name='username' autocomplete="off" placeholder={{name}}>
        </div>
        <div class="form-item">
            <input id="password" type="password" name='password' autocomplete="off" placeholder={{password}}>
        </div>
        <div class="form-item"><button id="submit">登錄</button></div>
  </form>
    </div>
    <script src="static/js/jquery.min.js"></script>
</body>
</html>

效果展示

在這裏插入圖片描述

pc端

 這裏我拿了以前寫的人臉識別登錄的界面來用,有興趣的點擊傳送門

# -*- coding:utf-8 -*-
#!/usr/bin/env python
# @Time    : 2020/5/6 19:55
# @Author  : Cxk
# @File    : login.py

from tkinter.messagebox import * 
from tkinter import *
import requests

class LoginPage(object):
    def __init__(self, master=None):
        self.root = master
        winWidth = 650
        winHeight = 400
        screenWidth = self.root.winfo_screenwidth()
        screenHeight = self.root.winfo_screenheight()

        x = int((screenWidth - winWidth) / 2)
        y = int((screenHeight - winHeight) / 2)
        # 設置窗口初始位置在屏幕居中
        self.root.geometry("%sx%s+%s+%s" % (winWidth, winHeight, x, y))
        # 設置窗口圖標
        # root.iconbitmap("./image/icon.ico")
        # 設置窗口寬高固定
        self.root.resizable(0, 0)
        self.student_number = StringVar()
        self.student_pw = StringVar() 
        self.createPage()
    
    def createPage(self):
        '''
        登錄頁面
        1:創建圖片組件
        2:根目錄基礎上添加Frame容器
        3:Frame容器上添加註冊控件
        '''
        bm=PhotoImage(file=r'cxk.gif')
        self.lab3=Label(self.root,image=bm)
        self.lab3.bm=bm
        self.lab3.pack()
        
        self.page = Frame(self.root) 
        self.page.pack()
        Label(self.page).grid(row=0, stick=W) 
        Label(self.page, text = '       學號:').grid(row=1, column=0,stick=W, pady=10) 
        Entry(self.page, textvariable=self.student_number).grid(row=1, column=1, stick=E) 
        Label(self.page, text = '       密碼:').grid(row=2, column=0,stick=W, pady=10) 
        Entry(self.page, textvariable=self.student_pw, show='*').grid(row=2, column=1, stick=E) 
        Button(self.page, text='學生登錄', command=self.student_loginCheck).grid(row=3,column=1) 

    def student_loginCheck(self):
        try:
            Student_number=self.student_number.get()
            Student_pw=self.student_pw.get()
            if Student_number=="" or Student_pw=="":
                showinfo(title="錯誤",message='帳號和密碼不能爲空!')
            else:
                data={
                    'username':Student_number,
                    'password':Student_pw
                }
                res=requests.post('http://127.0.0.1:5000/login',data)
                if (res.json()['code']==200):
                    self.page.destroy()
                    self.lab3.pack_forget()
                    StudentPage(self.root)
                else:
                    showinfo(title='錯誤',message='%s'%res.json()['msg'])
        except:
            showinfo(title='錯誤',message='未知錯誤!')
        
class StudentPage(object): 
    def __init__(self, master=None): 
        self.root = master #定義內部變量root 
        self.root.geometry('%dx%d' % (650, 400)) #設置窗口大小 
        self.root.resizable(0,0) #防止用戶調整尺寸
        self.createPage() 
    
    def createPage(self): 
        self.menuPage = MenuFrame(self.root) # 創建不同Frame 
    
        
class MenuFrame(Frame): # 繼承Frame類 
    def __init__(self, master=None):
        Frame.__init__(self, master) 
        self.root = master #定義內部變量root
        self.createPage()
  
 
    def createPage(self):
        strs="登錄成功!"
        Label(self.root,text=strs,font=("Arial", 30)).pack()
    
root = Tk() #建立一個根窗口,所有窗口的基礎
root.title('學生管理系統')
LoginPage(root)#進入調用登錄
root.mainloop()

效果展示

在這裏插入圖片描述

重點代碼講解

 我們先獲取到前端輸入框的字符,然後將該字符進行requests.post帶上去提交請求,爲啥是post而不是get呢,看前面的代碼,我在接口處設置了methods=[‘POST’],表示該處只接受post請求,而一般帳號密碼都是post請求的,因爲post請求不會在url顯示,想了解更多自行百度post與get分別。然後我們根據服務器接口返回的json數據中的“code”進行判定,200表示請求登錄成功,看你接口怎麼設置。
 注意,我們要先將網頁源碼運行,不然找不到請求的。

Student_number=self.student_number.get()
Student_pw=self.student_pw.get()
if Student_number=="" or Student_pw=="":
    showinfo(title="錯誤",message='帳號和密碼不能爲空!')
else:
    data={
        'username':Student_number,
        'password':Student_pw
    }
    res=requests.post('http://127.0.0.1:5000/login',data)
    if (res.json()['code']==200):
        self.page.destroy()
        self.lab3.pack_forget()
        StudentPage(self.root)
    else:
        showinfo(title='錯誤',message='%s'%res.json()['msg'])

微信小程序

js

//index.js
//獲取應用實例
const app = getApp()
Page({
  data: {
    name:'',
    password:''
  },
  
  name(e){
    this.setData({
      name: e.detail.value
    })
  },
  password(e){
    this.setData({
      password: e.detail.value
    })
  },
  formSubmit: function () {
    wx.request({
      url: 'http://127.0.0.1:5000/login',
      data: {
        username: this.data.name,
        password: this.data.password
      },
      method: 'post',
      header: {
        'content-type': 'application/json'
      },
      success: function (res) {
        var msg=JSON.parse(res.data)
        wx.showModal({
          title: '提示',
          content: msg['msg'],
        })
      }
    })
  }
  ,
  onLoad: function () {
  },
}

wxml

<view class='container'>
  <view class='header'>
    <text>登錄嘗試</text>
  </view>
    <view class='section'>
      <text>帳號:</text>
      <input type='number' placeholder='請輸入學號' bindinput ="name"/>
    </view>
    <view class='section'>
      <text>密碼:</text>
      <input password='true' placeholder='請輸入密碼' bindinput ="password"/>
    </view>
    <view class='button'>
      <button type='primary' form-type='submit' bindtap="formSubmit" >登錄</button>
    </view>
</view>

wxss

/**index.wxss**/
input{
  border: 1px solid #ccc;
  width: 310px;
  height: 40px;
}
.button{
  margin-top: 20px;
}
.header text{
  font-size: 25px;
  color: #666;
}

效果展示

在這裏插入圖片描述

後記

 至此,我們基本瞭解了flask的七七八八,剩下的就是一堆細節操作以及高端使用,一點一點學,慢慢的我們就會舉一反三,其實很多時候敲着敲着就開竅了,比如說這篇文章,其實我也是邊敲邊理解,以前沒嘗試過三端合一接口,就腦子想應該可以,然後就動手試了下,不過數據格式是個問題,小程序提交的數據跟網頁pc提交的數據不一致,這裏弄了好久。。實屬坑,最後沒辦法,用if來判斷了,有大佬知道咋回事的留言,不勝感激。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章