使用python从零开始搭建web项目
这次的开发可以说是从零开始的:需求分析——架构设计——数据库设计——api设计——可交互原型的开发——扩展功能进行开发(其中也包括对前面设计的不合理的修改)。左上角新建数据库连接,选择duckdb,选择你要连接的文件的路径,这样就可以了,不需要navicat一样输入用户名密码之类的。此外,要注意的是,当需要启动后端项目的时候,需要在dbeaver上先断开连接,否则后端项目启动不了,因为文件占用冲突
一、学习记录:
因为要使用python来搭建web项目,根据搜集的资料,最终选择使用gradio + fastapi + duckdb来进行搭建。因为有javaweb的学习经验,所以这次选择直接边结合ai完成代码,边进行相关框架的学习。这次的开发可以说是从零开始的:需求分析——架构设计——数据库设计——api设计——可交互原型的开发——扩展功能进行开发(其中也包括对前面设计的不合理的修改)。
gradio的框架比较简单,好上手一些,可以在b站找个视频,跟着一起敲一敲。
fastapi的学习,可以参考fastapi的文档,但由于原文是英文,阅读理解起来还是有点困难,所以我选择了使用 fastapi菜鸟教程 来进行学习,把其中的内容通读一遍,其中的代码看不懂可以交给ai来解释。
duckdb duckdb官网 是一个开源、高性能的嵌入式列式数据库,不需要独立的服务进程,像 SQLite 一样可以被嵌入进任何应用程序。
下面会先介绍下gradio,然后是对于fastapi的介绍、核心概念等内容,最后会介绍下duckdb数据库。
二、gradio框架简要介绍
我在项目中使用的比较简单:定义需要的函数——使用Blocks类自定义界面(包括组件、监听器绑定)——launch()——启动前端项目
import gradio as gr
def greet(name):
return "Hello " + name + "!"
with gr.Blocks() as demo:
name = gr.Textbox(label="Name")
output = gr.Textbox(label="Output Box")
greet_btn = gr.Button("Greet")
# 事件监听器
greet_btn.click(fn=greet, inputs=name, outputs=output, api_name="greet")
# 启动配置
if __name__ == "__main__":
demo.launch(
server_name="127.0.0.1",
server_port=7860,
share=False,
show_error=True,
inbrowser=True
)
三、fastapi框架简要介绍
FastAPI是一个现代、快速(高性能)的python web框架,基于标准的python类型提示,使用python3.6+构建的web框架。
特点:高性能,基于Starlette 和 Pydantic;Starlette 用于路由匹配,Pydantic 用于数据验证。框架易于使用,文档易于阅读。
安装:pip install fastapi以及 pip install uvicorn
四、fastapi核心概念:pydantic、ASGI、starlette、schema
1、pydantic: Pydantic 是一个基于 Python 类型提示的数据验证和设置管理库。它利用 Python 的类型注解来提供数据的验证、序列化和文档生成。
作用:(1)请求体验证
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class ItemCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
price: float = Field(..., gt=0, description="价格必须大于0")
description: Optional[str] = None
tags: List[str] = []
@app.post("/items/")
async def create_item(item: ItemCreate):
"""
FastAPI 自动完成:
1. 验证请求体JSON是否符合ItemCreate模型
2. 自动转换类型(如字符串数字转float)
3. 如果验证失败,返回422错误详情
"""
# 这里直接使用验证后的item对象
return {
"message": "Item created",
"item": item.dict(), # 已经验证过的数据
"item_name": item.name # 直接访问属性,类型安全
}
(2)查询参数验证
from fastapi import FastAPI, Query
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None
@app.get("/items/")
def read_item(item: Item, q: str = Query(..., max_length=10)):
return {"item": item, "q": q}
(3)响应数据序列化:
class UserResponse(BaseModel):
id: int
username: str
email: str
created_at: datetime
# 配置选项
class Config:
# 将datetime自动转换为ISO格式字符串
json_encoders = {
datetime: lambda v: v.isoformat()
}
@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
# 从数据库获取原始数据
raw_user_data = {
"id": user_id,
"username": "john_doe",
"email": "john@example.com",
"created_at": datetime.now(),
"password_hash": "secret", # 敏感信息
"internal_id": 12345 # 内部字段
}
# 自动过滤为UserResponse模型定义的字段
return raw_user_data
# 实际返回: {"id":1,"username":"john_doe","email":"john@example.com","created_at":"2024-01-01T12:00:00"}
(4)模型继承、复杂嵌套模型
(5)自动生成OpenAPI文档
class Item(BaseModel):
name: str = Field(..., example="手机")
price: float = Field(..., example=2999.99, description="商品价格")
category: str = Field(..., example="电子产品")
class Config:
schema_extra = {
"example": {
"name": "笔记本电脑",
"price": 5999.99,
"category": "电子产品"
}
}
@app.post("/items/")
async def create_item(item: Item):
return item
2、ASGI: 是 Python 异步 Web 服务器和应用程序之间的标准接口。
# WSGI 应用(同步)- 传统 Flask 风格
def wsgi_app(environ, start_response):
status = '200 OK'
response_headers = [('Content-type', 'text/plain')]
start_response(status, response_headers)
return [b'Hello World']
# ASGI 应用(异步)- FastAPI 风格
async def asgi_app(scope, receive, send):
await send({
'type': 'http.response.start',
'status': 200,
'headers': [(b'content-type', b'text/plain')],
})
await send({
'type': 'http.response.body',
'body': b'Hello World',
})
# 实际中的应用
# WSGI应用(Flask风格)
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello World' # Flask帮你处理了所有WSGI细节
#ASGI应用(FastAPI风格)
from fastapi import FastAPI
app = FastAPI()
@app.get("/weather")
async def get_weather():
async with httpx.AsyncClient() as client:
response = await client.get("https://api.weather.com/data")
return response.json()
3、Starlette: Starlette 是一个轻量级的 ASGI 框架/工具包,用于构建高性能的异步 Python Web 服务。
from starlette.applications import Starlette
from starlette.responses import JSONResponse
# Starlette 帮你处理了 ASGI 底层细节
app = Starlette()
@app.route("/")
async def homepage(request): # 更友好的接口
return JSONResponse({"message": "Hello World"})
核心组件:(1)请求响应对象
from starlette.requests import Request
from starlette.responses import JSONResponse, HTMLResponse
async def hello(request: Request):
# 访问请求信息
client_ip = request.client.host
user_agent = request.headers.get("user-agent")
return JSONResponse({
"message": "Hello",
"client_ip": client_ip,
"user_agent": user_agent
})
(2)中间件:
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware
middleware = [
Middleware(CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"])
]
app = Starlette(middleware=middleware)
(3)路由系统
from starlette.routing import Route, Router
# 方式1:装饰器
@app.route("/users")
async def list_users(request):
return JSONResponse({"users": []})
# 方式2:显式路由
async def user_detail(request):
user_id = request.path_params["user_id"]
return JSONResponse({"user_id": user_id})
routes = [
Route("/", homepage),
Route("/users/{user_id:int}", user_detail)
]
app = Starlette(routes=routes)
4、schema: Schema 指的是数据结构的定义和描述,它规定了数据的形状、类型、约束条件和关系。在 FastAPI 中,Schema 主要通过Pydantic模型来定义。Pydantic 模型自动生成 JSON Schema。
作用包括:数据合约:定义API输入输出的数据结构;验证规则:指定数据的类型、格式和约束;文档来源:自动生成交互式API文档;转换规范:处理数据的序列化和反序列化;开发工具:提供IDE支持和类型安全。
输入:原始JSON → Schema验证转换 → 类型正确的Python对象
输出:Python对象 → Schema序列化过滤 → 干净的JSON响应
from pydantic import BaseModel, validator, Field
from typing import Optional, List
from enum import Enum
# 这就是一个schema
class UserRole(str, Enum):
ADMIN = "admin"
USER = "user"
MODERATOR = "moderator"
# 这也是一个schema
class UserCreate(BaseModel):
username: str = Field(..., min_length=3, max_length=50, description="用户名")
email: str = Field(..., regex=r'^[\w\.-]+@[\w\.-]+\.\w+$', description="邮箱地址")
password: str = Field(..., min_length=8, description="密码")
full_name: Optional[str] = Field(None, max_length=100, description="全名")
role: UserRole = Field(UserRole.USER, description="用户角色")
age: Optional[int] = Field(None, ge=0, le=150, description="年龄")
# 数据验证
@validator('username')
def username_must_be_alphanumeric(cls, v):
if not v.isalnum():
raise ValueError('用户名只能包含字母和数字')
return v
@validator('password')
def password_strength(cls, v):
if not any(c.isupper() for c in v):
raise ValueError('密码必须包含至少一个大写字母')
if not any(c.islower() for c in v):
raise ValueError('密码必须包含至少一个小写字母')
if not any(c.isdigit() for c in v):
raise ValueError('密码必须包含至少一个数字')
return v
class Config:
# 生成 JSON Schema 示例
schema_extra = {
"example": {
"username": "johndoe",
"email": "john@example.com",
"password": "SecurePass123",
"full_name": "John Doe",
"role": "user",
"age": 30
}
}
# 使用自定义验证器
@app.post("/users", response_model=UserResponse)
async def create_user(user: UserCreate):
"""创建新用户,包含数据验证"""
# Pydantic 自动验证输入数据
return await create_new_user(user)
5、依赖注入、类型提示 :见文档相关介绍
五、duckdb数据库:
1、介绍: duckdb是一个开源、高性能的嵌入式(不需要独立的服务进程)列式数据库,像 SQLite 一样可以被嵌入进任何应用程序。
2、适合的场景: 数据分析;数据科学(与python、R集成进行数据预处理);嵌入式应用(桌面应用、移动应用的本地数据处理)。
3、与MySQL对比:
| DuckDB | MySQL |
|---|---|
| 嵌入式数据库 | 客户端——服务器数据库 |
| 列式存储 | 行式存储 |
| 主要用于OLAP(分析型) | 主要用于OLTP(事务型) |
| 适合中小数据集 | 适合大型企业级 |
| 单写多读 | 高并发读写 |
4、使用的步骤:
(1)在命令行运行 pip install duckdb 安装duckdb,可以使用清华源https://pypi.tuna.tsinghua.edu.cn/simple。
(2)在项目代码中引入duckdb,并连接数据库
# 无需启动服务,直接连接文件
import duckdb
# 连接数据库(文件不存在会自动创建)
conn = duckdb.connect('my_database.db')
# 查询数据
result = conn.execute("SELECT * FROM users").fetchall()
(3)可以安装dbeaver软件 dbeaver官网
来进行duckdb数据库的数据的可视化,这个软件的作用和我们使用MySQL时navicat的作用一样。
左上角新建数据库连接,选择duckdb,选择你要连接的文件的路径,这样就可以了,不需要navicat一样输入用户名密码之类的。
此外,要注意的是,当需要启动后端项目的时候,需要在dbeaver上先断开连接,否则后端项目启动不了,因为文件占用冲突。

这里再浅浅说下MySQL数据库启用的步骤:保证MySQL服务启动;在idea中输入用户名密码等连接数据库。
5、与MySQL语法对比差异:
| MySQL | DuckDB |
|---|---|
| 自增:AUTO_INCREMENT | 自增:创建序列并建表时使用序列作为默认值 |
| comment注释 | 不支持列注释 |
| 显示创建索引 | 自动创建 |
| 支持外键约束 | 不支持外键约束 |
| 丰富的数据类型 | 简化的数据类型 |
| varchar(25) | varchar |
例:在DuckDB自增操作:
-- 先创建序列
CREATE SEQUENCE IF NOT EXISTS transaction_id_seq START 1;
-- 创建表,使用序列作为默认值
CREATE TABLE IF NOT EXISTS accounts (
id INTEGER PRIMARY KEY DEFAULT nextval('transaction_id_seq'),
);
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)