侃侃
最近挺長時間沒碼代碼了,覺得是時候該來寫篇總結性文章了,但是想了好久都沒找到有啥可寫的。後面翻了一下以前寫的博客,好像有關於python-web的博文一篇都沒有,那麼就從這篇開始吧。
我接觸python-web是從建立自己博客的念頭開始的,那時候總想有個自己狂拽酷炫吊炸天的網站,但是怎麼建立用什麼做一頭霧水,磕磕絆絆的搞了半個多月算是懵懵懂懂的入門了。
據我瞭解的python-web框架有flask和django,而這兩者的區別呢,我也不是很懂,我沒用過django,只是大慨知道flask跟django呢,在我個人看來一個就像是毛坯房,一個是精裝房,看個人喜好吧。
首先我比較喜歡折騰,所以肯定首選是flask,可塑性高,方便簡單。再者呢,還不是因爲窮!你看這精裝房,你看這配飾,多高級!
哈哈哈,說些玩笑話,其實還是因爲看了下兩者源碼的對比,發現flask好像比較簡潔明瞭,頭不會那麼快禿。
好了,步入正題,該文我將會簡單的使用flask來進行一些總結,最後再大概說一下怎麼在雲服務器上運行flask並佈置網站。
簡單嘗試
第一步不用說肯定是pip install flask,使用國內源比較快。
pip install -i https://pypi.doubanio.com/simple
接着看圖示。
#!/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’),我們再試一試。
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來判斷了,有大佬知道咋回事的留言,不勝感激。