Flask + SQLAlchemy 实战:从数据模型到查询优化的完整指南

发布时间:2026/10/10 6:35:17

Flask + SQLAlchemy 实战:从数据模型到查询优化的完整指南 简介面向优达学城全栈开发课程的Fyyur项目源码主要服务于正在学习Flask与PostgreSQL数据建模的开发者。项目围绕音乐演出场地和艺术家预约网站展开要求为现有视图与控制器补齐数据模型实现对场所、艺术家及表演场次的创建、检索与更新。压缩包共64个文件大小约2.32MB包含18个HTML页面、10个CSS样式、8个JavaScript脚本、7个Python程序及6个pyc文件另有配置文件、字体、图片和说明文档目录结构清晰。当前已有75人学习浏览。通过阅读项目中的Python程序、表单模块与数据库迁移脚本可以理解路由、表单和数据模型的组织方式结合依赖清单与迁移配置还可掌握环境搭建和数据库版本管理方法适合作为课程作业、实战练习或作品集项目参考。1. Fyyur 不是普通的 CRUD 作业它逼你把 Flask 的数据关系想清楚Fyyur 是 Udacity 课程项目里一个特别典型的全栈练习为独立乐队艺人和演出场地搭建预约平台。表面看只有场地、艺人、演出三块内容的增删改查实际动手后才会发现真正的门槛不在 Flask 路由和 Jinja2 模板而在「一场演出如何同时关联一个艺人和一个场地」这种关系建模以及编辑表单回填、搜索模糊匹配、外键级联这些边角逻辑。很多人卡在这个项目上不是不会写视图函数而是没把数据模型想明白就急着敲代码。下面从模型设计讲起把建表、路由、表单、搜索四条线逐一打通最后给一个跨表查询的优化技巧。适合刚学完 Flask 基础、想用完整项目验证 SQLAlchemy 用法的开发者也适合准备把课程项目重构后放进作品集的人。2. 先立数据模型Venue、Artist、Show 三张表的关系决定后面所有代码2.1 为什么这个项目一定要用 ORM 而不是裸 SQLFyyur 的核心业务是「艺人找场地、场地找艺人」数据天然是关联的。用裸 SQL 写当然能跑但你会发现手写 JOIN 的代码会散落在每个路由里而且表单提交后的字段校验得自己一遍遍重复。常见做法是用 Flask-SQLAlchemy 做 ORM 层理由有三一是模型类直接对应表结构改字段后能用工具同步二是关系查询可以走 Python 属性而不是字符串拼接三是配合表单库做校验时字段类型能直接映射到控件。我见过不少同学在这个项目里坚持用sqlite3模块裸写 SQL做到「编辑场地」功能时开始痛苦——因为要手动拼 UPDATE 语句、手动处理没提交的字段、手动判断外键是否存在。对比下来 ORM 的成本几乎可以忽略对比项裸 SQLFlask-SQLAlchemy建表手写 CREATE TABLE模型类自动生成关联查询手写 JOIN 拼字符串relationship 属性直接取字段变更手工 ALTER TABLE重建或迁移代码量路由里塞满 SQL路由只写业务逻辑2.2 三个模型的字段设计与关系选择先看 models.py 的完整定义。这里的关键决策是Show 不是一张普通的中间表而是一张带业务属性start_time的关联模型所以用db.Table做纯关联表并不合适应该建模成独立模型类用两个外键指向 Artist 和 Venue。# models.py from flask_sqlalchemy import SQLAlchemy db SQLAlchemy() class Venue(db.Model): __tablename__ venue id db.Column(db.Integer, primary_keyTrue) name db.Column(db.String(120), nullableFalse) city db.Column(db.String(120), nullableFalse) state db.Column(db.String(120), nullableFalse) address db.Column(db.String(120), nullableFalse) phone db.Column(db.String(120), nullableFalse) genres db.Column(db.String(120), nullableFalse) # 逗号分隔存储 image_link db.Column(db.String(500)) facebook_link db.Column(db.String(500)) seeking_talent db.Column(db.Boolean, defaultFalse) seeking_description db.Column(db.String(500)) shows db.relationship(Show, backrefvenue, lazyTrue, cascadeall, delete-orphan) class Artist(db.Model): __tablename__ artist id db.Column(db.Integer, primary_keyTrue) name db.Column(db.String(120), nullableFalse) city db.Column(db.String(120), nullableFalse) state db.Column(db.String(120), nullableFalse) phone db.Column(db.String(120), nullableFalse) genres db.Column(db.String(120), nullableFalse) image_link db.Column(db.String(500)) facebook_link db.Column(db.String(500)) seeking_venue db.Column(db.Boolean, defaultFalse) seeking_description db.Column(db.String(500)) shows db.relationship(Show, backrefartist, lazyTrue, cascadeall, delete-orphan) class Show(db.Model): __tablename__ show id db.Column(db.Integer, primary_keyTrue) artist_id db.Column(db.Integer, db.ForeignKey(artist.id), nullableFalse) venue_id db.Column(db.Integer, db.ForeignKey(venue.id), nullableFalse) start_time db.Column(db.DateTime, nullableFalse)逻辑说明Show 的两个外键都不写ondeleteCASCADE而是交给 ORM 层的cascade参数。这样删除场地时SQLAlchemy 会先清理关联的 Show 记录再删场地本身避免在 SQLite 里出现外键约束冲突。genres字段用逗号分隔的字符串存储表单渲染时可以按逗号拆成数组模板里也能直接展示省掉一张多对多关联表。参数说明String 长度按表单控件的 maxlength 对齐phone 和 facebook_link 这类不参与查询的字段也给足长度DateTime 字段在 SQLite 下实际存的是文本Flask-SQLAlchemy 会自动转换但后面表单解析时要注意格式统一Boolean 字段的default只在对象首次创建时生效更新时不显式赋值会保持原值——这是后面编辑表单的隐藏坑。2.3 建表的执行顺序与开发期重建策略模型定义好后最常见的是在应用启动时执行db.create_all()。它在每次启动时检查表是否存在不存在才创建。对于 Fyyur 这种没有复杂迁移需求的课程项目够用且直观。# app.py 初始化片段 from flask import Flask from models import db app Flask(__name__) app.config[SQLALCHEMY_DATABASE_URI] sqlite:///fyyur.db app.config[SQLALCHEMY_TRACK_MODIFICATIONS] False db.init_app(app) with app.app_context(): db.create_all()问题在于开发中途改了模型字段create_all不会自动加列。我一般直接删掉 SQLite 文件重建或者用 Flask-Migrate 做一次初始迁移。课程项目阶段没必要把迁移工具玩得很深但要意识到「改模型不重建表」是后面各种 500 报错的最大来源。重建后记得跑一遍种子数据脚本否则页面列表全是空的调试没有参照。提示开发阶段重建 SQLite 数据库非常正常。写一个 seed.py 把场地和艺人各插三条每次重建后执行一遍能省下大量手工录入时间。3. 路由与模板从列表页到预约流程的核心路径3.1 场地列表的分组查询与「即将演出数」统计Fyyur 的场地列表页有一个经典需求按「城市 州」分组展示每个场地旁边显示即将到来的演出数量。这个需求直接在视图函数里做 Python 分组循环即可不需要上 GROUP BY 聚合。# app.py 中 /venues 路由 from datetime import datetime app.route(/venues) def venues(): venue_rows Venue.query.all() city_state_map {} for venue in venue_rows: key (venue.city, venue.state) if key not in city_state_map: city_state_map[key] { city: venue.city, state: venue.state, venues: [] } upcoming [s for s in venue.shows if s.start_time datetime.now()] city_state_map[key][venues].append({ id: venue.id, name: venue.name, num_upcoming_shows: len(upcoming) }) areas list(city_state_map.values()) return render_template(venues.html, areasareas)逻辑说明这里故意没用group_by因为 Fyyur 的场地量级很小Python 侧分组更直观模板里也容易控制嵌套循环。venue.shows是 relationship 的默认懒加载访问时自动发起查询所以列表页存在 N1 查询问题最后一章讲优化办法。参数说明datetime.now()是本地时间如果数据库里存的是 UTC 时间比较结果会整体偏移。很多人列表页的「即将演出」数量不对多半是时区混用导致的后面第 5 章还会专门展开。3.2 搜索接口ilike 模糊匹配与空关键词处理Fyyur 的搜索需求是输入关键词后同时匹配名称和城市。SQLAlchemy 最直接的做法是用ilike在 SQLite 和 PostgreSQL 下都能做到大小写不敏感。app.route(/venues/search) def search_venues(): search_term request.args.get(search_term, ).strip() if not search_term: return redirect(url_for(venues)) results Venue.query.filter( db.or_( Venue.name.ilike(f%{search_term}%), Venue.city.ilike(f%{search_term}%) ) ).all() return render_template(search_venues.html, resultsresults, search_termsearch_term)逻辑说明db.or_把两个模糊条件拼成 OR 查询。用 f-string 拼 like 模式时search_term里的特殊字符不会破坏参数化查询因为 SQLAlchemy 的 filter 始终走参数绑定。空关键词直接重定向回列表页避免用户点搜索按钮没输入内容时看到整张表。参数说明ilike在 SQLite 里对 ASCII 字符有效对中文和带重音字符不友好。如果数据里有中文场地名建议用like并保证存库时大小写统一或者在 Python 侧做过滤。课程项目用ilike最省事生产环境再考虑全文检索。3.3 创建演出外键校验与时间解析的先后顺序创建 Show 是这个项目里最考验数据完整性的一步。表单提交时带artist_id和venue_id两个外键以及一个datetime-local格式的start_time。后端要做的事按顺序来解析表单、校验外键存在、解析时间、写入数据库。app.route(/shows/create, methods[POST]) def create_show(): artist_id request.form.get(artist_id) venue_id request.form.get(venue_id) start_time request.form.get(start_time) artist Artist.query.get(artist_id) venue Venue.query.get(venue_id) if not artist or not venue: flash(艺人或场地不存在请重新选择) return redirect(url_for(create_show_form)) try: parsed_time datetime.strptime(start_time, %Y-%m-%dT%H:%M) except ValueError: flash(时间格式不正确请重新选择) return redirect(url_for(create_show_form)) show Show( artist_idartist.id, venue_idvenue.id, start_timeparsed_time ) db.session.add(show) db.session.commit() return redirect(url_for(show_detail, show_idshow.id))逻辑说明datetime-local控件提交的格式是2024-06-01T20:00没有秒所以strptime的格式串必须带 T 且不含秒。很多教程照抄%Y-%m-%d %H:%M:%S提交时必然报 ValueError。外键校验放在时间解析之前是为了让用户看到具体是哪个数据错了而不是笼统的 400 页面。参数说明flash加redirect是 Flask 处理表单错误的推荐方式。如果需要在同一请求里保留用户输入就要像第 4 章那样用render_template而不是重定向。这里只做了一次 commit没有显式事务后续如果扩展成「创建演出同时更新艺人状态」就要保证所有操作在同一 session 里异常时统一 rollback。3.4 首页最近演出跨三张表的条件查询首页要展示最近十场演出每场包含艺人名、场地名和时间。这需要把 Show、Artist、Venue 三张表关联起来是最能体现 ORM 优势的一处。app.route(/) def index(): recent_shows ( db.session.query(Show) .join(Artist, Show.artist_id Artist.id) .join(Venue, Show.venue_id Venue.id) .order_by(Show.start_time.desc()) .limit(10) .all() ) return render_template(index.html, showsrecent_shows)模板里访问show.artist.name、show.venue.name即可SQLAlchemy 会根据外键自动完成对象关联。逻辑说明两个 join 把三张表串起来order_by按时间倒序取最近十条limit 控制返回行数。这里没有用 selectinload 预加载所以模板里访问 artist 和 venue 时仍会触发额外查询但只有十条影响可忽略。参数说明desc()表示倒序limit(10)是 SQL 层截断。如果首页想同时展示「即将开始」的演出可以在 join 之后加.filter(Show.start_time datetime.now())这比先查出全量再在 Python 里过滤要高效得多SQLite 也能用上索引。4. 表单回填与校验编辑场景最容易翻车的三个细节4.1 编辑页的字段回填把数据库值映射回表单控件Fyyur 的编辑表单和创建表单共用同一个模板区别只在路由是 GET 还是 POST、模板里是否带 value 属性。回填的坑集中在 genres 和 seeking_talent 这类非常规字段。!-- venue_edit.html 片段 -- form methodPOST action/venues/{{ venue.id }}/edit input namename value{{ venue.name }} required input namecity value{{ venue.city }} required input namestate value{{ venue.state }} required input nameaddress value{{ venue.address }} required input namephone value{{ venue.phone }} required input namegenres value{{ venue.genres }} select nameseeking_talent option valuetrue {% if venue.seeking_talent %}selected{% endif %}是/option option valuefalse {% if not venue.seeking_talent %}selected{% endif %}否/option /select textarea nameseeking_description{{ venue.seeking_description }}/textarea button typesubmit保存/button /form逻辑说明seeking_talent是 Boolean 字段在 select 选项里用selected判断选中态。提交的值是字符串true或false后端读取时不能直接当布尔用必须做一次转换否则if request.form.get(seeking_talent)永远为真。genres因为存的是逗号分隔字符串回填到文本框时直接显示原始字符串即可用户编辑时整串修改。参数说明required属性只是浏览器端校验后端依然要再校验因为直接 POST 请求可以绕过浏览器。Jinja2 渲染 value 时自动做 HTML 转义不用担心引号破坏页面结构。如果模板里同时出现{{ venue.xxx }}和手动拼字符串的写法要注意保持转义一致避免 XSS 隐患。4.2 校验失败时保留用户输入render 而不是 redirect后端校验失败时如果只是 redirect 回编辑页用户填的内容全丢了。常见做法是失败时用render_template而不是重定向把表单数据和错误信息一起传入。app.route(/venues/int:venue_id/edit, methods[POST]) def edit_venue(venue_id): venue Venue.query.get_or_404(venue_id) name request.form.get(name, ).strip() if not name: flash(场地名称不能为空) return render_template( venue_edit.html, venuevenue, form_datarequest.form ) venue.name name venue.city request.form.get(city, ).strip() venue.state request.form.get(state, ).strip() venue.address request.form.get(address, ).strip() venue.phone request.form.get(phone, ).strip() venue.genres request.form.get(genres, ).strip() venue.seeking_talent request.form.get(seeking_talent) true venue.seeking_description request.form.get( seeking_description, ).strip() db.session.commit() flash(场地信息已更新) return redirect(url_for(venue_detail, venue_idvenue.id))逻辑说明失败分支用render_template回显form_data模板里优先读form_data的值读不到再回退到venue对象。这样用户看到的是自己刚填的内容而不是旧数据。seeking_talent的转换在这一行request.form.get(seeking_talent) true刚好对应模板里 value 为true的选中项。参数说明.strip()去掉首尾空格避免数据库存出北京 这种脏数据。get_or_404自动处理 id 不存在的情况不用手写if not venue。提交成功后 redirect 是 PRG 模式防止用户刷新页面重复提交。4.3 CSRF 与 400 错误别让表单在本地突然失灵很多人在本地跑 Fyyur 时表单提交一切正常部署到服务器后突然 400页面白屏。原因多半是模板里缺了 CSRF 令牌而某些表单库在模板渲染时会强制校验。Fyyur 如果用手写 HTML 表单而不走表单库的 form 对象要么全局关闭 CSRF要么手动在模板里加隐藏字段。半途加 CSRF 是最容易翻车的启用后所有 POST 请求都必须带令牌包括用脚本写测试数据时的 POST。我见过有人本地测试一直报 400排查半天发现是测试脚本没带csrf_token。如果没准备用 Flask-WTF最简单的方案是保持关闭最怕的是有的页面带、有的页面不带那种间歇性 400 会让人怀疑人生。注意判断 400 是不是 CSRF 导致的看响应体里有没有 The CSRF token is missing 字样。有就是令牌问题没有就去查字段名和路由是否匹配。4.4 创建与编辑共用模板一个布尔参数的复用写法创建页面和编辑页面的表单结构几乎一样区别只在 action 地址和是否回填。常见做法是共用一个模板文件通过传入的 venue 对象是否存在来决定行为。!-- venue_form.html 片段 -- {% set target url_for(edit_venue, venue_idvenue.id) if venue else url_for(create_venue) %} form methodPOST action{{ target }} input namename value{{ form_data.get(name) if form_data else venue.name if venue else }} button typesubmit保存/button /form逻辑说明Jinja2 的 set 语句根据 venue 是否传入决定表单提交地址。value 的取值优先级是form_data、venue、空字符串覆盖了「校验失败回显」「编辑回填」「新建空白」三种场景一套模板全搞定。参数说明这种写法的前提是路由里对两种请求都传了正确变量创建页面传venueNone编辑页面传venuevenue_obj。如果忘记传Jinja2 访问未定义变量会渲染成空表单能显示但回填全丢。调试时先看模板收到的变量再看模板报错。5. 本地调试避坑Fyyur 最常见的五个翻车现场5.1 改完模型后列表页报 500表结构没同步现象给 Venue 模型新增了一个字段后打开场地详情页直接 500终端日志报no such column: venue.xxx。原因SQLite 数据库文件还是旧表结构db.create_all()只建新表不改旧表。解决开发阶段直接删掉instance/fyyur.db重新create_all再跑种子脚本。如果已经用 Flask-Migrate 管理就执行迁移命令。建议课程项目选前者不值得为模型迁移投入额外时间。这个坑出现频率极高基本每次改模型都要来一遍。5.2 编辑保存后什么都不变Boolean 字段被字符串常量覆盖现象把 seeking_talent 从「否」改成「是」保存后刷新页面还是「否」。原因后端写的是venue.seeking_talent request.form.get(seeking_talent)提交的值是字符串false而if false在 Python 里为真于是把 False 覆盖成了 True。反过来把「是」改「否」时字符串true也为真等于永远写入 True页面看起来像没改。解决统一用request.form.get(seeking_talent) true做转换。排查时先看数据库实际存的值再回头检查赋值语句。这个坑几乎每个做 Fyyur 的人都会踩一次属于典型的类型意识缺失。5.3 搜索关键词带空格时结果为空忘了 strip现象输入「北京」搜不出来输入「 北京 」却能搜出来或者反过来。原因搜索词直接拼进 ilike 模式前后空格导致匹配失败或者存库时字段带了空格查询时没带。解决查询前调.strip()清理搜索词。如果还不行检查库里有没有脏数据用一次 UPDATE 把字段首尾空格清掉。这个属于写查询函数时顺手解决的事但漏掉的人特别多而且表现很隐蔽不容易第一时间想到是空格问题。5.4 演出时间显示不一致时区混用现象数据库存的是 22:00列表页显示 22:00详情页显示 05:00差了好几个小时。原因有的路由用datetime.utcnow()做比较有的路由用datetime.now()存库时又用了带时区信息的对象模板渲染时再一转换就乱套了。解决统一全项目用本地时间。存库前strptime得到 naive datetime模板里直接输出不附加时区不要用datetime.now(timezone.utc)这类带时区对象。这个坑踩过之后我给自己定了条规矩Fyyur 这种单时区项目所有时间一律用 naive local time彻底避免混用。5.5 删除场地报 IntegrityError级联删除没配好现象删除一个已经有过演出的场地SQLAlchemy 抛IntegrityError: FOREIGN KEY constraint failed。原因Show 表里 venue_id 引用着这个场地级联删除没生效。解决在 relationship 上加cascadeall, delete-orphan第 2 章的代码已经加了。如果数据库里已有历史脏数据先手动把关联的 Show 清掉再删场地。这个坑的特点是从来没演出的场地删得好好的一旦有演出记录必炸特别容易让人误以为是演出记录本身的问题。6. 进阶一点用一次连接查询解决列表页的 N1 性能隐患Fyyur 的场地列表页每渲染一个场地就要查询一次它的 shows 集合数据量小的时候没感觉但场地数过百、每场都有几十条演出记录时页面响应会肉眼可见变慢。这是典型的 N1 问题一次主查询加 N 次关联查询。解决思路是用joinedload一次性 JOIN 取回关联数据。# 用 joinedload 一次性加载关联的 show from sqlalchemy.orm import joinedload app.route(/venues) def venues(): venue_rows Venue.query.options( joinedload(Venue.shows) ).all() # 后面的分组逻辑不变venue.shows 不再触发额外查询逻辑说明joinedload会用 LEFT OUTER JOIN 把 Venue 和 Show 一次查出来SQLAlchemy 在内存里完成对象组装。JOIN 结果里同一个场地会重复出现多次ORM 根据主键自动去重得到的venue_rows数量依然是场地数没有重复。参数说明如果列表页还要显示每场演出的艺人名就要链式joinedload(Venue.shows).joinedload(Show.artist)否则访问show.artist时又会触发新的查询。这个技巧在数据量上来之前看不出差别但对理解 ORM 的查询计划很有帮助。把app.config[SQLALCHEMY_ECHO] True开一段时间你会看到用了 joinedload 后整个页面只剩一条 SQL。我在做这个项目时习惯开着 SQL 日志观察每个页面的查询条数。看到列表页疯狂刷查询语句的时候才真正理解 N1 是怎么回事。后来我把这个检查习惯带到了所有 Flask 项目里先看 SQL 条数再决定要不要优化而不是凭感觉提前堆缓存。这个思路比任何 ORM 技巧都值钱希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/10 6:35:17

Exadata X9M数据库一体机全解读:从原理到落地的避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 6:35:17

Unity反编译实战:用dnSpy分析并修改游戏代码

简介:dnSpy是一款功能强大的.NET程序反编译与调试工具,专为Unity开发者、游戏引擎研究者及希望从现有软件中学习代码逻辑的技术人员准备。借助该工具,可直接打开并分析Unity项目生成的C#程序集(dll),还原类…

2026/10/10 6:35:17

Fyyur实战:Flask全栈项目从跑通到ORM进阶与避坑指南

简介:Fyyur-Udacity-Project是Udacity全栈开发课程中的音乐演出场地与艺术家预定网站项目,适合正在学习Flask、PostgreSQL和Web API设计的开发者。该项目已具备视图与控制器,但缺少数据模型和数据库交互能力,学习重点在于补全模型…

2026/10/10 7:35:21

MCP Server 生产级实践:从跑通到敢上线的四个关键步骤

1. 从"能跑"到"敢上线":MCP Server 的鸿沟到底在哪很多人第一次写 MCP Server 的经历都差不多:照着官方 SDK 的示例,定义一个 tool,写个 handler,本地用客户端连上,看到工具被正确调用…

2026/10/10 7:35:21

Android Fragment重叠问题详解:成因、排查与解决方案

如果你写过一段时间的安卓应用,大概率遇到过这样一个诡异场景:某个页面上明明只该有一个弹窗或一个子页面,结果界面上出现了两份一模一样的 Fragment,点掉一层还有一层。我最早是在一个资讯类 App 的详情页踩到这个坑的——用户连续双击“展开更多”按钮,底部弹出的面板叠了两层…

2026/10/10 7:35:21

多智能体协作实战:从提示词堆砌到团队化分工调度

做AI应用这些年,我越来越觉得“单智能体包打天下”这个思路在真实业务约束下并不可靠。最近我搭了一套内部代号叫agency-agents的模拟项目,核心就是让多个智能体像一个小团队一样分工协作。它解决的场景很典型:一次任务里既要做资料搜集&…

2026/10/10 7:35:21

基于Python的Django+Flask畜牧站疾病防控与检测系统实战解析

做基层畜牧站的信息化项目,最头疼的不是算法,而是把一堆琐碎的防疫流程理顺。最近在开发一个基于Python的畜牧站疾病防控与检测系统,技术栈选了DjangoFlask这个组合。很多人第一反应是“一个项目为什么要混用两个框架”,其实真正落…

2026/10/10 7:30:21

Spring Boot昆虫标本管理系统实战:从数据库设计到毕业答辩全流程

简介:这是一份面向高校毕业设计场景的Spring Boot昆虫标本管理系统完整项目资料。系统围绕昆虫标本汇总、标本分类、论坛管理、留言咨询及图片识别等功能模块展开,采用Java语言与MySQL数据库,以B/S结构实现管理员与用户双端操作,可…

2026/10/10 7:31:36

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/9 20:15:56

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 0:04:53

从逻辑门到计算机:数字电路核心原理与全加器搭建实战

如果你拆过一台旧电脑的主板,盯着那些黑乎乎的小芯片看上一会儿,可能会冒出同一个疑问:这堆引脚密集的元件,到底是怎么“变”出那么复杂的应用的?答案并不在某个神秘的部件里,而是在所有芯片内部都在反复使…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑