Django表关系与表查询

目录
收起
1、一对多
1.1、新增数据
1.2、更新一个员工所属的部门:
1.3、根据条件删除:
1.4、查询数据
2、多对多
2.1、新增数据
2.2、查询数据
2.3、更新数据
2.4、删除数据
3、自定义多对多表
3.1、新增数据
3.2、查询数据
3.3、删除数据

1、一对多

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

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")
    # department = models.ForeignKey("Department", related_name = 'employee')  # 加了related_name = 'employee'后,在进行查询一个部门的全部员工时就不用employee_set了,直接使用employee即可。其余方法和使用employee_set一致。

    class Meta:
        db_table = "employee"

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

以上都是关于模型的定义和使用,当然,最重要的是使用模型相关方法进行增删查改。

1.1、新增数据

新增Department:

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

新增Employee:

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

当然这样添加会报错:

ValueError: Cannot assign “1”: “Employee.department” must be a “Department” instance.

因为新增employee时,department需要传入一个实例对象,而不是单纯的一个ID。正确添加如下:

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

1.2、更新一个员工所属的部门:

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

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

1.3、根据条件删除:

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

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

1.4、查询数据

一个员工所属的部门:

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

一个部门的全部员工:

department = Department.objects.get(id=1)
all_employee= department.employee_set.all()/a.employee_set.values()/a.employee_set.values_list()

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

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

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

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

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

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

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

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

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

2、多对多

class Student(models.Model):
    name = models.CharField(max_length=16, verbose_name=u'名字')
    age = models.IntegerField(verbose_name=u'年龄')


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

2.1、新增数据

1、首先,多对多关系表在迁移时会生成三张表,虽然我们只定义了两张表,但是由于有ManyToManyField字段存在,会使得第三张表名字为:有ManyToManyField字段的模型名_字段名(例如:club_members)。这第三张表是自动生成的,当然,我们是可以控制这第三张表,稍后会说到

新增student:

Student.objects.create(name="小张", age=19)
Student.objects.create(name="小明", age=18)
Student.objects.create(name="小铭", age=19)
Student.objects.create(name="小林", age=17)

新增club:

Club.objects.create(name="跑步")
Club.objects.create(name="跳远")
Club.objects.create(name="跳高")
Club.objects.create(name="跳河")

club因为存在ManyToManyField字段,所以新增数据时,不能直接将该字段拿来使用

新增club_members:

先查询student数据

student = Student.objects.get(name="小林")

再查询club数据

club = Club.objects.get(name="跑步")

添加到关联表

club.members.add(student)

注意:add()这个方法接收的是一个对象,所以,如果要进行批量添加的话,如下:

students = Student.objects.all()
club = Club.objects.get(name="跑步")
club.members.add(*students)

2.2、查询数据

查询一个社团的全部成员

c = Club.objects.get(name="跑步")
c.members.all()/c.members.values()/c.members.values_list()

查询一个成员的全部社团

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

2.3、更新数据

更新一个club下所有成员名字为1

b=Club.objects.get(name="ww")
b.members.update(name="1")  # 返回更新条数,例如:3

2.4、删除数据

1、ManyToManyField是默认级联删除的,例如,如果要删除所有club下的某个student,那么就很简单了。

club=Club.objects.get(id=1) # 先查club
club.members.filter(name="ss").delete() # 再查student,name字段是关联的Student表的name

返回数据为:(6, {u’framework.Student’: 1, u’framework.Club_members’: 5}),表示Student表删除了一条数据,Club_members表删除了5条数据。如果没有该student,那么返回为(0, {})。从上面可以看出如果使用以上方法不仅会删除Student表中数据,还会删除Club表数据。

2、有时候我们不想删除那么多数据,例如只想删除某个club下的所有数据而不影响Student表中数据,那么可以使用如下方法:

club=Club.objects.get(id=1) # 先查要删除的那个club
club.members.clear() # 调用clear()方法删除所有关于该club的数据

3、有时候我们还想只删除某个club下的某个student数据,那么可以使用如下方法:

club=Club.objects.get(id=2) # 先查club
stu=Student.objects.get(id=2) # 再获取要删除的student
club.members.remove(stu) # 调用remove方法删除

3、自定义多对多表

前面说了多对多会自动创建一张关联表,这张表是可以自定义的。

class Student(models.Model):
    name= models.CharField(max_length=16)
    age = models.IntegerField()


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


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

这种多对多关联是自己定义的第三张关联关系表,所以操作起来会较前面简单。

3.1、新增数据

Membership.objects.create(student_id=1, club_id=1)

因为两个字段都是外键关联,所以操作时需要使用字段名_id的形式进行操作。

3.2、查询数据

查询一个学生所有的club

a=Student.objects.get(id=1)
b=a.membership_set.all()

查询一个club下的所有学生

a=Club.objects.get(id=1)
b=a.membership_set.all()

3.3、删除数据

Membership.objects.filter(student_id=1, club_id=1).delete()

返回值:(1, {u’framework.Membership’: 1})/(0, {u’framework.Membership’: 0})


好啦,文章到这里结束啦,谢谢浏览呀,祝各位看官老爷天天开心!

posted @   Python喵  阅读(116)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示