(1)一对一:OneToOneField
(2)一对多:Foreignkey
(3)多对多:ManyToManyField
如: (1)一个用户类型可以有多个用户,而一个用户只属于一个用户类型
(2) 一个班级可以有多个学生, 而一个学生只能属于一个班级
(3)一个出版社可以出版很多不同的图书, 而一本图书只能属于一个出版社
(4)一个家庭可以有多个人, 而一个人只能属于一个家庭
Django 会自动将字段的名称添加“_id”作为列名,ForgienKey 的定义如下:
class django.db,model.ForeignKey(to,on_delete,**options)
有两个必填参数。to指定所关联的 Model,它的中取值可以是直接引用其他的 Model,也可以是 Model 所对应的字符串名称;on_delete当删除关联表的数据时,Django 将根据这个参数设定的值确定应该执行什么样的 SQL 约束。
on_delete 可以理解为 MySQL 外键的级联动作,当主表执行删除操作时对子表的影响,即子表要执行的操作,Django 提供的可选值如下所示:
- CASCADE,级联删除,它是大部分 ForeignKey 的定义时选择的约束。它的表现是删除了“主”,则“子”也会被自动删除。
- PROTECT,删除被引用对象时,将会抛出 ProtectedError 异常。当主表被一个或多个子表关联时,主表被删除则会抛出异常。
- SET_NULL,设置删除对象所关联的外键字段为 null,但前提是设置了选项 null 为True,否则会抛出异常。
- SET_DEFAULT:将外键字段设置为默认值,但前提是设置了 default 选项,且指向的对象是存在的。
- SET(value):删除被引用对象时,设置外键字段为 value。value 如果是一个可调用对象,那么就会被设置为调用后的结果。
- DO_NOTHING:不做任何处理。但是,由于数据表之间存在引用关系,删除关联数据,会造成数据库抛出异常。
2、语法格式:
#一个A类实例对象关联多个B类实例对象 class A(model.Model): .... class B(model.Model): 属性 = models.ForeignKey(多对一中"一"的模型类, ...)
3、应用:(一个用户类型可以多个用户)CRUD操作
(1) models.py
from django.db import models
# Create your models here.
# one to many =1:N
# 用户类型: 可以多个用户
# 一个用户:只属于一个用户类型
# 用户类型
class UserType(models.Model):
name=models.CharField(max_length=30) # 用户类型名称 :黑铁,青铜,白银,黄金,钻石
class Meta:
db_table='userType'
verbose_name='用户类型'
verbose_name_plural=verbose_name
#用户表
class User(models.Model):
name = models.CharField(max_length=30) # 用户名称
age = models.IntegerField(default=18) # 年龄
#关联关系-FK(用户类型,级联删除) (自动生成 user_type_id)
user_type=models.ForeignKey(UserType,on_delete=models.CASCADE) #级联删除
# user_type=models.ForeignKey(UserType,on_delete=models.PROTECT) #保护模式
# user_type=models.ForeignKey(UserType,on_delete=models.SET_NULL,null=True) #设置空模式
# user_type=models.ForeignKey(UserType,on_delete=models.SET_DEFAULT,default=2) #设置默认模式
# user_type=models.ForeignKey(UserType,on_delete=models.DO_NOTHING) #什么也不做(发生异常有提示)
class Meta:
db_table = 'user'
verbose_name = '用户'
verbose_name_plural = verbose_name
数据迁移 : python manage.py makemigrations
数据同步到数据库:python manage.py migrate
(2)views.py
from django.http import HttpResponse
from django.shortcuts import render
# Create your views here.
# 一对多
from onetomany.models import UserType, User
# 用户类型添加数据
def addUser(request):
# 用户类型
user_types = ['黑铁', '青铜', '白银', '黄金', '钻石', '大师', '王者']
for type in user_types:
UserType.objects.create(name=type)
return HttpResponse('添加成功!!')
# 用户添加数据
def addUser2(request):
# 用户 使用id进行添加
for i in range(10, 31):
User.objects.create(name=f'刘飞-{i}', age=i, user_type_id=i % 7 + 1)
return HttpResponse('添加成功!!')
# 用户添加数据
def addUser3(request):
# 用户 :通过对象进行添加
for i in range(10, 31):
User.objects.create(name=f'王芳-{i}', age=90 + i, user_type=UserType.objects.get(pk=i % 7 + 1))
return HttpResponse('添加成功!!')
# 删除数据
def delUser(request):
# 删除用户User ,此时UserType表无关
# User.objects.filter(id=4).delete()
# 删除UserType表数据,此时User表有关,删除
UserType.objects.filter(id=1).delete()
return HttpResponse('删除成功!!')
# 修改数据
def updateUser(request):
# 修改用户类型表
UserType.objects.filter(id=2).update(name='荣耀')
return HttpResponse('修改成功!!')
# 修改数据
def updateUser2(request):
# 修改用户表
User.objects.filter(id=2).update(name='mike',age=18)
return HttpResponse('修改成功!!')
# 查询数据
def getUser(request):
#正向查询:从user表查找Usertype表
user=User.objects.get(id=1)
print(user.name,user.age,user.user_type,user.user_type_id)
print(user.user_type.id,user.user_type.name)
# 刘飞-10 10 UserType object (4) 4
# 4 黄金
return HttpResponse('查询成功!!')
# 查询数据
def getUser2(request):
# 反向查询:从Usertype表查找user表
usertype = UserType.objects.get(pk=5)
print(usertype.id,usertype.name)
#一对多,查询集合
print(usertype.user_set.all())
return HttpResponse('查询成功!!')
(3)urls.py
from django.contrib import admin
from django.urls import path, include
#导入视图
from onetomany import views as onetomany_view
urlpatterns = [
# path('onemany', include('onetomany.urls')), #子路由
path('onemany/adduser/', onetomany_view.addUser), #添加
path('onemany/adduser2/', onetomany_view.addUser2), #添加
path('onemany/adduser3/', onetomany_view.addUser3), #添加
path('onemany/del/', onetomany_view.delUser), #删除
path('onemany/update/', onetomany_view.updateUser), #修改
path('onemany/update2/', onetomany_view.updateUser2), #修改
path('onemany/get/', onetomany_view.getUser), #查找
path('onemany/get2/', onetomany_view.getUser2), #查找
]
(4) 运行
添加修改删除的数据
正向查询
反向查询
(5)总结
一个用户类型可以有多个用户,而一个用户只属于一个用户类型
对象的使用:
正向 (在User这边, 有userType属性的这一边):
获取用户所在用户类型(对象) :user.user_type
获取用户所在用户类型的属性: user.user_type.name
反向 (在UserType这边):
获取用户类型的所有用户(获取Manager对象): usertype.user_set
获取用户类型的所有用户(获取QuerySet查询集): usertype.user_set.all()
filter(),get()等操作中的使用:
正向 (在User这边, 有userType属性的这一边):
User.objects.filter(属性_name='1')
如: User.objects.filter(usertype_name='1')
反向 (在UserType这边):
usertype.objects.filter(类名小写_id=7)
如: usertype.objects.filter(user_id=7)