django orm原理_Django 框架4:ORM高级操作-多表定义与操作

Model关系说明:UserInfo:员工信息表,Dept:部门,JobLevel:级别

一、一对多关系

1、使用ForeignKey定义,主表被关联的字段,必须是primary_key或unique属性

ForeignKey,使用ForeignKey的字段查询时是一个对象,使用.继续查询子表数据

主表:to的表,子表,定义ForeignKey的表

**注意,如果UserInfo表存在记录,migrate的时候会报错

1)先把主表录入数据,再在ForeignKey里设置deafult

2)把ForeignKey的null设置成True

参数说明备注

to主表名:必填

可省略to例:

'Group'或to=‘Group’

to_feild关联主表字段:必须是primarykey或unique

1、省略,自动关联主表的Primarykey

2、指定关联主键字段

3、子表关联字段名自动生成例:

s=models.ForeignKey('Salary')

子表自动生成s_id字段

s:定义的ForeignKey名

_id:固定

related_name给外键定义外部查询方法,替代_set,_set失效

作为方法使用related_name='r'

obj.r.filter()

on_delete主表删除数据后,子表做何操作,必填!

CASCADE:此值设置,是级联删除。

PROTECT:此值设置,是会报完整性错误。

SET_NULL:此值设置,会把外键设置为null,前提是允许为null。

SET_DEFAULT:此值设置,会把设置为外键的默认值。

SET():此值设置,会调用外面的值,可以是一个函数。

default外键默认值:如果子表有记录参照下面三条

1、如果不指定,运行makemigrateion出提示

2、先建主表记录,再ForeignKey,否则不符外键约束

3、也可设置null=True设置为空

related_query_name给定主表,通过related_query_name查询副表字段,返回的是主表queryset对象

给外键定义外部查询字段,在filter里使用副表里定义:related_query_name='r'

Group.objects.fileter(r__name='sa')

返回的是副表name=sa对应的Group

limit_choices_to待查

parent_link待查

db_constraint待查

表结构代码from django.db import models

class UserInfo(models.Model):

# 自动生成id,并设置为主键

name = models.CharField(max_length=32)

age = models.SmallIntegerField()

# 定义关系,只写模型名,默认找JobLevel的primarykey字段

# level = models.ForeignKey('JobLevel',on_delete=SET_DEFAULT,default='1')

# to_field可以指定primarykey或unique字段,副表自动生成的依然是level_id字段

# level = models.ForeignKey('JobLevel', to_field='id')

level = models.ForeignKey('JobLevel', to_field='id', related_name='r_method',

related_query_name='r_query', on_delete='SET_NULL',null=true)

class JobLevel(models.Model):

# 自动生成id,并设置为主键

name = CharField(max_lengh=32)

salary = IntegerField()

# 添加:level可以赋对象值。

models.UserInfo.objects.create(username='root4',password=1111,

level=models.JobLevel.objects.filter(level='SS1').first()

)

查询:

_set,主表操作副表记录,须first或get获取单一对象,Queryset列表不能使用_set# -副表->主表

u=models.UserInfo.objects.filter(id=1).first()        # 使用filter的结果是queryset对象,所以加first只取一个Models对象,方便操作。

u.level                                               # .定义的外键名,结果是JobLevel对象

u.level.salary                                        # .定义的外键名.主表字段,结果是查询主表的对应字段值

# 使用双下划线__查询:

u=models.UserInfo.objects.filter(level__salary=10000) # 通过外键level__salary,查询工资是10000的所有用户

# -通过主表查副表:

#使用related_name查询

s=j.r_method.all()                                    # 通过related_name查询,结果是queryset类型

#使用_set,需要把ForeignKey里面的related_name删掉。否则报错。

s=j.userinfo_set.all()                                # 结果和上面一样

#使用related_query_name查询

s=models.JobLevel.objects.filter(r_query__name='root')    # root对应的joblevel,返回的是QuerySet对象

# -通过副表__查询主表:

s=models.UserInfo.objects.filter(joblevel__name='s1')     # 查询S1职位对应的所有用户。

修改

update基于字段修改

add基于对象更改,自动找到关联外键字段

对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。

一对多,对于.remove和.add只能在_set情况下使用,通过主表改副表里用,remove:清空字段,字段必须null=True# 修改1:使用queryset对象更新副表

j=models.JobLevel.objects.filter(id=2).first()

u=models.UserInfo.objects.filter(id__lt=10)           # 注意获取到的是queryset对象

u.update(level=j)                                     # 因为level字段是一个对象,所以把查询到的对象j赋值给level

# 修改2:使用obj更新副表

for u_obj in u:                                       # 直接给UserInfo表赋值

u_obj.update(level_id=j.id)

# 或:u_obj.update(level_id=2)

# 修改3:使用_set修改,通过主表对象修改副表

j.userinfo_set.add(*u)                                # 使用*u把对象j传给QuerySet对象

j.userinfo_set.add(obj_u)                             # 把j传递给obj_u的models对象。

删除:

是指删除副表关联字段的值# j.userinfo_set.remove(*u)

# 这个是坑,*u里的所有对象必须都关联id=2的对象,如果有关联id=3的,会报错!!!!!

2、_set,   主表操作副表记录,须first或get获取单一对象,Queryset列表不能使用_setlevel_obj = models.JobLevel.objects.filter(level='SS1').first()    # 必须first或get获取单一对象,Queryset列表不能使用_set

二、多对多关系

表结构代码:

1、使用ManyToManyField自动生成中间表结构

优点:表自动维护,缺点:无法直接对表进行操作。

默认中间表名:应用_表1_表1定义的外键名,例:ormtest_userinfo_dept_objclass UserInfo(models.Model):

# 自动生成id,并设置为主键

name = models.CharField(max_length=32)

age = models.SmallIntegerField()

level = models.ForeignKey('JobLevel', to_field='id', related_name='r_method',

related_query_name='r_query', on_delete='SET_NULL',null=true)

dept_obj = models.ManyToManyField('Dept')

class Dept(models.Model):

name = models.CharField(max_length=50)

code = models.CharField(max_length=50, unique=True)

操作:"""ManyToManyField"""

# 创建Dept表记录

models.Dept.objects.create(name='开发部',code='KF0001')

models.Dept.objects.create(name='总务部',code='ZW0002')

models.Dept.objects.create(name='采购部',code='CG0003')

# 添加1,通过对象,add添加

u1 = models.UserInfo.objects.filter(name='root').first()

d1 = models.Dept.objects.filter(name='开发部').first()

u1.dept_obj.add(d1)

# 添加1-2,通过对象,添加多个

u1 = models.UserInfo.objects.filter(name='user')

d1 = models.Dept.objects.filter(name='开发部').first()

d1.userinfo_set.add(*u1)        # 把u1所有的对象都和d1建立关联

# 添加2,通过id,add添加

u1 = models.UserInfo.objects.filter(name='root1').first()

u1.dept_obj.add(*[1, 3])      # 添加多个

u1.dept_obj.add(2)        # 添加一个

# 添加3,通过对象,使用_set 返向add添加

u1 = models.UserInfo.objects.filter(name='root').first()

d1 = models.Dept.objects.filter(name='开发部').first()

d1.userinfo_set.add(u1)

# 查询1,使用__查副表字段:

u3 = models.UserInfo.objects.filter(dept_obj__name='开发部').all()

# 查询2,使用_set查询

d3 = models.Dept.objects.filter(name='开发部').first()

u3 = d3.userinfo_set                    # 与查询1的u3一样

# 删除1,移除field值,从中间表删除整条记录

u2 = models.UserInfo.objects.filter(name='root').first()

d2 = models.Dept.objects.filter(name='总务部').first()

d2.userinfo_set.remove(u2)

# 删除2,清空对应的中间表记录

d2.userinfo_set.clear()

# 使用.set修改关联值:通过中间表ID可以判断出来,set原理是先删除后建立

# 注意事项:

# 1、u2对应中间表多个记录,set把所有对应记录全删掉

# 2、set只创建对应参数的记录

u2.dept_obj.set('3')        # 只创建一个对应id为3的记录

u2.dept_obj.set(['2','1'])  # 列表前不加*

2、使用Foreignkey实现多表关联

优点:可以自定义中间表结构。class UserInfo(models.Model):

# 自动生成id,并设置为主键

name = models.CharField(max_length=32)

age = models.SmallIntegerField()

department = models.ManyToManyField

dept_obj = models.ManyToManyField('Dept')

class Dept(models.Model):

name = models.CharField(max_length=50)

code = models.CharField(max_length=50, unique=True)

class UserInfo_To_Dept(models.Model):

userinfo = models.ForeignKey('UserInfo')

dept = models.ForeignKey('Dept')

level = models.CharField(max_length=50)        # 自定义的字段

你可能感兴趣的:(django,orm原理)