Django数据关系:一对多、多对多及自关联模型建立与查询详解
本文详细解析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'
以上内容为本文全部,希望对您的学习有所帮助,欢迎支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













