• Index

django 一对多

Reads: 808 Edit

参考资料
https://zhuanlan.zhihu.com/p/427308152

一对多

首先来说说一对多,这个关联关系经常用到,多的一方通过models.ForeignKey进行关联。如下示例:

from django.db import models

class Department(models.Model):
    name = models.CharField(max_length=20)
    create_data = models.DateField(auto_now_add=True)
    is_delete = models.BooleanField(default=False)  # default=False,在数据库中表现为0

    class Meta:
    # 这里定义了db_table的话,那么迁移后表名就是department这个了,不会是应用名_类名小写(例如:framework_department)
        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", on_delete=models.CASCADE)
    # department = models.ForeignKey("Department", related_name = 'employees', on_delete=models.CASCADE)  # 加了related_name = 'employee'后,在进行查询一个部门的全部员工时就不用employee_set了,直接使用employee即可。其余方法和使用employee_set一致。

    class Meta:
        db_table = "employee"

以上定义了两个模型,员工和部门是一对多关系,员工属于多的一方,所以使用了models.ForeignKey来与部门进行关联。关联的模型如果是定义在一个py文件里的话,那么可以直接写模型名称即可,例如:Department就可以直接使用,但是如果要关联不在一个py文件里的模型,那么就要通过:应用名.模型名使用(例如:user.User)。

在命令行终端输入以下命令,在MySQ中生成数据表。

python3 manage.py makemigrations 
python3 manage.py migrate

新增数据

新增Department

deparment = Department.objects.create(name="生产部1")

新增Employee

employee = Employee.objects.create(name="小明", age=18, gender=0, salary=8000.50, comment="新入职员工", department=deparment)

新增多个employee

Employee.objects.create(name="小明", age=18, gender=0, salary=8000.50, comment="新入职员工",
department=Department.objects.get(id=4))

Employee.objects.create(name="小张", age=18, gender=0, salary=9000.50, comment="新入职员工",
department=Department.objects.filter(id=4)[0])

更新一个员工所属的部门

Employee.objects.filter(id=1).update(department=5)

这里要注意的是,更新就不用传一个实例对象了,只需要传入部门id即可。传入实例对象会报错。

根据条件删除

删除指定部门下的所有员工

Employee.objects.filter(department=2).delete()

删除员工

Department.objects.filter(id=6).delete()

查询数据

employee = Employee.objects.get(id=4)
employee_belong_department = employee.department
employee_belong_department_name = employee_belong_department.name
print(employee_belong_department)

一个部门的全部员工

department = Department.objects.get(id=1)
all_employee= department.employee_set.all()
或者
all_employee = department.employee_set.values()
或者
all_employee = department.employee_set.values_list()

或者

department = Department.objects.get(id=7)
all_employee2 = department.employees.filter(id__in=[31,32]).all()

使用外键时,一般都会定义一个删除的关联操作。什么意思呢?如下:

department = models.ForeignKey("Department", on_delete=models.CASCADE)

如果一个模型使用了外键。那么在对方那个模型被删掉后,该进行什么样的操作。可以通过on_delete来指定。可以指定的类型如下:

CASCADE:级联操作。如果外键对应的那条数据被删除了,那么这条数据也会被删除。

PROTECT:受保护。即只要这条数据引用了外键的那条数据,那么就不能删除外键的那条数据。如果我们强行删除,Django就会报错。

SET_NULL:设置为空。如果外键的那条数据被删除了,那么在本条数据上就将这个字段设置为空。如果设置这个选项,前提是要指定这个字段可以为空。

SET_DEFAULT:设置默认值。如果外键的那条数据被删除了,那么本条数据上就将这个字段设置为默认值。如果设置这个选项, 前提是要指定这个字段一个默认值 。

SET():如果外键的那条数据被删除了。那么将会获取SET函数中的值来作为这个外键的值。SET函数可以接收一个可以调用的对象(比如函数或者方法),如果是可以调用的对象,那么会将这个对象调用后的结果作为值返回回去,可以不用指定默认值 。

DO_NOTHING:不采取任何行为。一切全看数据库级别的约束。


Comments

Make a comment

www.ultrapower.com ,王硕的博客,专注于研究互联网产品和技术,提供中文精品教程。 本网站与其它任何公司及/或商标无任何形式关联或合作。
  • Index
aaaaa