flask框架学习

以前只整过js的后端,这次网安平台实践大作业打算用python写后端,于是赶紧滚过来学学flask

简介与安装

Flask是一个轻量级的可定制框架,使用Python语言编写,较其他同类型框架更为灵活、轻便、安全且容易上手。它可以很好地结合MVC模式进行开发,开发人员分工合作,小型团队在短时间内就可以完成功能丰富的中小型网站或Web服务的实现。

Flask是目前十分流行的web框架,采用Python编程语言来实现相关功能。Flask框架的主要特征是核心构成比较简单,但具有很强的扩展性和兼容性,程序员可以使用Python语言快速实现一个网站或Web服务。一般情况下,它不会指定数据库和模板引擎等对象,用户可以根据需要自己选择各种数据库。

安装直接pip install flask就行,如果害怕环境乱了,建议用anaconda或者virtualenv

我win下的环境已经乱的可以了,懒得搞了(

安装完成后可以用python运行下面的代码试试

from flask import Flask

app = Flask(__name__) # Flask函数接收参数__name__,指向了程序所在的包,即Flask将在当前模块运行

@app.route("/") # route()是一个装饰器,它会进行路由匹配,将请求的url映射到函数上。这里'/'与hello_world进行了绑定
def hello_world():
    return "Hello, World!"

if __name__ == '__main__':
    app.run() # run方法启动了web服务器,默认是127.0.0.1:5000

能看到这个页面就安装胜利了

顺便讲一下上面代码中的run(),其参数是app.run(host, port, debug, options)

  • host是将要监听的域名,默认为localhost(127.0.0.1),设置为0.0.0.0就可以在外部服务器使用
  • port是监听的端口,默认5000
  • debug是提供调试信息,默认为false
  • options是要转发到底层的Werkzeug服务器.

需要注意的一点,根据官方文档,尽管交互式调试器在允许 fork 的环境中无法正常使用(也即在生产服务器上正常使用几乎是不可能的),但它依然允许执行任意代码。这使它成为一 个巨大的安全隐患,因此它绝对不能用于生产环境

路由

Flask中的路由是指用户请求的URL与视图函数之间的映射,现代Web框架使用路由技术来帮助用户记住应用程序URL,可以直接访问所需的页面,而无需从主页导航。

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

这里,URL '/hello' 规则绑定到了hello_world(),如果用户访问localhost:5000/hello,则hello_world()的输出将在浏览器中体现

另外,application对象的add_url_rule()也可将URL与函数绑定

def hello_world():
   return "Hello, World!"
app.add_url_rule('/', 'hello', hello_world)

基础语法

向规则参数添加变量,可以动态构建URL,变量记为<variable_name>

举个例子

from flask import Flask

app = Flask(__name__)

@app.route("/hello/<name>")

def hello_world(name):
    return "Hello, %s" % name

app.run()

route()的URL里加入了/<name>,并且我们将参数附加到了hello_world()函数内

看一下效果

大概来说这个<name>可以被动态替换,你输入的url是什么他就是什么

这个<name>是字符串替换,还有其他的替换类型

  • int:整数替换
  • float:浮点值替换
  • path:可接受用作目录分隔符的斜杠
from flask import Flask

app = Flask(__name__)

@app.route("/test/<int:var_a>")

def test_1(var_a):
    return "Number is: %d" % var_a

@app.route("/tset/<float:var_b>")

def test_2(var_b):
    return "Float is: %f" % var_b

app.run()

看看效果呢

1664336333074

而且float不能接受整数

1664336355467

直接not found了

另外,Flask的URL规则基于Werkzeug的路由模块,这确保形成的URL是唯一的,并且基于Apache规定的先例。

看看这个

from flask import Flask

app = Flask(__name__)

@app.route("/test_1")

def test_1():
   return "Can You See Me?"

@app.route("/test_2/")

def test_2():
   return "Can You See Me?"

app.run()

注意这个'/',在源码中第二个参数是/test_2/,这让他成为了一个规范的URL,所以访问/test_2和/test_2/都合法。但是/test_1/就不行了,因为他的参数是/test_1

另外,在url构建中,url_for()也十分有用。

url_for()的第一个参数为函数名,后续参数为多个关键字参数,每个参数对应URL的变量部分

from flask import Flask, redirect, url_for


app = Flask(__name__)


@app.route('/admin')
def Admin():
   return 'Admin Access'


@app.route('/guest/<guest>')
def Guest(guest):
   return 'Guest %s Access' % guest


@app.route('/user/<name>')
def User(name):
   if name == 'admin':
      return redirect(url_for('Admin'))
   else:
      return redirect(url_for('Guest', guest = name))


app.run()

url_for()有关的是user(),他检查了<name>是否为'admin'

若匹配成功,则使用url_for()重定位至函数Admin(),否则重定位至函数Guest(),并且将接收的参数name传递给Guest()作为他的参数

在访问http://127.0.0.1:5000/user/admin后,发现其重定位至http://127.0.0.1:5000/admin

然后其他的参数就会重定位到guest界面

1664337750076

在http中有不同的从URL检索数据的方法

  • GET: 以未加密的形式将数据发送到服务器
  • HEAD: 和GET方法相同,但没有响应体
  • POST: 用于将HTML表单数据发送到服务器,并且POST方法接收的数据不由服务器缓存
  • PUT: 用上传的内容替换目标资源的所有当前表示
  • DELETE: 删除由URL给出的目标资源的所有当前表示

在Flask中,路由一般响应GET请求,但我们可以通过route()来改变他

我们尝试更改为响应POST请求,先写一个html表单,保存为test.html

<html>
   <body>
      <form action = "http://localhost:5000/login" method = "post">
         <p> Enter Name: </p>
         <p> <input type = "text" name = "username" /> </p>
         <p> <input type = "submit" value = "submit" /> </p>
      </form>
   </body>
</html>

然后写一下Flask

from flask import Flask, redirect, url_for, request, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template("test.html")

@app.route('/success/<name>')
def success(name):
    return 'welcome, %s' % name

@app.route('/login', methods = ['POST', 'GET'])
def login():
   if request.method == 'POST':
      print("Method is POST")
      user = request.form['username']
      return redirect(url_for('success', name = user))
   else:
      print("Method is GET")
      user = request.args.get('username')
      return redirect(url_for('success', name = user))


app.run()

render_template()可以渲染一个静态的html文件,并且实现参数的传递。他会自动在templates文件夹中找到对应的html,因此我们不需要给出html的完整路径。

我们打开test.html,并且随便写点东西进去

表单数据将POST到表单标签的action子句中的URL

/login映射到login(),通过user = request.form['username']来获取POST方法传递的数据,此处获得了参数username的值

他将作为变量传递给success(),并转到相应的URL,打印相应的文字。

同时,我们可以看到

测试语句的输出表明确实是POST方法而非GET方法

若我们将html中的方法改为GET,则会通过user = request.args.get('username')来获取数据。args和其他语言差不多,是包含表单参数对及其对应值对的列表的字典对象

和数据库有关的操作

数据库选用SQLite,直接来一个实例吧。实例目标是创建一个学生表

先创建一个SQLite数据库database.db

import sqlite3

conn = sqlite3.connect('database.db')

conn.execute('CREATE TABLE students (name TEXT, addr TEXT, city TEXT, pin TEXT)')

conn.close()

第一个函数new_student()

@app.route('/new_student')
def new_student():
    return render_template('student.html')

对应的student.html如下

<html>
   <body>
      <form action = "{{ url_for('addrec') }}" method = "POST">

         <h3> Student Information </h3>

         Name <br>
         <input type = "text" name = "name" /> </br>

         Address <br>
         <textarea name = "add" > </textarea> <br>

         City <br>
         <input type = "text" name = "city" /> <br>

         PINCODE <br>
         <input type = "text" name = "pin" /> <br>

         <input type = "submit" value = "submit" /> <br>

      </form>
   </body>
</html>

第二个函数add()函数通过POST检索表单数据,插入到学生表中,操作的成功以及失败信息均显示在result.html中

@app.route('/add', methods=['POST', 'GET'])
def add():
    if request.method == 'POST':
        try:
            name = request.form['name']
            addr = request.form['add']
            city = request.form['city']
            pin = request.form['pin']

            with sql.connect("database.db") as con:
                cur = con.cursor()
                cur.execute("INSERT INTO students (name, addr, city, pin) VALUES(?, ?, ?, ?)", (name, addr, city, pin))

                con.commit()
                msg = "Successfully Recorded"
        except:
            con.rollback()
            msg = "Error While Inserting"

        finally:
            return render_template("result.html", msg = msg)
            con.close()

result.html中仅包含一个转义语句,用来显示操作结果

<html>
   <body>
   
      result of addition : {{ msg }}
      <h2> <a href = "\"> go back to home page </a> </h2>
      
   </body>
</html>

第三个函数list()将填充的对象传递给list.html

@app.route('/list')
def list():
    con = sql.connect("database.db")
    con.row_factory = sql.Row

    cur = con.cursor()
    cur.execute("select * from students")

    rows = cur.fetchall()
    return render_template("list.html", rows = rows)

list.html比较模板,遍历并打印数据

<html>
   <body>
   
      <table border = 1>
         
         <thead>
            <td> Name </td>
            <td> Address </td>
            <td> city </td>
            <td> Pincode </td>
         </thead>
         
         {% for row in rows %}
            
            <tr>
               <td> {{row["name"]}} </td>
               <td> {{row["addr"]}} </td>
               <td> {{ row["city"]}} </td>
               <td> {{row['pin']}} </td>	
            </tr>

         {% endfor %}
      
      </table>
      
      <a href = "/"> Go back to home page </a>
   </body>
</html>

最后也是最初的函数home(),呈现home.html作为入口点

@app.route('/')
def home():
    return render_template('home.html')

home.html比较简单

<html>
<body>
    <a href = "/new_student"> Add New Record </a>
    <br/>
    <a href = "/list"> Show List </a>
</body>
</html>

运行源码,访问http://localhost:5000/,就能玩一下这个简单的学生表操作了

posted @ 2022-09-28 11:32  iPlayForSG  阅读(229)  评论(0编辑  收藏  举报