14、 Django-多表操作-多个模块的关联-一对多的增删改查- models.ForeignKey()
#多模块关联
-- 关联分类:Django中的三个函数
-- ForeignKey-称为外键:一对多、将字段定义在多的一端中
-- ManyToMnayField:多对多、将字段定义在两端的任意一端中
-- OneToOneField:一对一、将字段定义在任意一端中
如:一对一:
一对多:
多对多:常用
如:
模型models.py
from django.db import models
#1对多 1:N
#用户类型 :用户 -- 1:N
#一种用户类型:可以有多个用户
#一个用户:只属于一个用户类型
#用户类型
class UserTyep(models.Model):
name = models.CharField(max_length=30)
#用户
class User(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField(default=10)
#用户类型的对象user_type
#使用外键ForeignKey关联两个表
#定义外键 :外键写在多的一端 、这里关联用户类型
#语法:关联的表名(模型类名) = models.ForeignKey(绑定的外键模型类, on_delete=models.CASCADE)
#on_delete=models.CASCADE 级联删除:表示当用户类型中的某个字段删除后、是否也要将绑定在用户类型下的用户删除
# user_type = models.ForeignKey(UserTyep, on_delete=models.CASCADE) #级联模式
#user_type = models.ForeignKey(UserTyep, on_delete=models.PROTECT) # 保护模式
# user_type = models.ForeignKey(UserTyep, on_delete=models.SET_NULL, null=True) # 置空模式
# user_type = models.ForeignKey(UserTyep, on_delete=models.SET_DEFAULT, default=0) # 设置默认值
# user_type = models.ForeignKey(UserTyep, on_delete=models.DO_NOTHING) # 保护模式
#设置related_name、设置了这个就不能使用自带的user_set属性了、直接使用 related_name='users' 中的users对象就行了
user_type = models.ForeignKey(UserTyep, on_delete=models.PROTECT,
related_name='users'
)
#no_delete有以下的选项:
# 1、models.CASCADE 表示级联删除、即当删除UserType表的主键数据时、相关联的表User中的对应的外键的数据也会被删除
# 2、models.PROTECT 表示保护模式、阻止级联删除
# 3、models.SET_NULL 置空模式、设为null、相应的null=True(必须)、意思是当删除UserType表的主键数据时、相关联的表User中的对应的外键的数据不会被删除、外键变为null
# 4、models.SET_DEFAULT #设置默认值、表示删除关联的外键值后相应的数据不会删除、但是要指定默认的外键值
# 5、models.SET() 删除的时候重新动态指向一个实体访问对应元素、可传函数、不常用、类似SET_DEFAULT
# 6、models.DO_NOTHING 什么也不做、外键不会消失也不会改变 不建议使用
#数据迁移
#python .\manage.py makemigrations
#python .\manage.py migrate
#数据迁移后会在定义外键的表(字段多)自动新增一个字段:字段命名为:被绑定的外键类名小写(user_type)_主键名(id)
#增加数据
views.py
from django.shortcuts import render,HttpResponse
from app_mysql.models import *
#一对多的增删改查
#增
def add_user(request):
# #给UserTyPe表添加数据
# user_types = ['温工', '黄工', '番薯', '柱子']
# for name in user_types:
# UserTyep.objects.create(name=name)
#给User表添加数据
for i in range(11, 30):
# #使用用户类型的id(user_type_id-主键)绑定用户
# User.objects.create(name=f'张三-{i}', age=i, user_type_id=i%4 + 1)
#使用用户类型的对象绑定用户
#user_type=UserTyep.objects.get(pk=i%4 + 1) 获取的是用户类型的id:pk为主键也是id
User.objects.create(name=f'李四-{i}', age=100+i,
user_type=UserTyep.objects.get(pk=i%4 + 1)
)
return HttpResponse('添加成功')
#删除数据
def del_user(request):
# #删除User数据、对用户类型无影响
# User.objects.filter(id=6).delete()
#删除UserType中的数据、会影响User表中的数据
#这里删除用户类型表中id=2的类型、会导致用户表中(外键)user_type_id=2的用户也会被删除、这就是级联删除on_delete=models.CASCADE
UserTyep.objects.filter(id=2).delete()
return HttpResponse('删除成功')
#修改数据
def update_user(request):
#修改UserType表数据
UserTyep.objects.filter(id=3).update(name='小新')
#修改User表数据
User.objects.filter(id=11).update(age=20)
return HttpResponse('修改成功')
#查询数据
def get_user(request):
# #正向查询:从User表去查找UserType表数据
# user = User.objects.get(id=2)
# #user.user_type 拿到的是用户类型的对象
# print(user.name, user.age, user.user_type, user.user_type_id)
# print(user.user_type.name, user.user_type.id)
#反向查询:从UserType表去查对应的用户
# utype = UserTyep.objects.get(pk=1)
# print(utype.id, utype.name) #UserType自身的属性
# # user_set:内部自动会生成的属性、可以让你反向查询到所关联的所有的User用户表的集合
# #print(utype.user_set)
# print(utype.user_set.all()) #返回查询集列表
#使用filter查找
#通过UserType中指定的字段查找User表中相关联的用户
#如查找用户类型表中id=3 name='番薯' 所关联的用户
# users = User.objects.filter(user_type=UserTyep.objects.get(name='番薯')) #传入UserType的对象
# users = User.objects.filter(user_type_id=3) #通过字段查找
# users = User.objects.filter(user_type__name='番薯') #传入UserType表中的字段
#还可以使用 related_name查找、当使用了related_name就不能使用自带的_set相关的属性了、如utype.user_set.all()
#需要在models中设置
utype = UserTyep.objects.get(pk=1)
print(utype.users.all())
print(utype.users.filter())
return HttpResponse('查询成功')
urls.py
from django.contrib import admin
from django.urls import path
from app_mysql import views as one2many_view
urlpatterns = [
#一对多
#增加数据路由
path('one2many/adduser/', one2many_view.add_user),
#删除数据路由
path('one2many/deluser/', one2many_view.del_user),
#修改数据
path('one2many/updateuser/', one2many_view.update_user),
#查询数据
path('one2many/getuser/', one2many_view.get_user),
path('admin/', admin.site.urls),
]