想象一下,你正在开发一个超酷的Web应用,比如一个博客平台或者一个在线商店。你的API不仅要能把数据(比如文章列表、商品信息)展示给用户,更要聪明到能理解用户的各种“小心思”:用户可能想看最新的文章、搜索特定关键词的商品、或者只想看当前页面的10条数据等等。

这篇文章就是要带你解锁FastAPI中使用SQLModel来实现这些高级查询功能的秘籍,主要关注两大神技:查询参数(Query Parameters)数据库联接(Joins)

1. 查询参数:让你的API听懂用户的“指令”

什么是查询参数?简单说,它就像是你给API发出的“指令”,通过URL告诉服务器你想要什么样的数据。

举个例子:

  • 你想看第2页的文章,每页显示5篇:http://localhost:8000/posts?skip=5&limit=5
  • 你想搜索标题包含“夏天”的文章:http://localhost:8000/posts?search=夏天

这里的 ?skip=5&limit=5?search=夏天 就是查询参数。它们以问号 (?) 开头,用 key=value 的形式表示,多个参数之间用与号 (&) 连接。

查询参数能干啥?

  1. 过滤 (Filtering):就像筛子一样,根据特定条件筛选数据。例如,只看某个作者的文章。
  2. 排序 (Sorting):按发布时间、价格等给结果排序(虽然本文不细讲,但原理类似)。
  3. 分页 (Pagination):当数据太多时,一页一页地看。limit(每页几条)和 skip(跳过几条,即 (页码-1) * 每页条数)是分页的黄金搭档。

FastAPI + SQLModel 如何实现查询参数?

在FastAPI中,这简直太简单了!你只需要在你的API接口函数(路径操作函数)里定义参数,并给它们加上类型提示。FastAPI会自动把URL中的查询参数“抓”出来,并转换成你想要的类型。

# --- main.py (或者你的API路由文件,比如 posts_router.py) ---
from typing import Optional, List
from fastapi import APIRouter, Depends
from sqlmodel import Session, select, func # 导入SQLModel的核心组件
from .. import schemas, models, database, oauth2 # 假设你的项目结构router = APIRouter(prefix="/posts", # 给这个路由下的所有路径加上 /posts 前缀tags=["Posts"]   # 在API文档中分组显示
)# 假设你的 database.py 里面有 get_db 函数来获取数据库会话
# from .database import get_db@router.get("/", response_model=List[schemas.PostOut]) # 注意这里的 response_model
async def get_all_posts(db: Session = Depends(database.get_db), # 依赖注入,获取数据库会话limit: int = 10,  # 默认每页10条skip: int = 0,    # 默认从第0条开始(跳过0条)search: Optional[str] = None # 可选的搜索词,默认为None# current_user: models.User = Depends(oauth2.get_current_user) # 如果需要登录认证
):"""获取所有帖子,支持分页和搜索,并统计每个帖子的点赞数。"""# 基础查询语句,选择帖子模型和统计投票数statement = (select(models.Post, # 我们要查询帖子本身func.count(models.Vote.post_id).label("votes") # 还要统计每个帖子的投票数,并命名为 "votes")# 关键:使用 .join() 来连接 Post 表和 Vote 表# isouter=True 表示使用 LEFT OUTER JOIN,这样即使帖子没有投票,也会被查询出来,投票数为0.join(models.Vote, models.Vote.post_id == models.Post.id, isouter=True)# 按帖子ID分组,这样 func.count 才能正确统计每个帖子的投票.group_by(models.Post.id))# 如果用户提供了搜索词,就在查询语句中加入过滤条件if search:# models.Post.title.contains(search) 表示标题包含搜索词即可# 对于大小写不敏感的搜索,可以使用 .ilike(f"%{search}%"),但要注意数据库是否支持statement = statement.where(models.Post.title.contains(search))# 应用分页参数statement = statement.limit(limit).offset(skip)# 执行查询# db.exec(statement).all() 会返回一个结果列表,# 列表中的每个元素是一个元组 (Post对象, votes数量)results = db.exec(statement).all()# FastAPI 会根据 response_model=List[schemas.PostOut] 自动处理这个 results# schemas.PostOut 需要被定义成能接收 Post 对象和 votes 数量的结构return results

代码讲解:

  1. @router.get("/", response_model=List[schemas.PostOut])
    • 定义了一个GET请求的接口,路径是 /posts/ (因为router有prefix="/posts")。
    • response_model=List[schemas.PostOut] 告诉FastAPI,这个接口返回的数据会是一个列表,列表里每个元素的结构都符合 schemas.PostOut 这个我们接下来要定义的“响应模型”。
  2. async def get_all_posts(...)
    • db: Session = Depends(database.get_db): FastAPI的依赖注入。get_db函数(通常在database.py中定义)会提供一个数据库会话 db,让我们能和数据库打交道。
    • limit: int = 10, skip: int = 0, search: Optional[str] = None: 这些就是我们的查询参数!FastAPI会从URL中解析它们。比如用户访问 /posts?limit=5&search=python,那么 limit就是5,search就是"python"。
  3. statement = select(models.Post, func.count(models.Vote.post_id).label("votes")) ...:
    • 这里开始构建SQLModel的查询语句。select() 是起点。
    • 我们不仅要 models.Post(帖子本身),还要 func.count(models.Vote.post_id).label("votes")(统计每个帖子的投票数,并把这个统计结果命名为 votes)。func 来自 sqlalchemy (SQLModel底层使用它),提供了数据库函数如 COUNT, SUM等。
  4. .join(models.Vote, models.Vote.post_id == models.Post.id, isouter=True):
    • 这是多表查询的关键!我们要把 Post 表和 Vote 表连接起来。
    • 连接条件是 models.Vote.post_id == models.Post.id (投票表中的帖子ID等于帖子表中的帖子ID)。
    • isouter=True 表示使用 左外连接 (LEFT OUTER JOIN)。这意味着即使一个帖子没有任何投票记录,它仍然会出现在结果中,其 votes 计数会是0。如果不用 isouter=True (即默认的内连接 INNER JOIN),那么没有投票的帖子就不会被查出来。
  5. .group_by(models.Post.id):
    • 因为我们用了聚合函数 func.count(),所以需要告诉数据库按什么来分组统计。这里我们按帖子的ID (models.Post.id) 分组,这样就能得到每个帖子的投票数。
  6. if search: statement = statement.where(models.Post.title.contains(search)):
    • 如果用户在URL中提供了 search 参数,我们就在查询语句中添加一个 where 条件,筛选出标题 (models.Post.title) 包含 (contains) 搜索词的帖子。
  7. statement = statement.limit(limit).offset(skip):
    • 将分页参数应用到查询语句上。
  8. results = db.exec(statement).all():
    • 执行最终构建好的查询语句,并获取所有结果。results 会是一个列表,每个元素是 (Post对象, votes数量) 这样的元组。
  9. return results:
    • 直接返回这个 results。FastAPI会很智能地根据我们之前定义的 response_model=List[schemas.PostOut] 来把这个元组列表转换成符合 PostOut 结构的JSON列表返回给客户端。

2. 数据库表关系与联接:让数据“手拉手”

在真实世界中,数据很少是孤零零存在的。比如:

  • 一个用户(User) 可以发布多篇帖子(Post)。(一对多关系)
  • 一个用户(User) 可以给多篇帖子(Post) 点赞,一篇帖子(Post) 也可以被多个用户(User) 点赞。(多对多关系,通常通过一个中间表,如 投票(Vote) 表来实现)

SQLModel 如何定义这些关系?

SQLModel 的美妙之处在于它同时是Pydantic模型(用于数据校验和序列化)和数据库表模型。

# --- models.py ---
from datetime import datetime
from typing import Optional, List # 注意这里也需要 List
from sqlmodel import SQLModel, Field, Relationship # 导入SQLModel的核心组件
from sqlalchemy import text # 用于设置数据库级别的默认值# 用户模型
class User(SQLModel, table=True):__tablename__ = "users" # 表名id: Optional[int] = Field(default=None, primary_key=True)email: str = Field(unique=True, index=True, nullable=False) # 邮箱唯一且建立索引password: str = Field(nullable=False)created_at: datetime = Field(default_factory=datetime.utcnow, # Python级别默认值sa_column_kwargs={"server_default": text("now()")} # 数据库级别默认值)# 定义关系:一个用户可以有多篇帖子# "Post" 是关联的模型类名(字符串形式避免循环导入问题)# back_populates="owner" 指向 Post 模型中名为 "owner" 的关系属性posts: List["Post"] = Relationship(back_populates="owner")# 帖子模型
class Post(SQLModel, table=True):__tablename__ = "posts" # 表名id: Optional[int] = Field(default=None, primary_key=True)title: str = Field(index=True, nullable=False) # 标题也加个索引,方便搜索content: str = Field(nullable=False)published: bool = Field(default=True, sa_column_kwargs={"server_default": text("true")})created_at: datetime = Field(default_factory=datetime.utcnow,sa_column_kwargs={"server_default": text("now()")})# 外键:这篇帖子的作者是谁# foreign_key="users.id" 指向 users 表的 id 字段# nullable=False 表示每篇帖子都必须有作者owner_id: int = Field(foreign_key="users.id", nullable=False)# 定义关系:这篇帖子的作者 (User 对象)# back_populates="posts" 指向 User 模型中名为 "posts" 的关系属性owner: Optional[User] = Relationship(back_populates="posts")# 投票模型 (用于用户给帖子点赞)
class Vote(SQLModel, table=True):__tablename__ = "votes"# 复合主键:一个用户对一个帖子只能投一票user_id: int = Field(foreign_key="users.id", primary_key=True, ondelete="CASCADE")post_id: int = Field(foreign_key="posts.id", primary_key=True, ondelete="CASCADE")# ondelete="CASCADE" 表示如果关联的 User 或 Post 被删除,这条 Vote 记录也会被自动删除

代码讲解 (models.py):

  • class User(SQLModel, table=True):: 定义一个User模型,它既是SQLModel(数据库表模型),也是Pydantic模型。table=True表示它对应数据库中的一张表。
  • id: Optional[int] = Field(default=None, primary_key=True): 定义 id 字段,是主键,可选(数据库会自动生成)。
  • posts: List["Post"] = Relationship(back_populates="owner"):
    • 这是定义关系的关键!它告诉SQLModel,一个 User 对象可以关联多个 Post 对象。
    • List["Post"] 表示这个 posts 属性是一个 Post 对象的列表。用字符串 "Post" 是为了避免Python在解析时可能遇到的循环导入问题。
    • back_populates="owner" 指的是,在 Post 模型那边,有一个名为 owner 的属性也定义了与 User 的关系,并且它们是相互关联的。
  • class Post(SQLModel, table=True):: 类似地定义 Post 模型。
  • owner_id: int = Field(foreign_key="users.id", nullable=False):
    • 这是外键字段。它存储的是对应 User 表中某条记录的 id
    • foreign_key="users.id" 明确指定了它引用 users 表的 id 列。
    • nullable=False 表示一篇帖子必须有一个作者。
  • owner: Optional[User] = Relationship(back_populates="posts"):
    • User 模型中的 posts 关系相呼应。它表示一个 Post 对象关联一个 User 对象(即帖子的作者)。
  • class Vote(SQLModel, table=True)::
    • user_id: int = Field(foreign_key="users.id", primary_key=True, ...)
    • post_id: int = Field(foreign_key="posts.id", primary_key=True, ...)
    • 这两个字段共同构成了复合主键,确保一个用户对一篇帖子只能投票一次。它们也都是外键,分别引用 users 表和 posts 表。
    • ondelete="CASCADE": 这是一个数据库层面的约束。如果一个用户被删除了,那么他所有的投票记录也会自动被删除。同理,如果一个帖子被删除了,关于这个帖子的所有投票记录也会被删除。这有助于保持数据的整洁和一致性。

为何需要联接 (Joins)?

想象一下,你想显示一篇帖子的详细信息,同时还要显示发帖人的用户名,以及这篇帖子有多少个赞。

  • 帖子标题、内容在 Post 表。
  • 发帖人用户名在 User 表(通过 Post.owner_id 关联)。
  • 点赞数需要统计 Vote 表中对应 post_id 的记录数量。

如果不用联接,你可能需要:

  1. 查询 Post 表获取帖子信息。
  2. 根据 Post.owner_id 再去 User 表查询用户信息。
  3. 根据 Post.id 再去 Vote 表统计点赞数。

这样查询次数太多,效率低下!联接 (Join) 就是为了解决这个问题,它允许你在一次数据库查询中,把来自不同但相关联的表的数据“拼接”在一起。

3. 玩转 SQLModel:多表联合查询实战

我们回到之前的 get_all_posts 接口,它已经用到了联接:

# --- main.py (或者你的API路由文件) ---
# ... (省略之前的导入和router定义) ...# 先定义好我们的响应模型 schemas.py
# --- schemas.py ---
from datetime import datetime
from pydantic import BaseModel # SQLModel本身就是Pydantic模型,但有时为了清晰或特定场景会用BaseModel
from .models import User # 导入你的SQLModel模型 Userclass UserOut(BaseModel): # 用于在响应中展示的用户信息,不包含密码等敏感信息id: intemail: strcreated_at: datetimeclass Config:from_attributes = True # Pydantic V2中的配置,允许从ORM对象属性创建模型实例class PostResponseBase(BaseModel): # 帖子基础信息id: inttitle: strcontent: strpublished: boolcreated_at: datetimeowner_id: intowner: UserOut # 嵌套UserOut,显示作者信息class Config:from_attributes = Trueclass PostOut(BaseModel): # 最终API返回的帖子结构,包含帖子信息和投票数Post: PostResponseBase # 帖子自身的详细信息votes: int             # 这个帖子的投票总数class Config:from_attributes = True # 确保可以从 (Post对象, votes数量) 这样的元组构造# ... 回到你的 API 路由文件 ...
@router.get("/", response_model=List[schemas.PostOut])
async def get_all_posts(db: Session = Depends(database.get_db),limit: int = 10,skip: int = 0,search: Optional[str] = None
):statement = (select(models.Post, # 选择 Post 模型对象func.count(models.Vote.post_id).label("votes") # 计算投票数,并命名为 "votes").join(models.Vote, models.Post.id == models.Vote.post_id, isouter=True) # 左外连接 Vote 表.group_by(models.Post.id) # 按帖子ID分组)if search:statement = statement.where(models.Post.title.contains(search))statement = statement.limit(limit).offset(skip)# results_from_db 的结构是 List[Tuple[Post, int]]# 例如:[(<Post object at 0x...>, 5), (<Post object at 0x...>, 0)]results_from_db = db.exec(statement).all()# FastAPI 会自动根据 response_model 将 results_from_db 转换# 它会尝试把每个 (Post, int) 元组 构造成一个 schemas.PostOut 对象# Post对象会被用来填充 PostOut.Post 字段 (内部的 PostResponseBase 会通过 Post.owner 自动加载用户信息)# int 会被用来填充 PostOut.votes 字段return results_from_db# 如果你想创建一个帖子,同时关联当前登录的用户作为作者
@router.post("/", status_code=status.HTTP_201_CREATED, response_model=schemas.PostResponseBase) # 注意响应模型
def create_post(post_data: schemas.PostCreate, # PostCreate 是一个只包含 title, content, published 的Pydantic模型db: Session = Depends(database.get_db),current_user: models.User = Depends(oauth2.get_current_user) # 获取当前登录用户
):# **post_data.model_dump() 把 Pydantic 模型转为字典# owner_id=current_user.id 把当前用户的ID设为帖子的作者IDnew_post = models.Post(**post_data.model_dump(), owner_id=current_user.id)db.add(new_post)db.commit()db.refresh(new_post) # 刷新new_post对象,使其包含数据库生成的值(如ID, created_at)# new_post.owner 会自动通过 relationship 加载关联的 User 对象# FastAPI 会根据 response_model=schemas.PostResponseBase 自动序列化return new_post

代码讲解 (schemas.py 和 create_post):

  1. schemas.py 的作用

    • UserOut: 定义了当我们需要在API响应中显示用户信息时,只显示哪些字段(比如不显示密码)。
    • PostResponseBase: 定义了帖子的基本输出信息,并且它嵌套了 owner: UserOut,这意味着在返回帖子信息时,会自动把作者的 UserOut 信息也包含进去。
    • PostOut: 这是我们 get_all_posts 接口最终的响应结构。它包含一个 Post 字段(类型是 PostResponseBase,即帖子详情加作者信息)和一个 votes 字段(帖子的点赞数)。
    • class Config: from_attributes = True: 这个配置(在Pydantic V2中,旧版是 orm_mode = True)非常重要。它允许Pydantic模型直接从数据库对象(ORM对象,比如我们的SQLModel实例)的属性来创建实例。比如,如果一个 Post SQLModel对象有 titlecontent 属性,PostResponseBase 就能直接用这些属性来填充自己。
  2. get_all_posts 返回 results_from_db

    • db.exec(statement).all() 执行后,results_from_db 是一个列表,每个元素是 (Post模型实例, 投票数) 这样的元组。
    • FastAPI看到 response_model=List[schemas.PostOut],它会尝试把每个元组 (p, v) 转换成一个 schemas.PostOut(Post=p, votes=v) 的实例。
    • schemas.PostOutPost 字段类型是 schemas.PostResponseBase。由于 from_attributes = TruePostResponseBase 会从 p (Post模型实例) 中读取属性。
    • 特别地,PostResponseBase 中的 owner: UserOut 字段,会因为 Post SQLModel模型中定义了 owner: Optional[User] = Relationship(...) 而被自动填充。SQLModel(或底层的SQLAlchemy)会在需要时加载关联的 User 对象,然后 UserOut 再从这个 User 对象中提取信息。
  3. create_post 接口

    • post_data: schemas.PostCreate: PostCreate 是一个Pydantic模型,用于接收创建帖子时客户端发来的数据(比如只有 title, content)。
    • current_user: models.User = Depends(oauth2.get_current_user): 假设你有一个 oauth2.py 文件,里面的 get_current_user 函数会验证JWT token并返回当前登录的 User SQLModel对象。
    • new_post = models.Post(**post_data.model_dump(), owner_id=current_user.id):
      • post_data.model_dump()PostCreate Pydantic模型转换成一个字典。
      • ** 将这个字典解包,作为参数传递给 models.Post 的构造函数。
      • owner_id=current_user.id 明确设置了这篇新帖子的作者是当前登录用户。
    • db.add(new_post), db.commit(), db.refresh(new_post): 这是标准的SQLModel(或SQLAlchemy)操作,将新对象添加到会话、提交到数据库、然后刷新对象以获取数据库生成的值。
    • return new_post: 返回创建好的 models.Post 对象。因为 response_model=schemas.PostResponseBase,FastAPI会自动将这个 Post 对象(包括其通过relationship加载的 owner 信息)转换为 PostResponseBase 格式的JSON响应。

关键点总结:

  • SQLModel 让模型定义更简单:一个类同时搞定Pydantic校验和数据库表结构。
  • Relationship 很强大:在SQLModel模型中定义好 Relationship,SQLModel(底层SQLAlchemy)就能帮你处理很多关联数据的加载。
  • select().join() 是多表查询的核心:用它来连接不同的表。isouter=True 用于左外连接,确保即使没有关联数据(如帖子没有投票)主表数据也能查出来。
  • func.count()group_by() 用于聚合统计:比如统计每个帖子的投票数。
  • FastAPI 的 response_model 和 Pydantic 的 from_attributes = True 是天作之合:它们能让你轻松地将数据库查询结果(甚至是包含关联对象的复杂结果)转换成规范的JSON API响应。

总结

通过本文,你已经掌握了如何在FastAPI中利用SQLModel的强大功能,通过查询参数让API更灵活,通过数据库联接Relationship高效查询和展示关联数据。

你学会了:

  1. 在FastAPI接口中定义查询参数(limit, skip, search)。
  2. 使用SQLModel的 select() 语句,并通过 .where(), .limit(), .offset() 来应用这些参数。
  3. 在SQLModel模型中通过 Field(foreign_key=...)Relationship(back_populates=...) 定义表间关系。
  4. 使用 select().join() 进行多表查询,特别是用 isouter=True 实现左外连接。
  5. 使用 func.count().label().group_by() 进行聚合统计。
  6. 设计合适的Pydantic响应模型(如 schemas.PostOut),并利用FastAPI的 response_model 特性自动转换查询结果。

现在,你已经具备了构建更复杂、更强大、用户体验更好的API的能力!动手试试,你会发现SQLModel和FastAPI的组合是如此优雅和高效。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为OD-2024年E卷-通过软盘拷贝文件[200分] -- python

问题描述&#xff1a; 有一名科学家想要从一台古董电脑中拷贝文件到自己的电脑中加以研究。但此电脑除了有一个3.5寸软盘驱动器以外&#xff0c;没有任何手段可以将文件持贝出来&#xff0c;而且只有一张软盘可以使用。因此这一张软盘是唯一可以用来拷贝文件的载体。科学家想要…

Keepalived 高可用,nginx + keepalived , lvs + keepalived、 数据库+keepalived

keepalived 官网 Keepalived 可以用来防止服务器单点故障的发生 # 原理 是基于VRRP协议实现的&#xff0c;当backup收不到vrrp包时&#xff0c;就认为master宕机了&#xff0c;这时就需要根据VRRP的优先级来选举一个backup 当master&#xff0c;就实现服务的HA&#xff08;高…

开疆智能Devicenet转ModbusTCP网关连接台达从站通讯模块配置案例

本案例是通过开疆智能Devicenet转ModbusTCP网关连接台达Devicenet从站通讯模块DVPDT02-H2的配置案例&#xff0c;网关作为ModbusTCP服务器和Devicenet主站&#xff0c;连接台达Devicenet从站&#xff0c; 配置过程&#xff1a; 首先配置Devicenet从站&#xff0c;先设置从站De…

网络NAT是什么

网络NAT&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09;是一种用于计算机网络中的技术&#xff0c;主要目的是在私有网络与公有网络&#xff08;比如互联网&#xff09;之间转换IP地址&#xff0c;实现私有网络中的多台设备通过一个公网IP访问外…

React状态管理——react-redux

目录 一、redux介绍 二、安装 三、基本实现步骤 3.1 创建Action Types 3.2 创建counterAction 3.3 创建counterReducer 3.4 结合所有Reducer 3.5 创建store 3.6 入口文件中提供store 3.7 在组件中的使用 3.8 使用thunk实现异步支持 3.8.1 安装 3.8.2 在counterAct…

Java 零工市场小程序 | 灵活就业平台 | 智能匹配 | 日结薪系统 | 用工一站式解决方案

在就业形势如此严峻的情况下&#xff0c;很多小伙伴都会选择零工的工作方式来赚取外快&#xff0c;很多用人单位也会因为职为短暂空缺或是暂时人手不够而选择招用兼职人员。 而Java 作为企业级开发的主流语言&#xff0c;以其卓越的性能和稳定性著称。把零工的需求&#xff08…

数据可视化——一图胜千言

第04篇&#xff1a;数据可视化——一图胜千言 写在前面&#xff1a;大家好&#xff0c;我是蓝皮怪&#xff01;前面几篇我们聊了统计学的基本概念、数据类型和描述性统计&#xff0c;这一篇我们要聊聊数据分析中最直观、最有趣的部分——数据可视化。你有没有发现&#xff0c;很…

1.1 Linux 编译FFmpeg 4.4.1

一、安装编译工具 sudo apt install -y autoconf automake build-essential cmake git pkg-config nasm yasm libtool zlib1g-dev说明&#xff1a; autoconf&#xff1a;生成 configure 脚本&#xff0c;用于自动配置源码。automake&#xff1a;与 autoconf 配合&#xff0c;…

【图片识别改名】如何批量识别大量图片的文字并重命名图片,基于WPF和京东OCR识别接口的实现方案

应用场景 在企业文档管理、数字图书馆、电商商品管理等场景中&#xff0c;经常需要处理大量图片中的文字信息。例如&#xff1a; 电商平台需要将商品图片中的型号、规格等信息提取出来作为文件名图书馆需要将扫描的图书页面识别为文字并整理归档企业需要将纸质文档电子化并按…

简历模板2——数据挖掘工程师5年经验

姓名 / Your Name 数据挖掘工程师 | 5年经验 | 推荐/风控/图模型 &#x1f4de; 138-XXXX-XXXX | ✉️ your.emailexample.com | &#x1f310; github.com/yourname | &#x1f4cd; 北京 &#x1f3af; 个人简介 / Summary 5年大厂数据挖掘经验&#xff0c;硕士学历。擅长推…

CSS3 渐变效果

1. 引言 CSS3 渐变能够在指定颜色之间创建平滑过渡效果。这种设计元素不仅能为网页增添丰富的视觉层次&#xff0c;更是现代网页设计的重要组成部分。CSS3 提供两种主要的渐变类型&#xff1a;线性渐变(Linear Gradient) - 沿直线方向进行颜色过渡&#xff1b;径向渐变(Radial…

A Survey on 3D Gaussian Splatting——3D高斯领域综述

原文链接&#xff1a;[2401.03890] A Survey on 3D Gaussian Splatting 动态更新的GitHub仓库&#xff08;包含性能对比与最新文献追踪&#xff09;&#xff1a; https://github.com/guikunchen/3DGS-Benchmarks https://github.com/guikunchen/Awesome3DGS 摘要&#xff1…

计算机网络 期末实训 eNSP 校园网

eNSP 综合实训 小型校园网 计算机网络期末实训 01 搭建拓扑 1.设计任务 构建一个小型校园网络,涵盖以下设备与区域: 学生宿舍区:50台计算机办公楼区:30台计算机(细分为财务部门、人事部门及其他科室)图书馆:10台计算机教学楼:30台计算机服务器集群:2台服务器,分别用…

Smart Form Adobe form 强制更改内表:TNAPR

强制更改内表:TNAPR se16-> Smart Form总览 Smart form 变量格式说明: &symbol& (括号中,小写字母为变量) &symbol& 屏蔽从第一位开始的N位 &symbol (n)& 只显示前N位 &symbol (S)& 忽略正负号 &symbol (<)& 符号在…

页面配置文件pages.json和小程序配置

页面配置文件pages.json和小程序配置 pages.jsonpagesstyle-navigationBarBackgroundColorstyle-navigationBarTitleTextstyle-navigationStylestyle-enablePullDownRefresh注意事项不同平台区分配置新建页面 globalStyletabBar代码 manifest.json授权web配置代理 pages.json …

Linux网络配置工具ifconfig与ip命令的全面对比

在Linux网络管理中&#xff0c;ifconfig和 ip命令是最常用的两个工具。随着时间的推移&#xff0c;ip命令逐渐取代了 ifconfig&#xff0c;成为更强大和灵活的网络配置工具。本文将对这两个工具进行全面对比&#xff0c;帮助您理解它们的区别和各自的优势。 一、ifconfig命令 …

STM32 实现解析自定义协议

一、环形队列设计与实现&#xff08;核心缓冲机制&#xff09; 数据结构设计&#xff1a; #define BUFFER_SIZE 512 #define BUFFER_MASK (BUFFER_SIZE - 1) typedef struct {volatile uint8_t buffer[BUFFER_SIZE]; // 环形缓冲区&#xff08;大小可配置&#xff09;volati…

NGINX 四层上游模块`ngx_stream_upstream_module` 实战指南

一、模块定位与引入 模块名称&#xff1a;ngx_stream_upstream_module 首次引入&#xff1a;NGINX 1.9.0&#xff08;2015-08-04&#xff09; 编译选项&#xff1a;启用 --with-stream&#xff08;含此模块&#xff09; 作用&#xff1a; 定义后端服务器组&#xff08;upstr…

WinUI3入门2:DataGrid动态更新 添加删除和修改字段

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

基于Python学习《Head First设计模式》第十三章 现实世界中的模式

定义设计模式 设计模式要素 模式名称、分类意图&#xff1a;描述模式是什么动机&#xff1a;描述什么时候使用这个模式&#xff0c;具体场景适用性&#xff1a;描述什么地方使用这个模式&#xff0c;用在什么场合结构&#xff1a;类图参与者&#xff1a;类和对象的责任和角色…