Django 框架4:ORM高級操做-多表定義與操做

Model關係說明:
UserInfo:員工信息表,Dept:部門,JobLevel:級別
python

111.PNG

1、一對多關係django

    一、使用ForeignKey定義,主表被關聯的字段,必須是primary_key或unique屬性ide

            ForeignKey,使用ForeignKey的字段查詢時是一個對象,使用.繼續查詢子表數據函數

            主表:to的表,子表,定義ForeignKey的表spa

            **注意,若是UserInfo表存在記錄,migrate的時候會報錯code

                1)先把主表錄入數據,再在ForeignKey裏設置deafultorm

                2)把ForeignKey的null設置成True對象


參數 說明 備註
to

主表名:必填開發

可省略to
rem

例:

'Group'或to=‘Group’

to_feild

關聯主表字段:必須是primarykey或unique

一、省略,自動關聯主表的Primarykey

二、指定關聯主鍵字段

三、子表關聯字段名自動生成

例:

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

外鍵默認值:若是子表有記錄參照下面三條

一、若是不指定,運行makemigrateion出提示

二、先建主表記錄,再ForeignKey,不然不符外鍵約束

三、也可設置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的,會報錯!!!!!

          

    二、_set,   主表操做副表記錄,須first或get獲取單一對象,Queryset列表不能使用_set

level_obj = models.JobLevel.objects.filter(level='SS1').first()    # 必須first或get獲取單一對象,Queryset列表不能使用_set


2、多對多關係

    表結構代碼:

        一、使用ManyToManyField自動生成中間表結構

            優勢:表自動維護,缺點:沒法直接對錶進行操做。

        默認中間表名:應用_表1_表1定義的外鍵名,例:ormtest_userinfo_dept_obj

class 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原理是先刪除後創建
# 注意事項:
    # 一、u2對應中間表多個記錄,set把全部對應記錄全刪掉
    # 二、set只建立對應參數的記錄
u2.dept_obj.set('3')        # 只建立一個對應id爲3的記錄
u2.dept_obj.set(['2','1'])  # 列表前不加*

        二、使用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)        # 自定義的字段
相關文章
相關標籤/搜索