python 学习笔记(6)—— Flask 、MySql

news2024/11/25 14:32:38

目录

Flask

1、起步

2、渲染项目的首页

3、处理无参数的 GET 请求

4、处理有 query 参数的 GET 请求

6、处理 params 参数的 get 请求 

6、处理 application/json 类型请求体的 POST 请求

7、根据参数渲染模板页面

 8、上传文件

数据库操作(mysql)


Flask

1、起步

        先创建一个项目的文件夹,然后在该文件夹下初始化一个虚拟环境。虚拟环境建设好后,文件夹下将有一个 venv 的目录。

# python 3版本 创建虚拟环境:
py -3 -m venv venv

# 激活虚拟环境
venv\Scripts\activate

# 安装 flask
pip install flask

        依次创建 flaskr、flaskr/static、flaskr/templates、tests目录:

        flaskr目录:包含应用代码和文件的 Python 包;

                /static:存放静态文件,如图片等;

                /templates:可以用来存放 html 文件,用于服务端渲染;

        test 目录:用来存放测试类型的文件;

2、渲染项目的首页

from flask import Flask
from flask import render_template
from flask_cors import CORS

# 创建该类的实例
app = Flask(__name__)
CORS(app, resources={r'/*': {'origins' :'*'}})      # 同源策略解决方法


# 使用装饰器设定匹配的URL,如果命中,则执行下面的函数;默认是 get 请求
@app.route('/')
def default_page():
    # 返回指定的页面,是项目下 templates 下的文件
    return render_template('index.html')

if __name__ == '__main__':
    # 运行该服务,监听的端口为 9090,host=‘0.0.0.0’表示接受公开访问
    app.run(port=9090, host='0.0.0.0')
# templates/index.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        h1{ color: brown; }
    </style>
</head>
<body>
    <h1>Hello, welcome to the first page.</h1>
</body>
</html>

3、处理无参数的 GET 请求

         改造 index.html 文件,让请求和结果展示在当前界面完成:

# templates/index.js

<body>
    <h1>Hello, welcome to the first page.</h1>
    <ul>
        <li>
            <button onclick="get_request('get_datetime', '.datetime')">click to get datetime</button>
            <p class="datetime"></p>
        </li>
    </ul>
<script>
    function get_request(path, renderElement, query='', callback){
        const xhr = new XMLHttpRequest()

        xhr.open('GET', `http://192.168.145.135:9090/${path}${query ?  `?${query}` : ''}`)

        xhr.onreadystatechange = () => {
            if(xhr.readyState === 4 && xhr.status){
                document.querySelector(renderElement).innerText = xhr.response
                callback ? callback(xhr.response) : ''
            }
        }

        xhr.send()
    }
</script>
</body>
# 规定匹配的路径为 /get_time 或 /get_time?
@app.route('/get_datetime')
def get_datetime():
    return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

4、处理有 query 参数的 GET 请求

        /templates/index.html 中新增的内容: 

        <li>
            <input class="name" type="text" placeholder="please input you name">
            <select class="gender" name="" id="">
                <option value="man">man</option>
                <option value="woman">woman</option>
            </select>
            <button onclick="request_args()">click to get datetime</button>
            <p class="name-gender"></p>
        </li>

<script>
    function request_args(){
        let name = document.querySelector('.name').value
        let gender = document.querySelector('.gender').value
        get_request('get_with_args', '.name-gender', `name=${name}&gender=${gender}`)
    }
</script>
from flask import Flask,request

@app.route('/get_with_args')
def get_with_args():
    args = request.args

    # 各参数可以从 request 实例上去获取
    # print(args['name'], args['gender'])

    name = args['name']
    gender = args['gender']
    return f'你好,帅气的{name}先生' if gender == 'man' else f'你好,美丽的{name}小姐'

        关于 request 更多内容可以参考: https://flask.net.cn/api.html#incoming-request-data

6、处理 params 参数的 GET 请求 

         html 文件新增的测试内容:

        <li>
            <input class="nickname" type="text" placeholder="input nickname">
            <input class="age" type="number" placeholder="input age">
            <button onclick="sendParams()">click to send params</button>
            <p class="nickname-and-age"></p>
        </li>

<script>
    const sendParams = () => {
        let nickname = document.querySelector('.nickname').value
        let age = document.querySelector('.age').value
        get_request(`test-params/${nickname}/${age}`, '.nickname-and-age', '', (resdata)=>{
            let strong = document.createElement('strong')
            let obj = JSON.parse(resdata)
            strong.innerText = `response data: nickname: ${obj.nickname}; age: ${obj.age}`
            document.querySelector('.nickname-and-age').append(strong)
        })
    }
</script>    
# 两个 params 参数都必须传, 预定义 nickname 参数为字符串,age 为整型
@app.route('/test-params/<string:nickname>/<int:age>')
def test_params(nickname, age):
    return {'nickname':nickname,'age':age}

6、处理 application/json 类型请求体的 POST 请求

        index.html 文件中新增的内容: 

        <li>
            <input class="username" type="text">
            <input class="passwd" type="password">
            <button class="post-btn">click to post</button>
            <p class="post-res"></p>
        </li>

<script>
    document.querySelector('.post-btn').addEventListener('click',()=>{
        fetch('http://localhost:9090/test-post',{
            method:'post',
            body:JSON.stringify({
                username:document.querySelector('.username').value,
                passwd:document.querySelector('.passwd').value
            }),
            headers:{
                'Content-Type':'application/json',
                'auth':'abcdefg---6789'
            }
        }).then(res => res.text()).then(data=>{
            document.querySelector('.post-res').innerText = data
        })
    })
</script>
@app.route('/test-post', methods=['post'])
def test_post():
    str = (request.data).decode()
    print(str)
    obj = json.loads(str)
    print(obj['username'])

    print(request.json['username'])
    
    # print(request.get_data())           # 与 request.data 一致,是字符串类型
    # print(request.json)                 # 是dict类型
    return 'ok'

7、根据参数渲染模板页面

        index.js 中添加的内容: 

        <li>
            <input type="text" placeholder="your address" class="_address">
            <input type="text" placeholder="your name" class="_name">
            <button class="to-new-page">click to new page with data</button>
        </li>

<script>
    document.querySelector('.to-new-page').addEventListener('click', ()=>{
        address = document.querySelector('._address').value
        name = document.querySelector('._name').value

        # 在新的窗口中访问
        window.open(`http://localhost:9090/new-page?address=${address}&name=${name}`)
    })
</script>

        新创建两个 html: 

# new-page.html   当有 name 时返回的页面,可以没有address

<body>
       {% if address %}
           <h1>Hi {{name}}, we know your address is {{address}}.</h1>
       {% else %}
           <h1>Hello {{name}}!</h1>
       {% endif %}
       <img src="https://tse3-mm.cn.bing.net/th/id/OIP-C.bVb769JBdzVZYuksxZ2Y-AHaEo?pid=ImgDet&rs=1" alt="">
</body>
# 404.html

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>404</title>
    <style>
        body,html{
            margin: 0;
            padding: 0;
        }
        .outer{
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .num{
            width: 100px;
            height: 100px;
            font-size: 5rem;
            font-weight: 900;
            text-shadow: 3px 3px 3px #aaa;
        }
        .num:nth-child(2n){ color: brown; }
        .num:nth-child(2n + 1){ color: chocolate; }
        .num:nth-child(4){ width: auto; }
    </style>
</head>
<body>
    <div class="outer">
        <div class="num">4</div>
        <div class="num">0</div>
        <div class="num">4</div>
        <div class="num">no found</div>
    </div>
</body>
# 可以直接访问
@app.route('/new-page')
def new_page():
    # 设置 address 和 name 都不是必传参数
    address = request.args['address'] if request.args else ''
    name = request.args['name'] if request.args else ''
    if name:                    # 往模板页面传递两个参数
        return render_template('another.html', address=address, name=name)
    else:
        # 如果没有名字,则返回 404 的页面
        return render_template('404.html')

只有 name 时
只有 name 时

name 和 address 都没有时

name 和 address 都具备时

 8、上传文件

        index.html 中新增的内容: 

        <li>
            <input type="file" accept=".jpg,.png,.gif" id="file">
            <button class="upload-file" onclick="uploadFile()">upload file</button>
            <p class="upload-file-res"></p>
        </li>

<script>
    function uploadFile(){
        let files = document.querySelector('#file').files

        const formdata = new FormData()
        formdata.append('file', files[0])
        formdata.append('time', new Date().getTime())

        fetch('http://localhost:9090/upload-file',{
            method:'post',
            body:formdata
        }).then(res=>res.text()).then(data=>{
            console.log(data)
        })
    }
</script>
@app.route('/upload-file', methods=['post'])
def upload_file():
    if 'file' not in request.files:
        return 'upload fail'

    file = request.files['file']

    if file.filename == '':
        return 'filename no found'

    file.save(f'./{file.filename}')        # 保存图片到本地

    return 'ok'

关于 flask 文件上传的更安全的处理:上传文件_Flask中文网

数据库操作(mysql)

        安装 pymysql:

pip install pymysql
import pymysql

# 连接指定数据库
conn = pymysql.connect(host='localhost', user='root',
                       password='abcdef',database='python_study',
                       charset='utf8')

# 定义一个游标对象,靠游标对象来执行sql 以及获取 结果
#cursor = conn.cursor()          # 默认是元组形式的结果

# 将游标对象定义为 字典 类型,进而更方便地获取数据
from pymysql.cursors import DictCursor
cursor = conn.cursor(DictCursor)            # 创建游标,定义返回的数据类型是字典

        查询语句的执行和结果获取:

# 创建并执行 执行sql语句
sql = 'select * from student'
cursor.execute(sql)

# 获取执行的结果集 所有数据
res = cursor.fetchall()
print(res)

# res = cursor.fetchmany(3)                   # 获取前三条结果

        关于更新类的操作(增、删、改):

# 更新一条数据
sql = "update student set age = 9 where num = '1000'"
cursor.execute(sql)
conn.commit()                       # 显式提交更新操作



# 新增一条数据,注意格式化的sql语句,如果有引号的要加上引号
name = '许九'
age = 10
gender = '男'
num = '1006'
sql = f"insert into student values ('{name}','{num}','{gender}',{age});"
cursor.execute(sql)
conn.commit()

        最后需要关闭连接:

# 关闭连接
conn.close()

        如果 连接的时候报错:RuntimeError: 'cryptography' package is required for sha256_password or caching_sha2_password auth methods

        该错误指出需要 'cryptography' 包来处理 'sha256_password' 或 'caching_sha2_password' 的认证方式。

        这可能是因为 Python 环境中缺少了 'cryptography' 包。这个包是一个 Python 的加密库,它提供了许多加密算法的实现,包括 'sha256_password' 和 'caching_sha2_password' 这两种 MySQL 的密码加密方式。

        直接安装这个包然后再运行程序即可:

pip install cryptography

        

 参考:

[1] flask获取post请求参数_flask post参数_阿常呓语的博客-CSDN博客

[2] 快速上手_Flask中文网 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1005479.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Jenkins结合gitlab自动化持续集成

最近在公司有负责搭建自动化测试环境&#xff0c;自动化脚本写好后&#xff0c;毋庸置疑是需要将自动化脚本进行持续集成测试&#xff0c;能够根据企业的定制化需求&#xff0c;通过Jenkins触发执行构建任务&#xff0c;定时执行自动化脚本等&#xff0c;今天就给大家介绍一下J…

可视化大屏设计模板 | 主题皮肤(报表UI设计)

下载使用可视化大屏设计模板&#xff0c;减少重复性操作&#xff0c;提高报表制作效率的同时也确保了报表风格一致&#xff0c;凸显关键数据信息。 软件&#xff1a;奥威BI系统&#xff0c;又称奥威BI数据可视化工具 所属功能板块&#xff1a;主题皮肤上传下载&#xff08;数…

【实践篇】redis管道pipeline使用详解

文章目录 0. 前言什么场景下使用redis管道特性 1.原理1.1 redis管道特性的处理机制 使用redis管道优化示例3. springboot使用redis管道示例4. 参考资料5. 源码地址6. Redis从入门到精通系列文章 0. 前言 Redis管道&#xff08;Pipeline&#xff09;是一种批量执行Redis命令的机…

Revit SDK 介绍:TypeRegeneration 修改类型,更新文档 ValidateParameters 参数合法性验证

前言 这篇文章介绍两个例子&#xff0c;逻辑比较简单&#xff1a; TypeRegeneration 修改类型&#xff0c;更新文档ValidateParameters 参数合法性验证 内容 TypeRegeneration FamilyType 不是继承自 Element 的&#xff0c;而是独立于 Element 体系之外&#xff0c;直接从…

window.structuredClone()

先看下兼容性 1. 创建一个要克隆的对象。例如&#xff1a; const originalObj {name: John,age: 25,address: {city: New York,country: USA} };2. 调用structuredClone()方法克隆对象。例如&#xff1a; const clonedObj window.structuredClone(originalObj);3. clonedObj将…

软件安全研究(四)

文章目录 Fine-Grained Code Clone Detection with Block-Based Splitting of Abstract Syntax Tree文章结构IntroMotivationDefinitionSystemOverviewProcessingVerify Experimentexperimental settingsRQ1RQ2RQ3RQ4RQ5 Fine-Grained Code Clone Detection with Block-Based S…

MeterSphere压测,出现HttpHostConnectException

现象&#xff1a;MeterSphere更换压力机后&#xff0c;压测出现出现HttpHostConnectException 解决方案&#xff1a; net.ipv4.tcp_tw_reuse默认是0或者2&#xff0c;更改为1 net.ipv4.tcp_tw_reuse&#xff0c;表示是否允许重新应用处于TIME-WAIT状态的socket用于新的TCP连…

轻量级软件FastGithub实现稳定访问github

当我们想访问全球最大的“同性交友网站”https://github.com/ 时&#xff0c;总会出现无法访问的界面&#xff0c;令人非常苦恼&#xff1a;幸运的是&#xff0c;有一种轻量级的软件可以帮助我们稳定地访问GitHub&#xff0c;那就是FastGithub。 什么是FastGithub&#xff1f…

数据结构和算法(5):二叉树

树 向量允许通过下标或秩&#xff0c;在常数的时间内找到目标对象&#xff1b;然而&#xff0c;一旦需要对这类结构进行修改&#xff0c;那么无论是插入还是删除&#xff0c;都需要耗费线性的时间。 列表允许借助引用或位置对象&#xff0c;在常数的时间内插入或删除元素&…

去除pdf/word的水印艺术字

对于pdf中的水印如果无法去除水印&#xff0c;则先另存为word&#xff0c;然后再按下面办法处理即可&#xff1a; 查看宏&#xff0c;创建&#xff1a;删除艺术字 添加内容&#xff1a; Sub 删除艺术字()Dim sh As ShapeFor Each sh In ActiveDocument.ShapesIf sh.Type msoT…

用ASE制作地表积水效果

unity引擎制作实时刷下雨地面效果 大家好&#xff0c;我是阿赵。   之前在Unity引擎做了几种不同的效果&#xff0c;比如视差偏移、下雨效果、顶点颜色工具等。这一篇文章&#xff0c;将会把这几个效果合并在一起&#xff0c;做出一个混合积水地表的效果。这个几个shader的基…

基于elelemt-ui封装一个表单

子组件 searchForm <template><el-formref"form":model"value":rules"rules":label-width"labelWidth":inline"inline"><el-form-itemv-for"field in fields":key"field.slot":label&q…

JMeter基础 —— 使用Badboy录制JMeter脚本!

1、使用Badboy录制JMeter脚本 打开Badboy工具开始进行脚本录制&#xff1a; &#xff08;1&#xff09;当我们打开Badboy工具时&#xff0c;默认就进入录制状态。 如下图&#xff1a; 当然我们也可以点击录制按钮进行切换。 &#xff08;2&#xff09;在地址栏中输入被测地…

excel单元格多行文本的excel 提取 公式

excel单元格多行文本的excel 提取 公式 第一行&#xff1a; TRIM(MID(SUBSTITUTE(A$1,CHAR(10),REPT(" ",160)),ROW(A1)*160-159,160)) 第9行&#xff1a; TRIM(MID(SUBSTITUTE(A$1,CHAR(10),REPT(" ",160)),ROW(A9)*160-159,160)) Excel如何提取某一单元…

GRU实现时间序列预测(PyTorch版)

&#x1f4a5;项目专栏&#xff1a;【深度学习时间序列预测案例】零基础入门经典深度学习时间序列预测项目实战&#xff08;附代码数据集原理介绍&#xff09; 文章目录 前言一、基于PyTorch搭建GRU模型实现风速时间序列预测二、时序数据集的制作三、数据归一化四、数据集加载器…

Multi Query Attention Group Query Attention

Multi Query Attention(MQA)在2019年就被提出来了&#xff0c;用于推理加速&#xff0c;但在当时并没有受到很多关注&#xff0c;毕竟一张2080就能跑Bert-base了。随着LLM的大火&#xff0c;MQA所带来的收益得以放大。 思路 Multi Query Attention(MQA)跟Multi Head Attention…

win10 自带虚拟机软件 虚拟CentOS系统

win10 下使用需要虚拟一个系统&#xff0c;不需要额外安装VMware、Virtual box等软件。使用win10 自带虚拟机软件即可 步骤1 确保启动Hyper-V 功能启用 控制面板 -> 程序 -> 启用或关闭Windows功能 步骤 2 创建虚拟机 2.1 打开Typer-V 2.2 创建虚拟机 2.2.1 操作 -&g…

什么是数据湖?数据湖的概念及发展历程

随着云计算、社交媒体、物联网、短视频等新一代互联网技术的快速发展&#xff0c;数据的数量和复杂性不断增加。许多企业和组织已经积累了大量的各种类型的数据&#xff0c;对于如何存储和管理这些海量数据&#xff0c;以及如何高效地分析和利用这些数据&#xff0c;是每个组织…

数字IC设计笔试面试经典题(1-10)

1 基础知识 1.1 锁存器的结构 锁存器即Latch &#xff0c;数电中称之为电平触发的D触发器&#xff0c;也是D型锁存器&#xff0c;有电平触发器SR触发器改进得到&#xff0c;其工作特点是电平是有效电平&#xff08;高电平或者低电平&#xff09;期间&#xff0c;才接受信号并…

Vue中实现全景房看图3D

示例代码 安装photo-sphere-viewer yarn add -D photo-sphere-viewer 组件引入插件 import { Viewer } from photo-sphere-viewer; import photo-sphere-viewer/dist/photo-sphere-viewer.css; // 引入样式 import MarkersPlugin from photo-sphere-viewer/dist/plugins/marker…