绝对干货,实例带你了解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来判断了,有大佬知道咋回事的留言,不胜感激。

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