当前位置: 首页 > article >正文

【后端】【Django DRF】Django ORM 详解:一对一、一对多、多对多

Django ORM 详解:一对一、一对多、多对多

在 Django 的 ORM(对象关系映射)中,数据库的表之间通常需要建立关联关系。最常见的三种关系是:

  • 一对一(OneToOneField):一个对象只能对应另一个对象,例如 一个用户只能有一个个人资料
  • 一对多(ForeignKey):一个对象可以关联多个对象,但多个对象只能属于同一个,例如 一个作者可以写多本书,但一本书只能有一个作者。
  • 多对多(ManyToManyField):多个对象可以相互关联,例如 一个学生可以选多门课程,一门课程也可以有多个学生

本文将以 循序渐进、通俗易懂 的方式,详细讲解 Django ORM 中如何使用 一对一、一对多、多对多 关系,并结合 代码示例和数据表结构 帮助你理解。


1. 一对一关系(OneToOneField)

什么是一对一?

一对一(1:1)关系,即 一个对象只能关联另一个对象,不能再关联其他对象。例如:

  • 一个用户 只能有 一个个人资料,反过来也一样。
  • 一个国家 只能有 一个首都,不能有多个。

模型设计

假设我们要管理用户的个人资料,每个用户只能对应一个个人资料,我们可以这样设计模型:

from django.db import models
from django.contrib.auth.models import User  # 导入 Django 自带的用户模型

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)  # 一对一关系
    phone = models.CharField(max_length=15, blank=True, null=True)
    address = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.user.username

解释

  • OneToOneField(User, on_delete=models.CASCADE)Profile 关联 User,每个 User 只能有一个 Profile
  • on_delete=models.CASCADE:如果 User 被删除,Profile 也会被删除。

数据库表结构

Django 在 Profile 表中添加了 user_id 外键,并加上了 唯一约束

CREATE TABLE Profile (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER UNIQUE NOT NULL,  -- 唯一外键,确保一对一关系
    phone VARCHAR(15),
    address TEXT,
    FOREIGN KEY (user_id) REFERENCES auth_user(id) ON DELETE CASCADE
);

如何使用

创建数据
user = User.objects.create(username="john_doe")  # 创建用户
profile = Profile.objects.create(user=user, phone="123456789", address="New York")  # 关联个人资料
查询数据
# 通过 user 获取 profile
user.profile.address  

# 通过 profile 获取 user
profile.user.username  
删除数据
user.delete()  # 删除用户时,Profile 也会被删除

2. 一对多关系(ForeignKey)

什么是一对多?

一对多(1:N)关系,即 一个对象可以关联多个对象,但 多个对象只能属于一个对象。例如:

  • 一个作者可以写多本书,但一本书只能有一个作者。
  • 一个公司有多个员工,但一个员工只能属于一个公司。

模型设计

假设我们要管理作者和书籍,每个作者可以写多本书:

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

    def __str__(self):
        return self.name

class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="books")  # 一对多关系

    def __str__(self):
        return self.title

解释

  • ForeignKey(Author, on_delete=models.CASCADE)Book 通过外键 author 关联 Author
  • related_name="books":这样 author.books.all() 可以直接获取该作者的所有书籍。
  • on_delete=models.CASCADE:如果 Author 被删除,所有他的 Book 也会被删除。

数据库表结构

Django 在 Book 表中添加 author_id 外键:

CREATE TABLE Book (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title VARCHAR(200),
    author_id INTEGER NOT NULL,  -- 外键
    FOREIGN KEY (author_id) REFERENCES Author(id) ON DELETE CASCADE
);

如何使用

创建数据
author = Author.objects.create(name="J.K. Rowling")
book1 = Book.objects.create(title="Harry Potter 1", author=author)
book2 = Book.objects.create(title="Harry Potter 2", author=author)
查询数据
# 获取作者的所有书籍
author.books.all()

# 获取某本书的作者
book1.author.name

3. 多对多关系(ManyToManyField)

什么是多对多?

多对多(M:N)关系,即 多个对象可以关联多个对象。例如:

  • 一个学生可以选多门课程,一门课程也可以有多个学生
  • 一个用户可以加入多个群聊,一个群聊也可以有多个用户

方法 1:Django 自动创建中间表

Django 可以 自动创建中间表 来管理多对多关系:

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

    def __str__(self):
        return self.name

class Course(models.Model):
    title = models.CharField(max_length=200)
    students = models.ManyToManyField(Student, related_name="courses")  # 多对多关系

    def __str__(self):
        return self.title

自动生成的中间表

Django 自动创建 一个 隐藏的中间表

CREATE TABLE course_students (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    student_id INTEGER NOT NULL,
    course_id INTEGER NOT NULL,
    FOREIGN KEY (student_id) REFERENCES Student(id),
    FOREIGN KEY (course_id) REFERENCES Course(id)
);

如何使用

添加关系
student1 = Student.objects.create(name="Alice")
course1 = Course.objects.create(title="Math")

course1.students.add(student1)
查询数据
# 获取 Alice 选修的课程
student1.courses.all()

# 获取选修 Math 课程的所有学生
course1.students.all()

方法 2:手动定义中间表

ManyToManyField 需要存储额外信息(如选课时间、成绩)时,需要手动创建中间表:

class Enrollment(models.Model):
    student = models.ForeignKey(Student, on_delete=models.CASCADE)
    course = models.ForeignKey(Course, on_delete=models.CASCADE)
    enrolled_at = models.DateTimeField(auto_now_add=True)  # 选课时间
    grade = models.CharField(max_length=5, blank=True, null=True)  # 选课成绩

查询数据

# 获取学生的选课及成绩
Enrollment.objects.filter(student=student1).values("course__title", "grade")

总结

关系类型适用场景Django ORM 字段
一对一用户 - 个人资料OneToOneField
一对多作者 - 书籍ForeignKey
多对多学生 - 课程ManyToManyField

掌握这些 ORM 关系,可以帮助你更好地设计数据库结构,提高项目的可维护性!🚀


http://www.kler.cn/a/611922.html

相关文章:

  • Windows下Tomcat的下载与安装
  • 单应性矩阵(homography)
  • SpringMVC 拦截器详解
  • 堆的常见应用1
  • 细胞内与细胞间网络整合分析!神经网络+细胞通讯,这个单细胞分析工具一箭双雕了(scTenifoldXct)
  • 【机器学习】——机器学习基础概念
  • python进行数据分析(以A 股为例)
  • uniapp开发中store的基本用法和模块化详解
  • uniapp上传图片之前压缩处理
  • 解构 HarmonyOS:技术神话背后的理性审视
  • 给聊天机器人装“短期记忆“:Flask版实现指南
  • 高级数据结构02AVL树
  • AI编程工具哪家强?对比Cusor、Copilot、Cline
  • C++算法深度解析:快速排序的实现、分析与优化
  • RoMA: 基于Mamba的遥感基础模型, 已开源, 首次验证mamba的scaling能力
  • 用数组遍历出来的页面,随节点创建的ref存储在数据仓库中,如果数据删除,页面相关节点也会删除,数据仓库中随节点创建的ref会不会也同时删除
  • STM32F103C8T6移植DMP解算MPU6050
  • Elasticsearch:使用 Azure AI 文档智能解析 PDF 文本和表格数据
  • linux---------进程概念(完)
  • 字节真题,问a,b,c指的地址是否相同?