Django数据关系:一对多、多对多及自关联模型建立与查询详解

沈知远
沈知远
发布时间:2026-10-14| 5人浏览过
原创

本文详细解析Django中三种核心数据关系的建立与查询方法。涵盖一对多模型中外键on_delete选项的设置、related_name的作用及反向查询;多对多模型的ManyToManyField自动建表与手动中间表两种实现方式;以及地区表等自关联模型的应用。通过具体代码示例,展示如何高效构建和维护复杂数据库关系。

一对多模型建立与查询

一对多模型

以员工与部门为例,一个部门包含多名员工,这种一对多关系在Django中如何构建?

实现方式是在“多”的一方添加外键字段。例如在员工模型中直接关联部门模型即可建立联系。

具体代码实现见下方示例(第19行):


class Department(models.Model):
  name = models.CharField(max_length=20)
  create_data = models.DateField(auto_now_add=True)
  is_delete = models.BooleanField(default=False)

  class Meta:
    db_table = "department"


class Employee(models.Model):
  name = models.CharField(max_length=20)
  age = models.IntegerField()
  gender = models.IntegerField(default=0)
  # decimal_place = 2表示两位小数,max_digits表示8个数字,包括小数的两位
  salary = models.DecimalField(max_digits=8,decimal_places=2)
  # null=True 表示可以为空,blank=True表示django后台管理输入这个字段可以为空
  comment = models.CharField(max_length=300,null=True,blank=True)
  hire_data = models.DateField(auto_now_add=True)
  department = models.ForeignKey("Department")

  class Meta:
    db_table = "employee"

扩展知识:

1. 定义外键时需通过on_delete参数指定主表数据删除时,关联表数据的处理策略。Django.db.models模块提供了以下可选常量:

关联属性on_delete选项取值说明

  • models.CASCADE:默认值,执行级联删除,即删除主表数据时同时删除关联的外键数据。

department = models.ForeignKey('Department', on_delete=models.CASCADE)
  • models.PROTECT:保护模式,若存在关联数据则禁止删除主表数据,抛出ProtectedError异常。

department = models.ForeignKey('Department', on_delete=models.PROTECT)
  • models.SET_NULL:删除主表数据后,将外键字段设为NULL。此选项要求外键字段必须允许为空(即设置null=True)。

2. 若关联的模型不在当前应用文件夹的model.py中,引用方式需调整为:


department = models.ForeignKey("(应用文件夹名).Department")

此外,还有一个关键设置需要注意:

当定义外键时指定department = models.ForeignKey("Department",related_name='employee'),通过部门反向查找员工时将使用employee作为属性名。若未设置related_name,Django默认使用类名小写加_set(即employee_set)进行反向查询。

一对多关系的查询操作:

查询某员工所属的部门(返回部门对象):


a = Employee.objects.get(id=1)
b = a.department

查询某部门下的所有员工(返回员工对象集合):


a = Department.objects.get(id=1)
b = a.employee_set.all()

多对多模型建立与查询

多对多模型

以学生与社团为例,一名学生可加入多个社团,一个社团也可包含多名学生。Django中如何建立这种多对多关系?

Django提供两种建立多对多关系的方法。

方法一:


class Student(models.Model):
  name= models.CharField(max_length=16)
  birthday=models.DateField()
class Club(models.Model):
  name= models.CharField(max_length=16)
  members = models.ManyToManyField("Student")

只需在任意一方的模型中添加类似第6行的ManyToManyField字段。Django会自动创建一张中间表来维护两张表之间的多对多关联。

如何进行查询?

1. 查询某社团的所有成员(返回学生对象集合):


c = Club.objects.get(id=1)
c.members.all()

2. 查询某学生的所有社团(返回社团对象集合):


s = Student.objects.filter(id=1)
s.club_set.all() # 类名的小写+_set

方法二:(灵活性更高)

手动创建一张中间表来显式管理关联关系。


class Student(models.Model):
  name= models.CharField(max_length=16)
  birthday=models.DateField()

class Club(models.Model):
  name= models.CharField(max_length=16)

class Membership(models.Model):
  student = models.ForeignKey("Student")
  club = models.ForeignKey("Club")

这种手动建表方式如何查询?

查询某学生加入的所有社团:


a = Student.objects.get(id=1)
b = a.membership_set.all() # 查出来的是对象
for i in b:
  print(i.club.name)

查询某社团的所有学生:


a = Club.objects.get(id=1)
b = a.membership_set.all() # 查出来的是对象
for i in b:
  print(i.student.name)

自关联模型应用

自关联模型

自关联模型指表中的某一列关联了同一表中的另一列。典型应用如地区表:省、市、县数据存储在一张表中,省的parent_id为null,市的parent_id指向所属省的id,县的parent_id指向所属市的id。

代码示例:


class Area(models.Model):  
    name = models.CharField(max_length=20, verbose_name='名称')
    # 自关联(特殊的一对多): 生成的字段名 parent_id
    parent = models.ForeignKey('self', verbose_name='上级行政区划')
    class Meta:
      db_table = 'tb_areas'
      verbose_name = '行政区划'

如何进行查询?

若已知某市(如a市),想查询其所属的省份:


a = Area.objects.get(id=1)
# b就是a市的省份的对象
b = a.parent

若已知某省(如a省),想查询其下辖的所有城市:


a = Area.object.get(id=1)
# b就是a省的全部市的对象
b = a.area_set.all() #类名小写+'_set'

以上内容为本文全部,希望对您的学习有所帮助,欢迎支持本站。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。