在Django中,ForeignKey
、OneToOneField
和 ManyToManyField
是用于定义模型之间关系的字段类型。
ForeignKey
ForeignKey
用于定义多对一的关系。例如,一个Employee可以属于一个Department,一个Department可以有多个Employee。
python
from django.db import models
class Department(models.Model):
name = models.CharField(max_length=100)
class Employee(models.Model):
name = models.CharField(max_length=100)
department = models.ForeignKey(
Department,
on_delete=models.CASCADE, # 当 Department 被删除时,级联删除关联的 Employee
related_name='employees', # 反向关系的名称,可以通过 department.employees.all() 获取所有关联的 Employee
related_query_name='employee', # 反向关系的查询名称,可以通过 Department.objects.filter(employee__name='John') 查询
limit_choices_to={'name__icontains': 'Engineering'}, # 限制可选的 Department 对象
db_constraint=True, # 是否在数据库中创建外键约束,默认为 True
swappable=True, # 是否允许模型在 INSTALLED_APPS 中被替换,默认为 True
verbose_name='Department', # 字段的可读名称
help_text='Select the department for the employee', # 帮助文本
db_index=True # 是否在数据库中为该字段创建索引,默认为 True
)
position = models.CharField(max_length=100, default='Employee')
# 示例数据
engineering = Department.objects.create(name='Engineering')
hr = Department.objects.create(name='Human Resources')
# 创建 Employee 对象
john = Employee.objects.create(name='John Doe', department=engineering)
jane = Employee.objects.create(name='Jane Smith', department=hr)
# 通过反向关系获取所有属于 Engineering 部门的员工
engineering_employees = engineering.employees.all()
# 通过反向查询获取名字为 John 的员工
john_employees = Department.objects.filter(employee__name='John')
to
: 这里是Department
模型,表示Employee
关联到Department
。on_delete=models.CASCADE
: 当Department
被删除时,级联删除关联的Employee
。related_name='employees'
: 通过department.employees.all()
可以获取所有关联的Employee
。related_query_name='employee'
: 通过Department.objects.filter(employee__name='John')
可以查询关联的Employee
。limit_choices_to={'name__icontains': 'Engineering'}
: 仅允许选择名称包含 "Engineering" 的Department
对象。db_constraint=True
: 在数据库中创建外键约束。swappable=True
: 允许模型在INSTALLED_APPS
中被替换。verbose_name='Department'
: 字段的可读名称。help_text='Select the department for the employee'
: 帮助文本。db_index=True
: 在数据库中为该字段创建索引。
OneToOneField
OneToOneField
用于定义一对一的关系。例如,一个用户可以有一个用户配置文件。
python
from django.db import models
class User(models.Model):
username = models.CharField(max_length=100)
class UserProfile(models.Model):
user = models.OneToOneField(
User,
on_delete=models.CASCADE, # 当 User 被删除时,级联删除关联的 UserProfile
related_name='profile', # 反向关系的名称,可以通过 user.profile 获取关联的 UserProfile
related_query_name='profile', # 反向关系的查询名称,可以通过 User.objects.filter(profile__bio='Developer') 查询
limit_choices_to={'username__icontains': 'admin'}, # 限制可选的 User 对象
db_constraint=True, # 是否在数据库中创建外键约束,默认为 True
swappable=True, # 是否允许模型在 INSTALLED_APPS 中被替换,默认为 True
primary_key=False, # 是否将该字段设置为主键,默认为 False
verbose_name='User', # 字段的可读名称
help_text='Select the user for the profile', # 帮助文本
db_index=True # 是否在数据库中为该字段创建索引,默认为 True
)
bio = models.TextField()
# 示例数据
user1 = User.objects.create(username='admin_user')
user2 = User.objects.create(username='regular_user')
# 创建 UserProfile 对象
profile1 = UserProfile.objects.create(user=user1, bio='Administrator')
profile2 = UserProfile.objects.create(user=user2, bio='Regular User')
# 通过反向关系获取 user1 的 UserProfile
admin_profile = user1.profile
# 通过反向查询获取 bio 为 'Administrator' 的用户
admin_users = User.objects.filter(profile__bio='Administrator')
to
: 这里是User
模型,表示UserProfile
关联到User
。on_delete=models.CASCADE
: 当User
被删除时,级联删除关联的UserProfile
。related_name='profile'
: 通过user.profile
可以获取关联的UserProfile
。related_query_name='profile'
: 通过User.objects.filter(profile__bio='Developer')
可以查询关联的UserProfile
。limit_choices_to={'username__icontains': 'admin'}
: 仅允许选择用户名包含 "admin" 的User
对象。db_constraint=True
: 在数据库中创建外键约束。swappable=True
: 允许模型在INSTALLED_APPS
中被替换。primary_key=False
: 不将该字段设置为主键。verbose_name='User'
: 字段的可读名称。help_text='Select the user for the profile'
: 帮助文本。db_index=True
: 在数据库中为该字段创建索引。
ManyToManyField
ManyToManyField
用于定义多对多的关系。例如,一个学生可以选修多门课程,一门课程可以有多个学生选修。
python
from django.db import models
class Course(models.Model):
name = models.CharField(max_length=100)
class Student(models.Model):
name = models.CharField(max_length=100)
courses = models.ManyToManyField(
Course,
related_name='students', # 反向关系的名称,可以通过 course.students.all() 获取所有关联的 Student
related_query_name='student', # 反向关系的查询名称,可以通过 Course.objects.filter(student__name='John') 查询
limit_choices_to={'name__icontains': 'Math'}, # 限制可选的 Course 对象
db_table='student_courses', # 自定义中间表的名称
db_constraint=True, # 是否在数据库中创建外键约束,默认为 True
swappable=True, # 是否允许模型在 INSTALLED_APPS 中被替换,默认为 True
verbose_name='Courses', # 字段的可读名称
help_text='Select the courses for the student', # 帮助文本
symmetrical=False, # 是否为对称关系,默认为 True。通常在自引用多对多关系中使用
through=None, # 自定义中间模型
through_fields=None, # 指定中间模型的字段
)
# 示例数据
math_course = Course.objects.create(name='Mathematics')
science_course = Course.objects.create(name='Science')
# 创建 Student 对象
john = Student.objects.create(name='John Doe')
jane = Student.objects.create(name='Jane Smith')
# 关联课程
john.courses.add(math_course)
jane.courses.add(math_course, science_course)
# 通过反向关系获取所有选修 Mathematics 课程的学生
math_students = math_course.students.all()
# 通过反向查询获取名字为 John 的学生
john_students = Course.objects.filter(student__name='John')
to
: 这里是Course
模型,表示Student
关联到Course
。related_name='students'
: 通过course.students.all()
可以获取所有关联的Student
。related_query_name='student'
: 通过Course.objects.filter(student__name='John')
可以查询关联的Student
。limit_choices_to={'name__icontains': 'Math'}
: 仅允许选择名称包含 "Math" 的Course
对象。db_table='student_courses'
: 自定义中间表的名称。db_constraint=True
: 在数据库中创建外键约束。swappable=True
: 允许模型在INSTALLED_APPS
中被替换。verbose_name='Courses'
: 字段的可读名称。help_text='Select the courses for the student'
: 帮助文本。symmetrical=False
: 这里设置为False
,因为这是一个非对称关系(学生和课程的关系不是对称的)。through=None
: 不使用自定义中间模型。through_fields=None
: 不指定中间模型的字段。