注,一对一、一对多、多对多–多数方法是通用
一对一
1.查 1.子表查询母表(通过子表的字段条件找到母表对应的数据) 通过子表查询母表,写法:子表对象.母表表名的小写.母表字段名 例如:子表原名.objects.get(子表字段=查询数据).母表表名小写.母表字段名 1.反向查询从母表入手 例如:母表原名.objects.get(子表名(小写)__子表字段=查询数据).母表字段名 2.母表查询子表(通过母表的字段条件找到子表对应的数据) 母表原名.objects.get(母表字段=查询数据).子表表名小写.子表字段名 2.反向查询从子表入手 子表.objects.get((一对一的子表字段)子表字段__母表字段=查询数据).子表字段 2.增 母表.objects.create(字段名字=添加的数据) 子表.objects.create((定义一对一)外键字段=母表的对象, 子表的字段=添加的数据) #写法1: 母表创建的对象=母表.objects.create(字段=数据) 字表.objects.create(外键字段=母表,字表字段=数据) 对象id=母表.objects.create(字段=数据).id 字表.objects.create(外键_id=对象id,字表字段=数据) #写法2: 母表对象=母表.objects.create(字段=数据) 字表对象=字表(外键=母表对象, 字表字段=数据) 字表对象.save() #写法3(字典导入): 母表对象=母表.objects.create(字段=数据) dict={'字表字段':"数据"} 字表.objects.create(外键=母表对象,**dict) 3.改 母表对象 = 母表.objects.get(字段=数据)#.get()等同于.filter(),.first() 母表对象.字段名=要修改的数据 母表对象.save() 字表.objects.filter(字段=数据).update(外键=母表对象, 字表字段=要修改的数据)#update(), delete()是QuerySet方法 1.修改单条数据 母表对象 = 母表.objects.get(字段=数据) 母表对象.字段名=要修改的数据 母表对象.save() 2.修改多条数据(把满足母表条件的字表字段改为相应数据) #写法1 字表.objects.filter(外键__母表字段=母表的数据).update(子表字段=要修改的数据) #写法2 dict = {"字表字段":"要修改的数据"} 字表.objects.filter(id__gt(条件可以改)=0()).update(**dict) 4.删 子表.objects.get(字段=数据).delete()#对象和QuerySet都有delete() 母表.objects.filter(字段=数据).delete 母表.objects.all().delete()#清空一张表一对多
1.查 #外键表联合查询 #外键子表查询母表,与一对一子表查询母表形式一致 通过子表数据找到它在母表所属的对应数据 子表.objects.get(字段=数据).母表.母表字段 #(找的是母表数据) 母表.objects.get(子表__字段=数据).母表字段 #(找的是母表数据) #外键母表查询子表,与一对一形式不同,因为母表为"多",不能像一对一一样通过.get().子表.子表字段的方式获取,但与多对多母表查询子表一致 #通过母表中指定某一个数据来查找子表中所有对应关系 #写法1 母表对象 = 母表.objects.get(字段=数据) 母表对象.子表_set.all() #注意:子表小写_set的写法,它实际上是一个QuerySet,可以用update,delete,all,filter等方法 #写法2 子表.objects.filter(字段=母表.objects.get(母表字段=数据)) 子表.objects.filter(子表外键__母表字段=数据) #写法:filter(子表外键字段__母表字段='过滤条件') #写法3 母表对象 = 母表.objects.get(字段=数据).id 子表.objects.filter(子表外键_id = 母表对象) #filter得到QuerySet,写法:filter(子表外键字段_母表主键=母表主键对象) 通过QuerySet的.values()方法,将QuerySet转化为ValuesQuerySet 子表.objects.filter(子表外键名=母表.objects.get(母表字段=数据)).values('子表外键__母表字段名', '子表字段') #获取子表的某一个字段,和母表的某一个字段,获取母表字段写法: 子表外键字段名__母表字段名--适用于values()或filter() 子表.objects.filter(子表外键__母表字段=数据).values("子表外键__母表字段", '子表字段') #如果不加values(),返回的是[<子表: xxx>, <子表: xxx>]这样一个QuerySet集合,通过values可以形成一个列表,列表中的每一个元素是一个字典,可以通过list()将ValuesQeurySet转化为列表,之后返回给templates #另外可通过.values_list()将QuerySet转化为ValuesListQuerySet。返回:[(u'\u7ea2', u'\u7ea2\u889c\u5b50'), (u'\u7ea2', u'\u7ea2\u889c\u5b50')] #得到的是一个列表,列表中是多个元组,每个元组是ValuesQuerySet中字典的value,常用于从models里将数据取出后动态添加到前端模板中的select选项中。 2.增 #增填子表数据,形式与一对一,一致(可以使用最顶上的一对一方法,字典方法这里不再重写了) #添加子表数据,对应母表的某一个数据 #方法1 子表.objects.create(子表外键=母表.objects.get(母表字段=数据).子表字段=需要添加的数据) 子表.objects.create(子表外键_id=母表.objects.get(母表字段=数据).id, 子表字段=要添加的数据) 返回对象 = 子表(子表外键=母表.objects.get(母表字段=数据), 子表字段=要添加的数据) 返回对象.save() 3.改 #以对应的母表的某一个数据,在更新子表中的字段数据 #写法1 子表.objects.filter(子表外键__母表字段=数据).update(子表需要更改的字段=改为什么的数据) #写法2 子表.objects.filter(子表外键_id=母表.objects.get(母表字段=数据).id).update(子表需要更改的字段=改为什么的数据) #写法3(对应母表的子表的id大于等于1的数据全部修改) 母表对象 = 母表.objects.get(字段=数据) 母表对象.子表_set.filter(id__gte=1).update(子表字段=改为什么数据) 更多方法参考一对一 4.删 子表.objects.get(字段=数据).delete #对象和QuerySet都有delete() 母表.objects.filter(字段=数据).delete() #更多方法参考一对一多对多
1.查 #多对多子表查询母表,通过子表某一个数据作为键,来查询对应的母表数据 #与一对多子表查询母表的形式不同,因为一对多,查询的是母表的“一”;多对多,查询的是母表的“多” #写法1 返回对象 = 子表.objects.get(字段=数据) #写法:子表对象.子表多对多字段.过滤条件(all()/filter()) 返回对象.外键.all() #写法2 #反向查询从母表入手 母表.objects.filter(子表表名小写__子表字段名=数据) #母表对象.filter(子表表名小写__子表字段名="过滤条件") #多对多母表查询子表,查找子表那些数据中关联了母表指定数据 #与一对多母表查询子表的形式完全一致,因为查到的都是QuerySet,一对多和多对多,都是在查询子表的“多” #写法1 返回对象 = 母表.objects.get(字段=数据) 返回对象.子表_set.all() #写法2 子表.objects.filter(子表外键=母表.objects.get(母表=数据)) #写法2简写 子表.objects.filter(子表外键__母表字段=数据) #写法:filter(子表外键字段__母表字段='过滤条件') #写法3 返回对象 = 母表.objects.get(字段=数据).id 子表.objects.filter(子表外键=返回对象) ##filter得到QuerySet,写法:filter(子表外键字段=母表主键对象),此处和一对多略有不同,是子表外键字段而不是外键字段_母表主键 2.增与改(增添子表或母表数据参照一对一的增,多对多重点在于关系表的对应关系变更) #添加子表关联关系 #添加子表数据与全部母表数据对应 #写法1 返回对象一 = 子表.objects.create(字段=数据) #如果存在可以使用.get() 返回对象二 = 母表.objects.all() #创建母表的所有数据QuerySet对象 返回对象一.子表外键.add(*返回对象二) #写法:子表对象.子表多对多字段.add(*QuerySet对象) #写法2 子表对象 = 子表.objects.get(字段=数据) 母表对象 = 母表.objects.all() 子表对象.子表外键=母表对象 子表对象.save() #让子表数据对象2一个以上的母表数据 子表对象 = 子表.objects.get(字段=数据) 母表对象 = 母表.objects.filter(字段__in = ["数据一", "数据而"]) # #models默认只能用这种方式得到并集,如需更复杂的过滤逻辑,需使用模块Q 子表对象.子表外键.add(*母表对象) #add是追加模式,如果当前子表数据已经存在母表对应数据,那么执行后,子表原有对应关系不变会额外增加数据对应 #子表对象.子表外键.clear()是清空子表对应的母表数据 子表对象=子表.objects.get(字段="数据") 母表对象=母表.objects.get(字段="数据") 子表对象.子表外键.clear() 子表对象.子表外键.add(母表对象) #此处没有* #添加母表关联关系 #让母表中的数据对应子表的某一个数据,可以用上边的方法,一个效果,下边介绍反向插入(从母表入手)的写法 子表对象=子表.objects.get(字段=数据) 母表对象=母表.objects.get(字段=数据) 母表对象.子表表名小写_set.add(子表对象) #从母表插入子表数据,写法:母表对象.子表名小写_set.add(子表对象)。 #让子表所有数据都对应母表某一个数据 子表对象=子表.objects.all() 母表对象=母表.objects.get(字段=数据) 母表对象.子表表名小写_set.add(*子表对象) #另外备注一下,母表对象.子表表名小写_set.clear()是让所有子表数据去掉母表某一个数据对应,母表对象.子表表名小写_set.all().delete()是删除.子表表名小写_set的所有人 #关于_set写法,究竟什么时候使用_set,简单记忆,只有子表才有"子表名小写_set"的写法,得到的是一个QuerySet集合,后边可以接.add(),.remove(),.update(),.delete(),.clear() 3.删 删除多对多表关系: #删除子表与母表关联关系 #让子表数据不关联任何母表数据 #写法1: 子表对象=子表.objects.get(字段=数据) 母表对象=母表.objects.all() 子表对象.子表外键='' 子表对象.save() #写法2: 子表对象=子表.objects.get(n字段="数据") 母表对象=母表.objects.all() 子表对象.子表外键.remove(*母表对象) #写法3: 子表对象=子表.objects.get(字段="数据") 子表对象.子表外键.clear() #更多例子参照多对多的增与改案例,这里就不再重复了 #删除母表与子表关联关系 #让所有子表数据不再关联某一个母表数据 #写法1: 子表对象=子表.objects.all() 母表对象=母表.objects.get(字段="数据") 母表对象.子表表名小写_set.remove(*子表对象) #写法2: 母表对象=母表.objects.get(字段="数据") 母表对象.子表表名小写_set.clear() #删除多对多表数据: #删除子表数据 #让子表对应母表指定数据的所有子表数据都删掉 母表对象=母表.objects.get(字段="数据") 母表对象.子表表名小写_set.all().delete() #注意有.all() #删除所有子表数据 子表.objects.all().delete() 删除母表数据: 默认情况下,如此例中,删除母表数据,那么子表与颜色表是一对一或外键关系的,子表对应数据会自动删除,与母表是多对多关系的话,不会自动删除关联数据,而是去掉母表已选项 如果想让与母表外键关联的子表在删除外键之后依旧可以保留子表数据,需要子表建表时加入以下字段: class 子表(models.Model):#(一对多举例) color=models.ForeignKey("Colors",null=True,on_delete=models.SET_NULL)) #可为空,如果外键被删后,子表数据此字段置空而不是直接删除这条数据,同理也可以SET_DEFAULT,需要此字段有默认值 description=models.CharField(max_length=10) #描述 #choice #choices相当于实现一个简化版的外键,外键的选项不能动态更新,如可选项目较少,可以采用 #先在models添加choices字段 class UserInfo(models.Model): phone = models.CharField(max_length=11) password = models.CharField(max_length=64) head_picture = models.ImageField(upload_to='UC_user', default='')#头像 nickname = models.CharField(max_length=20, blank=True, default='')#昵称 realname=models.CharField(max_length=10, blank=True, default='')#真实姓名 sex_choice = ((0,"男"),(1,"女")) sex = models.IntegerField(choices=sex_choice, default=0) #在views.py中调用 Userinfo_obj=UserInfo.objects.get(phone=xxxx) print(Userinfo_obj.sex) #返回0或1 print(child_obj.get_sex_display()) #返回男或女