1128 聚合查詢 orm字段及屬性


一 聚合查詢

1. 級聯

級聯刪除

操作外鍵字段管理數據的時候

書跟出版社是一對多關系,外鍵字段在書那,如果把出版社刪了,所對應的書也會自動刪除

級聯更新

如果把出版社主鍵值改變,那么書籍表中的出版社主鍵值也會更新改變

2. 聚合函數

  • 聚合函數必須用在分組之后
  • 沒有分組其實默認整體就是一組
  • Max Min Sum Sum Avg Count

使用 aggregate

  1. 關鍵字 aggregate

  2. 還需要導入模塊

    from django.db.models import Max,Min,Sum,Sum,Avg,Count
    
只要跟數據庫相關的功能,基本上都在django.db.models里面
如果不在,可能直接在django.db中

使用場景

  • 單獨使用:不分組,只聚合結果(aggregate)
  • 分組使用: 按字段分組,可分組字段與聚合結果(annotate)
1.篩選出價格最高的書籍的
res = models.Book.objects.aggregate(mr = Max('price'))
print(res)
2.求書籍總價格
res = models.Book.objects.aggregate(sm = Sum('price'))
print(res)
3.求書籍平均價格
res = models.Book.objects.aggregate(av = Avg('price'))
print(res)
4.一起使用
res = models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Count('price'),Avg('price'))
print(res)

3. 分組查詢

語法

values('分組字段').annotate(別名=聚合函數('字段')).filter(聚合字段別名條件).values('取分組字段', '取聚合字段別名')

什么時候需要分組

  • 統計每一個部門的平局薪資
  • 統計每一個部門的男女比例
  • 統計某一數據的組別內數據

使用 annotate

  1. 關鍵字 annotate

  2. 借助於聚合函數

    from django.db.models import Max,Min,Sum,Sum,Avg,Count
    
  3. django中models后面點什么,就按什么分組

代碼

    1.統計每一本書的作者個數 書名 和對應的作者人數
    res = models.Book.objects.annotate(author_num=Count('authors__id')).values('title','author_num')
    print(res)

    2.統計出每個出版社賣的最便宜的書的價格  出版社的名字 價格
    res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price')
    print(res)

    按照其他字段分組
    res = models.Publish.objects.values('想要分組的字段名').annotate(min_price=Min('book__price')).values('name','min_price')
    print(res)


    3.統計不止一個作者的圖書
    1.先拿書及對應的作者數
    2.再篩選出大於一的圖書  書名 作者數目
    res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title','author_num')
    print(res)

    4.查詢各個作者出的書的總價格  作者名字  總價格
    res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
    print(res)

4. F與Q查詢

F查詢

  • 通過字段名獲取可以直接做運算的查詢結果
  • F基於 F('字段條件')

導入

from django.db.models import F

使用

  • 后面的條件是來自於數據庫的其他字段值
  • 更改字符數操作,需要借助於Concat方法,在后面拼接字符串
from django.db.models import F,Q

    1. 查詢庫存數大於賣出數的書籍
    res = models.Book.objects.filter(kun_cun__gt = F('mai_cun')).values('title')  # 后面的條件是來自於數據庫的其他字段值
    print(res)



    2. 將所有書的價格上漲100塊
    models.Book.objects.all().update(price=F('price') + 100)



    3.將所有書的名稱后面全部加上 "爆款" 后綴    了解知識點    操作字符串數據需要借助於Concat方法
    from django.db.models.functions import Concat
    from django.db.models import Value
    ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))

Q查詢

  • 完成邏輯運算方式的查詢
  • Q基於 Q('字段條件')
  • 三種運算符 &(與) |(或) ~(非)

導入

from django.db.models import Q

使用

1.查詢一下書籍名稱是三國演義 或者 庫存數是500的書籍
res = models.Book.objects.filter(title='三國演義',kun_cun=500)  # and關系
res = models.Book.objects.filter(title='三國演義',kun_cun=500)  # and關系


res = models.Book.objects.filter(Q(title='三國演義'),Q(kun_cun=500))  # Q包裹之后逗號還是and關系

res = models.Book.objects.filter(Q(title='三國演義') | Q(kun_cun=500))  #  |就是or的關系

res = models.Book.objects.filter(~Q(title='三國演義') | Q(kun_cun=500))  #   ~就是not關系
print(res)

Q對象高級用法 q.children(('元組'))

按條件查詢時,可以傳字符串進行查詢默認是and關系,更改connector改為or,對象前加~取反

 q = Q()
    q.connector = 'or'  # 默認是and  可以改成or
    q.children.append(('title','三國演義'))
    q.children.append(('kun_cun__gt',500))
    res = models.Book.objects.filter(~q)  # 取反
    print(res)

img

二 ORM字段及參數

1.ORM字段

常用字段

字段 說明 字段屬性
AutoField() 默認自增主鍵(primary_key=True),django會默認建立id字段主鍵
CharField() 字符類型 max_length=64,數據長度,必須明確
IntegerField() 整型
DateField() 年月日時間類型 -- auto_now=True,數據被更新就會更新時間
-- auto_now_add=True,數據第一次參數時產生
DateTimeField() 年月日小時分鍾秒時間類型 -- auto_now=True,數據被更新就會更新時間
-- auto_now_add=True,數據第一次參數時產生
DecimalField() 混合精度的小數類型 -- max_digits=3,限定數字的最大位數(包含小數位)
-- decimal_places=2,限制小數的最大位數
BooleanField() 布爾字段,對應數據庫tinyint類型 數據長度只有1位 內部只接收0/1或者True/Flase
TextField 專門用來存大段文本
FileField 專門用來文件路徑 upload_to = '/etc/data',給該字段傳值的時候 直接傳文件對象
		CharField     varchar
		IntegerField   int
		BigIntegerField   bigint
		EmailField    varchar(254)
		DateField
		DateTimeField
			auto_now:每次修改數據的時候 都會自動將當前修改時間更新上去  實時更新
			auto_now_add:在創建數據的時候 會將當前時間自動記錄 之后不會自動修改  除非你人為修改
		
		AutoField     auto_increment   
		
		BooleanField    布爾值  
			該字段在存儲的時候 你只需要傳布爾值True或False
			它會自動存成1/0
		
		TextField  專門用來存大段文本
		
		FileField  專門用來文件路徑   '/etc/data/a.txt'   
			upload_to = '/etc/data'
			給該字段傳值的時候 直接傳文件對象
			會自動將文件對象保存到upload_to后面指定的文件路徑中
			然后將路徑保存到數據庫
		
		DecimalField(Field)
        - 10進制小數
        - 參數:
            max_digits,小數總長度
            decimal_places,小數位長度

DateField和DateTimeField

auto_now_add

配置auto_now_add=True,創建數據記錄的時候會把當前時間添加到數據庫。

auto_now

配置上auto_now=True,每次更新數據記錄的時候會更新該字段。

不常用字段

# 1. BigAutoField():大整型自增
# 2. BigIntegerField():長整型
# 3. EmailField():郵箱字段,擁有/admin/驗證
# 4. FloatField():浮點型小數
# 5. SmallIntegerField():小整型
# 6. TextField():大文本類型
# 7. FileField():文件字段

字段合集

AutoField(Field)
        - int自增列,必須填入參數 primary_key=True

    BigAutoField(AutoField)
        - bigint自增列,必須填入參數 primary_key=True

        注:當model中如果沒有自增列,則自動會創建一個列名為id的列
        from django.db import models

        class UserInfo(models.Model):
            # 自動創建一個列名為id的且為自增的整數列
            username = models.CharField(max_length=32)

        class Group(models.Model):
            # 自定義自增列
            nid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=32)

    SmallIntegerField(IntegerField):
        - 小整數 -32768 ~ 32767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正小整數 0 ~ 32767
    IntegerField(Field)
        - 整數列(有符號的) -2147483648 ~ 2147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正整數 0 ~ 2147483647

    BigIntegerField(IntegerField):
        - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807

    BooleanField(Field)
        - 布爾值類型

    NullBooleanField(Field):
        - 可以為空的布爾值

    CharField(Field)
        - 字符類型
        - 必須提供max_length參數, max_length表示字符長度

    TextField(Field)
        - 文本類型

    EmailField(CharField):
        - 字符串類型,Django Admin以及ModelForm中提供驗證機制

    IPAddressField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制

    GenericIPAddressField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6
        - 參數:
            protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
            unpack_ipv4, 如果指定為True,則輸入::ffff:192.0.2.1時候,可解析為192.0.2.1,開啟此功能,需要protocol="both"

    URLField(CharField)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 URL

    SlugField(CharField)
        - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下划線、連接符(減號)

    CommaSeparatedIntegerField(CharField)
        - 字符串類型,格式必須為逗號分割的數字

    UUIDField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證

    FilePathField(Field)
        - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能
        - 參數:
                path,                      文件夾路徑
                match=None,                正則匹配
                recursive=False,           遞歸下面的文件夾
                allow_files=True,          允許文件
                allow_folders=False,       允許文件夾

    FileField(Field)
        - 字符串,路徑保存在數據庫,文件上傳到指定目錄
        - 參數:
            upload_to = ""      上傳文件的保存路徑
            storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage

    ImageField(FileField)
        - 字符串,路徑保存在數據庫,文件上傳到指定目錄
        - 參數:
            upload_to = ""      上傳文件的保存路徑
            storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage
            width_field=None,   上傳圖片的高度保存的數據庫字段名(字符串)
            height_field=None   上傳圖片的寬度保存的數據庫字段名(字符串)

    DateTimeField(DateField)
        - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)
        - 日期格式      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field)
        - 時間格式      HH:MM[:ss[.uuuuuu]]

    DurationField(Field)
        - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值為datetime.timedelta類型

    FloatField(Field)
        - 浮點型

    DecimalField(Field)
        - 10進制小數
        - 參數:
            max_digits,小數總長度
            decimal_places,小數位長度

    BinaryField(Field)
        - 二進制類型

 字段合集

ORM字段與MySQL字段對應關系

對應關系:
    'AutoField': 'integer AUTO_INCREMENT',
    'BigAutoField': 'bigint AUTO_INCREMENT',
    'BinaryField': 'longblob',
    'BooleanField': 'bool',
    'CharField': 'varchar(%(max_length)s)',
    'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
    'DateField': 'date',
    'DateTimeField': 'datetime',
    'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
    'DurationField': 'bigint',
    'FileField': 'varchar(%(max_length)s)',
    'FilePathField': 'varchar(%(max_length)s)',
    'FloatField': 'double precision',
    'IntegerField': 'integer',
    'BigIntegerField': 'bigint',
    'IPAddressField': 'char(15)',
    'GenericIPAddressField': 'char(39)',
    'NullBooleanField': 'bool',
    'OneToOneField': 'integer',
    'PositiveIntegerField': 'integer UNSIGNED',
    'PositiveSmallIntegerField': 'smallint UNSIGNED',
    'SlugField': 'varchar(%(max_length)s)',
    'SmallIntegerField': 'smallint',
    'TextField': 'longtext',
    'TimeField': 'time',
    'UUIDField': 'char(32)',

ORM字段與MySQL字段對應關系

2. 關系字段

ForeignKey():外鍵字段

外鍵類型在ORM中用來表示外鍵關聯關系,一般把ForeignKey字段設置在 '一對多'中'多'的一方。

ForeignKey可以和其他表做關聯關系同時也可以和自身做關聯關系。

字段參數

to

設置要關聯的表

to_field

設置要關聯的表的字段

on_delete

當刪除關聯表中的數據時,當前表與其關聯的行的行為。

models.CASCADE

刪除關聯數據,與之關聯也刪除

db_constraint

是否在數據庫中創建外鍵約束,默認為True。

# 1. ForeignKey():外鍵字段
    #-- 字段屬性to關聯模型類
    #-- 字段屬性to_field關聯字段,省略默認關聯主鍵
    #-- 字段屬性on_delete (外鍵關聯數據被刪除時的操作)
        #-- models.CASCADE 級聯刪除
class Book(models.Model):
     publish = models.ForeignKey(to='Publish', to_field='id', on_delete=models.CASCADE)
        #-- modles.PROTECT 拋出異常
        #-- models.SET_NULL 設置空值
        #-- models.SET_DEFAULT 設置默認值
        #-- models.SET(value)自定義值
    #-- 字段屬性related_name自定義反向查詢的字段名,自定義后方向查詢自定義的名字會將默認的類名下划線set覆蓋。

    #-- 字段屬性db_constraint=False取消關聯關系,但還可以使用連表查詢
#總結:models.ForeignKey(to='關聯的類名', null=True, on_delete=models.SET_NULL, db_constraint=False, related_name="本類名小寫")

class Test2(models.Model):
    name = models.CharField(max_length=20)
    test1 = models.ForeignKey(to='Test1', null=True, on_delete=models.SET_NULL, db_constraint=False, related_name="tt")

OneToOneField():一對一外鍵字段

一對一字段。

通常一對一字段用來擴展已有字段。(通俗的說就是一個人的所有信息不是放在一張表里面的,簡單的信息一張表,隱私的信息另一張表,之間通過一對一外鍵關聯)

字段參數

to

設置要關聯的表。

to_field

設置要關聯的字段。

on_delete

當刪除關聯表中的數據時,當前表與其關聯的行的行為。(參考上面的例子)

#2、OneToOneField():一對一外鍵字段
#    -- 字段同外鍵

ManyToManyField():多對多關系字段

#3、ManyToManyField():多對多關系字段
    #-- 字段屬性to關聯模型類
    #-- 字段屬性through關聯關系類
    #-- 字段屬性through_fields關聯關系表中(本身類名小寫字段, 關聯表類名小寫字段)    
class MyBook(models.Model):
       my_author = models.ManyToManyField(to='MyAuthor', through='MyBook_MyAuthor', through_fields=('mybook', 'myauthor'))

class MyAuthor(models.Model):
    name = models.CharField(max_length=20)

class MyBook_MyAuthor(models.Model):
    mybook = models.ForeignKey(to="MyBook", null=True, on_delete=models.SET_NULL, db_constraint=False)
    myauthor = models.ForeignKey(to='MyAuthor', null=True, on_delete=models.SET_NULL, db_constraint=False)
    time = models.DateField()

3. 字段屬性

null

用於表示某個字段可以為空

#1. null:默認為False,True表示字段可為null,與數據庫相關
    a1 = models.CharField(max_length=20)  # 插入數據時該字段必須賦值
    a2 = models.CharField(max_length=20, null=True)  # 插入數據時可以為空

unique

如果設置為unique=True 則該字段在此表中必須是唯一的

db_index

如果db_index=True 則代表着為此字段設置索引。

default

為該字段設置默認值。

#1. null:默認為False,True表示字段可為null,與數據庫相關
    a1 = models.CharField(max_length=20)  # 插入數據時該字段必須賦值
    a2 = models.CharField(max_length=20, null=True)  # 插入數據時可以為空

#2. blank:默認為False,True表示字段可為空, 與表單驗證相關

#3. choice:可選的,限制了該選項的字段值必須是所指定的choice中的一個:
    -- sex = models.SmallIntegerField(choices=((1, '男'), (2, "女")))
    -- obj.get_sex_display()

#4. db_column:自定義字段名
sex = models.SmallIntegerField(choices=choices, default=0, db_column='gender')
# 他只是將數據庫中的字段變為gender,在django中若要查詢該字段的值仍需要輸入sex,因此不常用,不建議使用。

#5. db_index:如果為True的話,設置索引

#6. default:字段默認值

#7. editable:默認為True,若為False,則不會在/admin/界面顯示

#8. primary_key:若設置為True,則表示將該字段設置為主鍵。一般情況下django默認會設置一個自增長的id主鍵。

#9. unique:若設置為True,該字段值不可重復

4. 自定義字段類型

class MyCharField(model.Field):
    def __init__(self,max_length,*args,**kwargs):
        重新調用父類的方法							
     	super().__init__(max_length=max_length,*args,**kwargs)
    調用創建庫字段時的類型方法
    def db_type(self,connection):
        return'char(%s)' % self.max_length
        

img

三 斷開關聯的關系表

1. 斷開外鍵關聯的ForeignKey使用

# 1、不使用ForeignKey方式斷開關聯(即建表的時候就不讓其擁有自動關聯關系,而是手動的靠創建數據時的數據錄入建立關聯關系),查詢的時候不再支持Django ORM連表查詢語法
class Publish(models.Model):
    name = models.CharField(max_length=20)
class Book(models.Model):
    name = models.CharField(max_length=20)
    # 字段需要寫_id來表示相關表的字段信息
    publish_id = models.IntegerField()

# *****
# 2、使用ForeignKey方式用db_constraint=False字段屬性斷開關聯,依然支持Django ORM連表查詢語法,建議使用
class Publish(models.Model):
    name = models.CharField(max_length=20)
class Book(models.Model):
    name = models.CharField(max_length=20)
    # 字段不需要寫_id來表示相關表的字段信息,ORM會自動添加
    publish = models.ForeignKey(to='Publish', null=True, on_delete=models.SET_NULL, db_constraint=False)

2.斷開關聯的多對多自動創建關系表

# 使用ManyToManyField方式用db_constraint=False字段屬性斷開關聯,依然支持Django ORM連表查詢語法,建議使用
class MyBook(models.Model):
    name = models.CharField(max_length=20)
    my_author = models.ManyToManyField(to='MyAuthor', db_constraint=False)
class MyAuthor(models.Model):
    name = models.CharField(max_length=20)

3. 斷開關聯的多對多手動創建關系表

  手動創建關系表的好處:手動創建關系表可以讓關系表可以擁有更多的自身的字段,同時通過關系表類名可以直接獲取第三張表

  1、和自動建立關系表類似,依然支持Django ORM連表查詢語法(多對多借助關系表連表查詢)

class Book(models.Model):
    name = models.CharField(max_length=20)
    
class Author(models.Model):
    name = models.CharField(max_length=20)
    
class Book_Author(models.Model):
    book = models.ForeignKey(to="Book", null=True, on_delete=models.SET_NULL, db_constraint=False)
    author = models.ForeignKey(to='Author', null=True, on_delete=models.SET_NULL, db_constraint=False)
    time = models.DateField()

  2、手動創建關系表,在關系表中用ForeignKey方式支持基於外鍵關系表的ORM連表查詢,同時明確ManyToManyField字段,所以也支持ORM正向方向連表查詢
   -- db_constraint=False斷開關聯可以在ForeignKey或ManyToManyField任意一方完成

class Book(models.Model):
    name = models.CharField(max_length=20)
    # 明確through與through_fields,ManyToManyField才不會自動建立關系表
    author = models.ManyToManyField(to='Author', through='Book_Author')
    
class Author(models.Model):
    name = models.CharField(max_length=20)
    
class Book_Author(models.Model):
    book = models.ForeignKey(to="Book", null=True, on_delete=models.SET_NULL, db_constraint=False)
    author = models.ForeignKey(to='Author', null=True, on_delete=models.SET_NULL, db_constraint=False)
    time = models.DateField()

總結

手動創建第三張表,第三張表的增刪改就采用關系表類名衍生的create|delete|update,就不再擁有add|clear|remove|set(因為關系表擁有自己的字段,這些方法無法直接操作這些字段)

圖書管理系統

待完成


RBAC 基於角色的權限管理

在web領域中,url就是一切

ORM中的事務操作

什么是事務

  • 在 MySQL 中只有使用了 Innodb 數據庫引擎的數據庫或表才支持事務。
  • 事務處理可以用來維護數據庫的完整性,保證成批的 SQL 語句要么全部執行,要么全部不執行。
  • 事務用來管理 insert,update,delete 語句
客戶A要給客戶B轉一筆錢,這個在數據庫中需要進行兩步:

  1.客戶A減錢

  2.客戶B加錢

如果在第一步結束后,服務器出現異常,停下了,第二步沒有進行,如果數據庫使用了事務操作,真的出現異常的時候,前面的操作會進行回滾。

簡單的說就是:要么全部執行成功,要么一個都不執行

這個回滾的操作就叫做數據庫的原子性操作。

四大特性

ACID

  • 原子性
    • 事務是最小的單位,不可再分
  • 一致性
    • 事務要求所有的DML語句操作時,必須保證同時成功或者同時失敗
  • 隔離性
    • 事務與事務之間是隔離的
  • 持久性
    • 是事務的保證,事務終結的標志(內存的數據持久到硬盤)

數據庫的三大范式(設計范式)

第一范式(1NF)

表中的列只能含有原子性(不可再分)的值

第二范式(2NF)

  • 滿足第一范式
  • 沒有部分依賴
    • 表必須有一個主鍵
    • 沒有包含在主鍵中的列必須完全依賴於主鍵,而不能只依賴主鍵的一部分。

第三范式(3NF)

  • 滿足第二范式

  • 沒有傳遞依賴

    即每個屬性都跟主鍵有直接關系而不是間接關系

django開啟事務

導入

from django.db import transaction

開啟

with transaction.atomic()
	在縮進的代碼中書寫數據庫操作
	該縮進的所有代碼,都是一個事務
	pass

回滾

rollback()

回滾就是回到上一個狀態


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM