做网站是否用数据库崇礼网站建设

张小明 2026/1/10 12:45:56
做网站是否用数据库,崇礼网站建设,佛山做企业网站的公司,网站建设作业多少钱Python MySQL关系映射实战#xff1a;手把手搞定一对多与多对多建模 文章目录Python MySQL关系映射实战#xff1a;手把手搞定一对多与多对多建模学习开场#xff1a;为什么关系映射是Python开发者的必修课#xff1f;环境准备#xff1a;搭建你的Python MySQL开发环境1. …Python MySQL关系映射实战手把手搞定一对多与多对多建模文章目录Python MySQL关系映射实战手把手搞定一对多与多对多建模学习开场为什么关系映射是Python开发者的必修课环境准备搭建你的Python MySQL开发环境1. 安装必要的包2. 准备MySQL数据库3. 基础连接测试基础概念理解关系映射的核心思想什么是关系映射三种基本关系类型为什么需要外键和关联表实战演练一一对多关系用户-订单场景描述数据库表设计用SQLAlchemy定义模型插入测试数据查询关系数据避免N1查询问题实战演练二多对多关系文章-标签场景描述数据库表设计用SQLAlchemy定义多对多关系多对多数据操作应用场景在实际项目中的最佳实践场景1电商系统用户订单管理场景2博客系统标签云和文章筛选性能优化建议学习总结关键要点回顾常见错误和解决方法学习交流与进阶刚开始用Python操作MySQL时我也被复杂的表关系搞得头大。明明业务逻辑很简单一到数据库设计就卡壳用户和订单怎么关联文章和标签怎么设计直到我真正理解了关系映射的核心思想才发现原来这么简单。今天我就带你从零开始30分钟搞定一对多和多对多的实战建模。学习开场为什么关系映射是Python开发者的必修课如果你正在用Python开发Web应用、数据分析系统或任何需要存储数据的项目几乎一定会遇到这样的场景一个用户有多个订单怎么设计数据库表一篇文章可以有多个标签一个标签也能对应多篇文章这种多对多关系怎么实现查询用户信息时如何同时获取他的所有订单数据这些问题背后都是关系映射在发挥作用。关系映射是数据库设计的核心思想它决定了你的数据如何组织、如何查询、如何维护数据一致性。我刚开始学习时最大的困惑是明明在Python里用列表、字典就能轻松表示的数据关系到了MySQL里怎么就变得这么复杂后来我才明白数据库有自己的一套规则而关系映射就是连接Python对象思维和数据库表结构思维的桥梁。学完这篇教程你将掌握理解一对多、多对多关系的本质区别用SQLAlchemy ORM在Python中优雅地定义这些关系掌握关联查询的多种写法避免N1查询问题在实际项目中应用关系映射提升代码可维护性环境准备搭建你的Python MySQL开发环境1. 安装必要的包我们先从最基础的开始。打开你的终端执行以下命令# 创建虚拟环境推荐python-mvenvmysql_venvsourcemysql_venv/bin/activate# Linux/Mac# 或 mysql_venv\Scripts\activate # Windows# 安装核心包pipinstallsqlalchemypymysqlmysql-connector-python# 可选安装Flask-SQLAlchemy如果你做Web开发pipinstallflask-sqlalchemy2. 准备MySQL数据库确保你的MySQL服务正在运行然后创建一个测试数据库-- 登录MySQLmysql-uroot-p-- 创建数据库CREATEDATABASErelationship_demoCHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ci;-- 创建用户并授权生产环境建议使用CREATEUSERdemo_userlocalhostIDENTIFIEDBYdemo_password;GRANTALLPRIVILEGESONrelationship_demo.*TOdemo_userlocalhost;FLUSHPRIVILEGES;3. 基础连接测试创建一个简单的Python脚本来测试连接# test_connection.pyimportpymysqlfromsqlalchemyimportcreate_engine# 方法1使用pymysql直接连接deftest_pymysql():try:connectionpymysql.connect(hostlocalhost,userroot,# 或用上面创建的demo_userpassword你的密码,databaserelationship_demo,charsetutf8mb4,cursorclasspymysql.cursors.DictCursor)print(✅ pymysql连接成功)connection.close()exceptExceptionase:print(f❌ 连接失败:{e})# 方法2使用SQLAlchemy引擎deftest_sqlalchemy():try:# 连接字符串格式mysqlpymysql://用户名:密码主机/数据库名enginecreate_engine(mysqlpymysql://root:你的密码localhost/relationship_demo)withengine.connect()asconn:print(✅ SQLAlchemy连接成功)exceptExceptionase:print(f❌ SQLAlchemy连接失败:{e})if__name____main__:test_pymysql()test_sqlalchemy()运行这个脚本确保连接正常。如果遇到问题通常是密码错误、MySQL服务没启动或权限问题。基础概念理解关系映射的核心思想什么是关系映射简单来说关系映射就是把现实世界中的对象之间的关系映射到数据库表之间的关系。在Python中我们习惯用对象和对象属性来思考在MySQL中我们用表和表之间的外键来思考。三种基本关系类型在数据库设计中主要有三种关系一对一一个A对应一个B一个B对应一个A如用户和用户详情一对多一个A对应多个B一个B只对应一个A如用户和订单多对多一个A对应多个B一个B也对应多个A如文章和标签今天我们先重点学习最常用的一对多和多对多。为什么需要外键和关联表我刚开始学习时总想用简单的方式绕过这些概念。比如把多个订单ID用逗号拼接存在用户表里。但这样会带来很多问题# ❌ 错误做法把订单ID拼接到一个字段里user_data{id:1,name:张三,order_ids:1,3,5,7# 这样存储会有很多问题}# 问题1查询某个订单的用户需要全表扫描# 问题2删除订单时无法自动清理关联# 问题3无法保证订单ID的真实存在数据不一致# 问题4无法添加订单的额外信息如购买时间、数量等正确的做法是使用外键约束让数据库帮我们维护数据的一致性。实战演练一一对多关系用户-订单场景描述假设我们正在开发一个电商系统最核心的关系就是用户和订单一个用户可以创建多个订单一个订单只属于一个用户这是典型的一对多关系。数据库表设计erDiagram users ||--o{ orders : 拥有 users { int id PK 主键 varchar name 用户名 varchar email 邮箱 datetime created_at 创建时间 } orders { int id PK 主键 int user_id FK 外键关联users.id decimal amount 订单金额 varchar status 订单状态 datetime created_at 创建时间 }用SQLAlchemy定义模型现在让我们用Python代码来实现这个关系# one_to_many_demo.pyfromsqlalchemyimportcreate_engine,Column,Integer,String,DateTime,DECIMAL,ForeignKeyfromsqlalchemy.ext.declarativeimportdeclarative_basefromsqlalchemy.ormimportrelationship,sessionmakerfromdatetimeimportdatetime# 创建基类Basedeclarative_base()# 定义User模型一的一方classUser(Base):__tablename__usersidColumn(Integer,primary_keyTrue)nameColumn(String(50),nullableFalse)emailColumn(String(100),uniqueTrue,nullableFalse)created_atColumn(DateTime,defaultdatetime.now)# 关键定义关系# relationship参数说明# Order关联的模型类名# backrefuser在Order模型中创建一个user属性可以通过order.user访问用户# lazydynamic延迟加载返回查询对象而不是直接加载所有数据ordersrelationship(Order,backrefuser,lazydynamic)def__repr__(self):returnfUser(id{self.id}, name{self.name}, email{self.email})# 定义Order模型多的一方classOrder(Base):__tablename__ordersidColumn(Integer,primary_keyTrue)user_idColumn(Integer,ForeignKey(users.id),nullableFalse)# 外键约束amountColumn(DECIMAL(10,2),nullableFalse)# 总金额10位整数2位小数statusColumn(String(20),defaultpending)# 订单状态created_atColumn(DateTime,defaultdatetime.now)def__repr__(self):returnfOrder(id{self.id}, user_id{self.user_id}, amount{self.amount})# 创建数据库连接和表enginecreate_engine(mysqlpymysql://root:你的密码localhost/relationship_demo)Base.metadata.create_all(engine)# 创建表# 创建会话Sessionsessionmaker(bindengine)sessionSession()print(✅ 数据库表创建成功)运行这个脚本检查数据库你会发现自动创建了两个表并且orders表有外键约束。插入测试数据# 插入测试数据defcreate_test_data():# 创建用户user1User(name张三,emailzhangsanexample.com)user2User(name李四,emaillisiexample.com)session.add_all([user1,user2])session.commit()# 提交后user1和user2才有idprint(f创建用户:{user1},{user2})# 为张三创建3个订单order1Order(user_iduser1.id,amount100.50,statuspaid)order2Order(user_iduser1.id,amount200.00,statusshipped)order3Order(user_iduser1.id,amount50.25,statuspending)# 为李四创建1个订单order4Order(user_iduser2.id,amount300.75,statuspaid)session.add_all([order1,order2,order3,order4])session.commit()print(✅ 测试数据创建完成)returnuser1,user2# 执行userscreate_test_data()查询关系数据这才是关系映射最强大的地方看看如何轻松查询关联数据defquery_demo():print(\n 一对多关系查询演示 \n)# 1. 查询用户的所有订单从一查多usersession.query(User).filter_by(name张三).first()print(f1. 用户{user.name}的所有订单:)# 注意我们在User模型中定义了orders关系并且设置了lazydynamic# 所以user.orders返回的是一个查询对象可以继续过滤fororderinuser.orders.all():# 需要调用.all()获取结果print(f - 订单ID:{order.id}, 金额:{order.amount}, 状态:{order.status})# 2. 查询订单所属的用户从多查一ordersession.query(Order).filter_by(amount200.00).first()print(f\n2. 订单{order.id}属于用户:{order.user.name})# 通过backref访问# 3. 条件查询查询张三所有已支付的订单print(f\n3. 张三已支付的订单:)paid_ordersuser.orders.filter_by(statuspaid).all()fororderinpaid_orders:print(f - 订单ID:{order.id}, 金额:{order.amount})# 4. 统计每个用户的订单数量print(\n4. 用户订单统计:)all_userssession.query(User).all()foruinall_users:countu.orders.count()# 使用count()方法避免加载所有数据print(f -{u.name}:{count}个订单)query_demo()避免N1查询问题这是初学者最容易踩的坑看看什么是N1问题defn_plus_one_problem():演示N1查询问题print(\n N1查询问题演示 \n)# ❌ 错误做法会产生N1次查询print(❌ 错误做法N1查询:)userssession.query(User).all()foruserinusers:# 每次循环都会执行一次查询ordersuser.orders.all()# 这里会执行单独的查询print(f{user.name}有{len(orders)}个订单)# ✅ 正确做法使用join一次性加载所有数据print(\n✅ 正确做法使用join:)fromsqlalchemy.ormimportjoinedload# 方法1使用joinedloaduserssession.query(User).options(joinedload(User.orders)).all()foruserinusers:# 现在user.orders已经在第一次查询时加载了print(f{user.name}有{len(user.orders.all())}个订单)# 方法2直接使用join更灵活print(\n✅ 使用join查询可以添加过滤条件:)resultsession.query(User,Order).join(Order,User.idOrder.user_id).all()foruser,orderinresult:print(f{user.name}- 订单{order.id}:{order.amount})# 注意在实际项目中可以使用SQLAlchemy的echoTrue查看执行的SQL语句# engine create_engine(mysqlpymysql://..., echoTrue)实战演练二多对多关系文章-标签场景描述现在考虑一个博客系统一篇文章可以有多个标签如Python、MySQL、教程一个标签可以对应多篇文章这是典型的多对多关系。数据库表设计多对多关系需要一个关联表junction table来连接两个主表erDiagram articles ||--o{ article_tags : 拥有 tags ||--o{ article_tags : 拥有 articles { int id PK varchar title text content datetime created_at } tags { int id PK varchar name } article_tags { int article_id FK int tag_id FK datetime created_at }用SQLAlchemy定义多对多关系# many_to_many_demo.pyfromsqlalchemyimportTable,Column,Integer,String,Text,DateTime,ForeignKeyfromsqlalchemy.ormimportrelationshipfromdatetimeimportdatetime# 先定义关联表注意这不是模型类是普通的Table对象# 关联表通常只包含外键和可能的额外字段如创建时间article_tagTable(article_tags,Base.metadata,Column(article_id,Integer,ForeignKey(articles.id),primary_keyTrue),Column(tag_id,Integer,ForeignKey(tags.id),primary_keyTrue),Column(created_at,DateTime,defaultdatetime.now))# 定义Article模型classArticle(Base):__tablename__articlesidColumn(Integer,primary_keyTrue)titleColumn(String(200),nullableFalse)contentColumn(Text)created_atColumn(DateTime,defaultdatetime.now)# 多对多关系定义# secondary参数指定关联表# lazydynamic可以改为subquery或select根据需求选择tagsrelationship(Tag,secondaryarticle_tag,backrefarticles,lazydynamic)# 使用dynamic可以继续过滤def__repr__(self):returnfArticle(id{self.id}, title{self.title[:20]}...)# 定义Tag模型classTag(Base):__tablename__tagsidColumn(Integer,primary_keyTrue)nameColumn(String(50),uniqueTrue,nullableFalse)def__repr__(self):returnfTag(id{self.id}, name{self.name})# 创建表Base.metadata.create_all(engine)print(✅ 多对多关系表创建成功)多对多数据操作defmany_to_many_operations():print(\n 多对多关系操作演示 \n)# 1. 创建标签python_tagTag(namePython)mysql_tagTag(nameMySQL)tutorial_tagTag(name教程)web_tagTag(nameWeb开发)session.add_all([python_tag,mysql_tag,tutorial_tag,web_tag])session.commit()# 2. 创建文章并关联标签article1Article(titlePython MySQL入门教程,content这是一篇关于如何使用Python操作MySQL的教程...)# 添加标签到文章article1.tags.append(python_tag)article1.tags.append(mysql_tag)article1.tags.append(tutorial_tag)article2Article(titleSQLAlchemy高级用法,content深入讲解SQLAlchemy的关系映射和查询优化...)article2.tags.append(python_tag)article2.tags.append(web_tag)session.add_all([article1,article2])session.commit()print(✅ 测试数据创建完成)# 3. 查询获取文章的所有标签print(\n1. 查询文章的所有标签:)articlesession.query(Article).filter_by(titlePython MySQL入门教程).first()print(f文章:{article.title})print(标签:,[tag.namefortaginarticle.tags.all()])# 4. 查询获取标签的所有文章print(\n2. 查询标签的所有文章:)tagsession.query(Tag).filter_by(namePython).first()print(f标签{tag.name}关联的文章:)forarticleintag.articles:print(f -{article.title})# 5. 为现有文章添加新标签print(\n3. 为文章添加新标签:)articlesession.query(Article).filter_by(titleSQLAlchemy高级用法).first()article.tags.append(tutorial_tag)# 添加教程标签session.commit()print(f添加后标签:{[tag.namefortaginarticle.tags.all()]})# 6. 移除文章的某个标签print(\n4. 移除文章的标签:)article.tags.remove(mysql_tag)# 如果存在则移除session.commit()print(f移除后标签:{[tag.namefortaginarticle.tags.all()]})# 7. 复杂查询查询同时有Python和MySQL标签的文章print(\n5. 复杂查询同时有Python和MySQL标签的文章)fromsqlalchemyimportand_resultsession.query(Article).join(Article.tags).filter(and_(Tag.namePython,Article.id.in_(session.query(Article.id).join(Article.tags).filter(Tag.nameMySQL)))).all()print(结果:,[article.titleforarticleinresult])many_to_many_operations()应用场景在实际项目中的最佳实践场景1电商系统用户订单管理# 实际项目中的用户订单查询defget_user_orders_with_details(user_id,page1,per_page10):获取用户订单列表带分页和详细信息fromsqlalchemy.ormimportcontains_eager# 使用join一次性加载所有需要的数据避免N1查询querysession.query(Order).join(Order.user).filter(User.iduser_id)# 添加排序和分页ordersquery.order_by(Order.created_at.desc())\.offset((page-1)*per_page)\.limit(per_page)\.all()# 统计总数用于分页totalquery.count()return{orders:orders,total:total,page:page,per_page:per_page,total_pages:(totalper_page-1)//per_page}# 使用示例user_ordersget_user_orders_with_details(1,page1,per_page5)print(f用户订单:{len(user_orders[orders])}条总共{user_orders[total]}条)场景2博客系统标签云和文章筛选# 标签云和文章筛选defget_tag_cloud(limit20):获取热门标签云fromsqlalchemyimportfunc# 查询每个标签的文章数量tag_countssession.query(Tag.name,func.count(article_tag.c.article_id).label(article_count)).join(article_tag).group_by(Tag.id).order_by(func.count(article_tag.c.article_id).desc()).limit(limit).all()return[{name:name,count:count}forname,countintag_counts]defget_articles_by_tags(tag_names,page1,per_page10):根据多个标签筛选文章# 查找包含所有指定标签的文章subquerysession.query(article_tag.c.article_id)fortag_nameintag_names:subquerysubquery.join(Tag).filter(Tag.nametag_name)article_ids[row[0]forrowinsubquery.distinct().all()]# 获取文章详情articlessession.query(Article).filter(Article.id.in_(article_ids)).order_by(Article.created_at.desc())\.offset((page-1)*per_page)\.limit(per_page).all()returnarticles# 使用示例print(热门标签云:,get_tag_cloud(5))print(Python和MySQL标签的文章:,get_articles_by_tags([Python,MySQL]))性能优化建议加载策略执行查询数内存占用适用场景代码示例lazyselect (默认)N1低不确定是否需要关联数据user.orders(首次访问时查询)lazyjoined1高总是需要关联数据query.options(joinedload(User.orders))lazysubquery2中分页查询关联数据query.options(subqueryload(User.orders))lazydynamic1N过滤时低需要对关联数据进一步过滤user.orders.filter_by(statuspaid)# 根据场景选择合适的加载策略defoptimize_loading_strategy():演示不同加载策略的选择# 场景1总是需要用户的所有订单# ✅ 使用joinedload一次查询搞定userssession.query(User).options(joinedload(User.orders)).all()# 场景2只需要用户信息不确定是否需要订单# ✅ 使用默认的lazyselect按需加载userssession.query(User).all()# ... 后续逻辑中如果需要订单再访问 user.orders# 场景3需要对用户的订单进行复杂过滤# ✅ 使用dynamic返回查询对象usersession.query(User).first()recent_ordersuser.orders.filter(Order.created_at2024-01-01).order_by(Order.amount.desc()).all()学习总结关键要点回顾通过今天的学习你应该掌握了一对多关系使用外键和relationship()定义通过backref实现双向访问多对多关系需要关联表使用secondary参数指定查询优化避免N1查询合理使用joinedload、subqueryload实际应用根据业务场景选择合适的关系设计和加载策略我刚开始学习时最大的收获是理解了关系映射的本质是建立数据之间的连接。不要害怕外键和关联表它们是你的朋友能帮你保证数据的一致性。常见错误和解决方法外键约束错误确保先创建父记录如用户再创建子记录如订单循环导入模型类之间相互引用时使用字符串形式Order而不是直接引用类会话管理记得及时commit和close会话避免连接泄露性能问题使用echoTrue查看生成的SQL优化查询语句学习交流与进阶恭喜你完成了Python MySQL关系映射的实战学习现在你已经掌握了数据库设计的核心技能之一。我特别想听听你的学习体验你在实际项目中遇到过哪些关系映射的难题运行示例代码时有没有遇到什么错误对于一对多和多对多的区别还有什么疑问我会认真阅读每一条留言并为初学者提供针对性的解答。记住数据库学习最好的方式就是多实践、多踩坑、多总结。推荐学习资源SQLAlchemy官方文档 - 关系教程 - 最权威的参考资料《Python数据库编程实战》 - 系统学习Python操作各种数据库MySQL官方文档 - 外键约束 - 理解数据库层面的约束下篇预告下一篇将分享《Python MySQL连接池实战用SQLAlchemy解决高并发下的连接瓶颈》带你彻底搞懂SQLAlchemy连接池让你告别连接超时和性能瓶颈最后的小建议数据库设计就像搭积木开始可能觉得复杂但一旦掌握了基本模式就能组合出各种强大的数据结构。今天学完一定要动手实践创建一个自己的小项目如博客系统、TODO应用把一对多和多对多关系都用上。遇到问题不要怕这正是成长的机会你的下一步行动✅ 运行今天的所有示例代码 修改代码尝试不同的关系配置 应用到自己的项目中 在评论区分享你的学习心得或问题期待看到你的实践成果
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

宽屏企业网站源码服务周到的做网站

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 设计一个智能窗帘控制系统,使用SG90舵机作为执行器。要求:1.通过光敏电阻检测环境亮度 2.当光线强度超过阈值时自动打开窗帘(舵机转90度) 3.低于阈值时自动关…

张小明 2026/1/10 6:15:49 网站建设

苏州实力做网站公司有哪些wordpress调整上传文件

如何让老旧的 elasticsearch-head 起死回生?一次关于响应延迟的深度调优实践 你有没有遇到过这样的场景:本地搭了个 Elasticsearch 用于开发调试,想快速看看索引分布和分片状态,于是顺手启了 elasticsearch-head ——结果页面加…

张小明 2026/1/10 6:15:51 网站建设

网站建设的系统分析找简历的网站

如何在Vivado中正确导入外部VHDL文件?一文讲透工程集成全流程你有没有遇到过这种情况:辛辛苦苦写好的VHDL模块,复制到Vivado工程里却“看不见”?综合时报错“Entity not found”,仿真时信号全红,折腾半天才…

张小明 2026/1/9 17:39:29 网站建设

网站建设实习周记做外贸通常用哪些网站

首先先看看 hashmap 在 jdk1.8 下扩容的核心方法在 JDK 1.8 的 HashMap 源码中,已经找不到 transfer 这个方法了。JDK 1.8 将扩容逻辑全部整合到了 resize() 方法中。而且,为了配合新的“尾插法”和“位运算”优化,这段代码的逻辑发生了翻天覆…

张小明 2026/1/10 6:15:51 网站建设

汕头网站外包计算机网站开发与技术专业介绍

一、工具核心特性与基础准备这款字幕提取工具的核心优势在于 “轻量化 高适配性”,无需下载客户端,仅通过网页端即可完成全部操作,兼容 Windows、MacOS 桌面系统及 iOS、Android 移动设备,无需配置复杂运行环境,零基础…

张小明 2026/1/10 5:13:33 网站建设

手机 字体 wordpress宁德seo推广

还在为超星网课的手动操作而烦恼吗?🤔 视频任务点刷不完、学习资源下载太繁琐、学习次数统计不准——这些困扰在线学习者的难题,现在有了完美的自动化解决方案!本文将为你揭秘如何用chaoxing_tool这款神器,轻松搞定超星…

张小明 2026/1/10 8:37:43 网站建设