Django ORM – 多表实例(手把手讲解)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

前言:为什么需要掌握 Django ORM 的多表操作?

在 Web 开发中,数据库设计往往是系统架构的核心。Django 的 ORM(对象关系映射)作为其核心特性之一,通过 Python 代码抽象了底层 SQL 的复杂性,让开发者能够更高效地操作数据库。然而,当项目涉及多个表之间的复杂关系时,如何通过 Django ORM 实现多表关联、查询和操作,便成为开发者必须掌握的关键技能。

本文将从基础概念出发,通过具体案例和代码示例,逐步讲解 Django ORM 中多表操作的核心知识点。无论是编程初学者还是有一定经验的开发者,都能通过本文快速理解多表实例的实现逻辑,并掌握如何在实际项目中灵活应用。


一对一关系:像书签一样精准关联

概念与比喻

一对一关系(One-to-One)类似于现实生活中的“身份证与个人信息”的绑定:每个身份证号对应唯一一个人,反之亦然。在 Django 中,这种关系通过 OneToOneField 实现,通常用于扩展用户模型或需要单独存储的关联数据。

示例代码

假设我们需要为用户模型添加详细的个人信息:

from django.db import models  
from django.contrib.auth.models import User  

class UserProfile(models.Model):  
    user = models.OneToOneField(User, on_delete=models.CASCADE)  
    bio = models.TextField(blank=True)  
    birthday = models.DateField(null=True)  

关键点解析

  • on_delete=models.CASCADE:当关联的用户被删除时,自动删除该 UserProfile。
  • 查询示例:通过 user.userprofile 可直接访问关联对象,无需额外查询。

一对多关系:如同图书馆的书籍与作者

概念与比喻

一对多关系(One-to-Many)类似于“作者与书籍”的关系:一个作者可以写多本书,但每本书只能有一个作者。在 Django 中,这种关系通过 ForeignKey 实现,外键字段通常位于“多”的一方(如书籍模型)。

示例代码

以博客系统为例:

class Author(models.Model):  
    name = models.CharField(max_length=100)  

class Article(models.Model):  
    title = models.CharField(max_length=200)  
    content = models.TextField()  
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='articles')  

关键点解析

  • 反向查询:通过 related_name 可以直接通过作者访问其所有文章,例如 author.articles.all()
  • 逆向操作:若删除作者,其所有文章会被级联删除(因 on_delete=models.CASCADE)。

多对多关系:像社交网络的“关注”功能

概念与比喻

多对多关系(Many-to-Many)类似于“用户与关注列表”的关系:用户 A 可以关注多个用户,同时也能被其他用户关注。在 Django 中,这种关系通过 ManyToManyField 实现,默认会自动生成中间表。

示例代码

以电商平台的“用户与收藏商品”为例:

class User(models.Model):  
    username = models.CharField(max_length=50)  

class Product(models.Model):  
    name = models.CharField(max_length=100)  
    price = models.DecimalField(max_digits=10, decimal_places=2)  
    favorites = models.ManyToManyField(User, related_name='favorite_products')  

关键点解析

  • 中间表管理:Django 自动创建 product_favorite 表,存储用户与商品的关联关系。
  • 查询示例
    # 获取用户收藏的所有商品  
    user = User.objects.get(username='Alice')  
    products = user.favorite_products.all()  
    
    # 将商品添加到收藏  
    product = Product.objects.get(name='iPhone 15')  
    product.favorites.add(user)  
    

跨表查询:如何高效获取关联数据?

选择性查询:避免“笛卡尔积”陷阱

当需要同时获取多表数据时,select_related()prefetch_related() 是两个关键方法:

  • select_related:用于一对一或一对多关系,通过 SQL 的 JOIN 操作一次性获取数据。
  • prefetch_related:用于多对多或反向一对多关系,通过两次查询减少数据库压力。

示例代码

articles = Article.objects.select_related('author').all()  
for article in articles:  
    print(article.author.name)  # 不会触发额外查询  

聚合与分组:统计作者的文章总数

Django ORM 支持通过 annotate()Count 实现聚合查询:

from django.db.models import Count  

authors = Author.objects.annotate(total_articles=Count('articles')).order_by('-total_articles')  
for author in authors:  
    print(f"{author.name} 写了 {author.total_articles} 篇文章")  

实战案例:电商系统的订单与用户关系

系统设计需求

假设我们开发一个电商平台,需要实现以下功能:

  1. 用户可以提交订单,每个订单包含多个商品。
  2. 每个商品属于一个分类。

模型设计

class Category(models.Model):  
    name = models.CharField(max_length=50)  

class Product(models.Model):  
    name = models.CharField(max_length=100)  
    price = models.DecimalField(max_digits=10, decimal_places=2)  
    category = models.ForeignKey(Category, on_delete=models.PROTECT)  

class Order(models.Model):  
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)  
    created_at = models.DateTimeField(auto_now_add=True)  

class OrderItem(models.Model):  
    order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items')  
    product = models.ForeignKey(Product, on_delete=models.PROTECT)  
    quantity = models.PositiveIntegerField()  

关键操作示例

  1. 创建订单
user = User.objects.get(username='Bob')  
order = Order.objects.create(user=user)  
product = Product.objects.get(name='Coffee Mug')  
OrderItem.objects.create(order=order, product=product, quantity=2)  
  1. 查询用户所有订单的总金额
from django.db.models import Sum  

total = OrderItem.objects.filter(order__user=user) \  
    .annotate(total_price=F('product__price') * F('quantity')) \  
    .aggregate(Sum('total_price'))['total_price__sum']  

结论:多表实例是 Django 项目的进阶之路

掌握 Django ORM 的多表操作,不仅是提升开发效率的关键,更是构建复杂系统的基础。通过本文的案例和代码示例,读者可以:

  1. 理解一对一、一对多、多对多关系的核心逻辑;
  2. 学会通过 select_relatedprefetch_related 优化查询性能;
  3. 在实际项目中设计合理的模型结构,实现数据关联与复用。

Django ORM 的强大之处在于其简洁性与灵活性,但真正的应用需要开发者结合业务场景不断实践。建议读者通过搭建小型项目(如博客系统或电商应用),逐步巩固多表操作的知识,最终实现从“会用”到“精通”的跨越。

最新发布