django进阶之ORM多表关联增删改查

数据库模型介绍

school 和 class 之间创建的是一对多关系,通过外键对象 sch 关联

userinfo 和 class 之间是多对多的关系,通过 ManyToManyField 创建

1
2
3
4
5
6
7
8
9
10
11
12
class UserInfo(models.Model):
name = models.CharField(max_length=128, null=True)
username=models.CharField(max_length=32, null=True)
password=models.CharField(max_length=32, null=True)

class School(models.Model):
name = models.CharField(max_length=128, null=True, blank=True)

class Class(models.Model):
sch = models.ForeignKey(to='School', default=1)
name = models.CharField(max_length=128, null=True, blank=True)
user = models.ManyToManyField(to='UserInfo')

一对多

以 school 和 class 之间的操进行示例

查询

通过 class 名称得到查询结果,然后通过关联的 sch 进行查询

1
2
3
obj_li = models.Class.objects.filter(name="class 1") #QuerySet list
for obj in obj_li:
print(obj.name, obj.sch.name)

查询结果肯定只有1条,可以通过 first() 直接得到对象,不用循环

1
2
obj = models.Class.objects.filter(name="class 1").first()   #QuertSet
print(obj.name, obj.sch.name)

创建

首先创建 school 对象,得到对应的 id, 然后创建 class ,在创建 class 的时候通过 sch 传入参数

1
2
3
obj = models.School.objects.create(name="aming_go")
class_obj = models.Class.objects.create(name="go_1期", sch=obj)
print(class_obj.sch.name)

删除

1
models.Class.objects.filter(name="class 1").delete()

更新

注意此处的下划线为两个,操作是针对2张表

1
2
models.Class.objects.filter(sch__name="aming_linux").update(name="10期linux")
models.Class.objects.filter(sch__name="aming_linux").delete()

多对多

以 userinfo 和 class 之间的操作进行示例

查询

1
2
3
class_obj = models.Class.objects.filter(name="python_24").first()
for item in class_obj.user.all():
print(item.username, item.name)

多对多的新增、删除、修改都是通过 add() remove() clear() 方法的组合完成
由于操作涉及到3个表,所以肯定需要首先得到两个表的对象,然后再进行操作

创建

add()方法传入的参数2种都可以,分别是 id 或者 *object
新增数据然后关联

1
2
3
class_obj = models.Class.objects.filter(name="python_24").first()
user_obj = models.UserInfo.objects.create(name="多对多测试", username="test")
class_obj.user.add(user_obj.id)

查询数据然后关联

1
2
3
class_obj = models.Class.objects.filter(name="python_24").first()
user_obj = models.UserInfo.objects.filter(name="Bob")
class_obj.user.add(*user_obj)

删除

1
2
3
class_obj = models.Class.objects.filter(name="python_24").first()
user_obj = models.UserInfo.objects.filter(name="Bob")
class_obj.user.remove(*user_obj)

更新

更新操作是首先查询,然后删除(使用 delete 或者 clear 均可),最后增加

1
2
3
4
class_obj = models.Class.objects.filter(name="python_24").first()
user_obj = models.UserInfo.objects.filter(name="Bob")
class_obj.user.clear()
class_obj.user.add(*user_obj)

上述操作都是正向查找,也就是通过主表的信息查询子表,当已知子表的信息查询主表的信息,就是反向查找
下面反向查找

反向查找

查询

1
2
3
user_obj = models.UserInfo.objects.filter(name="Bob").first()
for item in user_obj.class_set.all(): #类名的小写_set
print(item.name)

创建

1
2
3
user_obj = models.UserInfo.objects.filter(name="Bob").first()
class_obj = models.Class.objects.filter(name="go_1期")
user_obj.class_set.add(*class_obj)

删除

1
2
3
user_obj = models.UserInfo.objects.filter(name="Bob").first()
class_obj = models.Class.objects.filter(name="go_1期")
user_obj.class_set.remove(*class_obj)

更新

也是先查询,然后删除,最后增加

反向查找需要使用 类名的小写_set 方式比较麻烦,可以使用 related_name 进行简化

  1. 在 models.py 中添加 related_name 参数
    变更仅涉及 ManyToManyField 的参数

    1
    2
    3
    4
    class Class(models.Model):
    sch = models.ForeignKey(to='School', default=1)
    name = models.CharField(max_length=128, null=True, blank=True)
    user = models.ManyToManyField(to='UserInfo', related_name='caluser')
  2. 更新数据库

    1
    2
    python manage.py makemigrations
    pyton manage.py migrate
  3. 查找示例

    1
    2
    3
    user_obj = models.UserInfo.objects.filter(name="Bob").first()
    for item in user_obj.caluser.all():
    print(item.name)

Recommended Posts