【1027 | Day54】Django之ORM字段及查詢優化(部分)

[toc]python

Django之ORM字段及查詢優化

一:經常使用字段

(1)AutoFiled字段:

(1)做用:mysql

  (1)int自動遞增字段,其必須傳入primary_key = Truegit

  (2)若是模型表中沒有自增列 會自動建立一個名爲id的自增列sql

  (3)相似於主鍵字段數據庫

(2)IntegerField:

(1)做用:django

  (1)整數類型 其範圍在-2147483648 to 2147483647(手機號不會用其存儲 位數不夠 通常使用字符串存儲手機號)app

  (2)至關於整形字段測試

(3)CharField:

(1)做用:優化

  (1)字符類型 必須提供max_length參數atom

  (2)至關於字符串類型

  (3)其相似mysql中的varchar類型,在模型表中是沒有char字段的

(3)DateField:

(1)做用:

  (1)日期字段,年月日格式

  (2)相似於python中datetime.time()

(4)DateTimeField:

(1)做用:

  (1)日期字段,年月日格式

  (2)相似於python中datetime.datetime()

(5)choice

(1)做用:

  (1)存在某些對應關係

  (2)例如:中文與英文對應 減小數據庫的存儲壓力

(2)使用方式:

user_obj = models.User_info.objects.filter(pk=1).first()
    print(user_obj.gender)  # 直接點字段 獲取仍是數字
    print(user_obj.get_gender_display())  # 男 get_gender_display() 固定使用方式

    user_obj = models.User_info.objects.filter(pk=3).first()
    print(user_obj.get_gender_display())  # 3 若是沒有和數字對應關係 不會報錯 直接返回數字

常見字段類型:

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)',

自定義字段:

from django.db import models

# Create your models here.
#Django中沒有對應的char類型字段,可是咱們能夠本身建立
class FixCharField(models.Field):
    '''
    自定義的char類型的字段類
    '''
    def __init__(self,max_length,*args,**kwargs):
        self.max_length=max_length
        super().__init__(max_length=max_length,*args,**kwargs)

    def db_type(self, connection):
        '''
        限定生成的數據庫表字段類型char,長度爲max_length指定的值
        :param connection:
        :return:
        '''
        return 'char(%s)'%self.max_length

二:經常使用字段參數

(1)null

(1)做用:

  (1)表示某個字段能夠設置爲空

  (2)當給模型表新增字段的時候能夠將給字段設置爲空 進行新增

(2)使用方式:

email = models.EmailField(null=True)  # 將該字段設置爲空

(2)unique

(1)做用:表示某個字段惟一 不能重複

(2)使用方式:

email = models.EmailField(unique=True)  # 將該字段設置惟一 只是演示使用方式

(3)default

(1)做用:給某個字段設置默認值

(2)使用方式:

email = models.EmailField(default='110@qq.com')  # 只是演示使用方式

(4)auto_now_add

(1)做用:建立數據記錄的時候 會把當前時間記錄

(2)使用方式:

create_time = models.DateField(auto_now_add=True)

(5)auto_now

(1)做用:只要數據被更新 當前時間都會被記錄

(2)使用方式

create_time = models.DateField(auto_now=True)

三:關係字段

(1)ForeignKey

(1)做用:

  (1)外鍵類型在ORM中用來表示外鍵關聯關係,通常把ForeignKey字段設置在 '一對多'中'多'的一方。

  (2)ForeignKey能夠和其餘表作關聯關係同時也能夠和自身作關聯關係。

(1)字段參數

(1)to

  (1)做用:設置要關聯的表

(1)to_field

  (1)做用:設置要關聯的表的字段

(1)on_delete

  (1)做用:當刪除關聯表中的數據時,當前表與其關聯的行的行爲。

(1)models.CASCADE

  (1)做用:刪除關聯數據,與之關聯也刪除

(1)db_constraint

  (1)做用:是否在數據庫中建立外鍵約束,默認爲True。

其他字段參數:

models.DO_NOTHING
刪除關聯數據,引起錯誤IntegrityError


models.PROTECT
刪除關聯數據,引起錯誤ProtectedError


models.SET_NULL
刪除關聯數據,與之關聯的值設置爲null(前提FK字段須要設置爲可空)


models.SET_DEFAULT
刪除關聯數據,與之關聯的值設置爲默認值(前提FK字段須要設置默認值)


models.SET

刪除關聯數據,
a. 與之關聯的值設置爲指定值,設置:models.SET(值)
b. 與之關聯的值設置爲可執行對象的返回值,設置:models.SET(可執行對象)

使用方式:

def func():
    return 10

class MyModel(models.Model):
    user = models.ForeignKey(
        to="User",
        to_field="id",
        on_delete=models.SET(func)
    )

(2)OneToOneField

(1)做用:

  (1)一對一字段

  (2)一般一對一字段用來擴展已有字段。(通俗的說就是一我的的全部信息不是放在一張表裏面的,簡單的信息一張表,隱私的信息另外一張表,之間經過一對一外鍵關聯)

(2)字段參數

(1)to

  (1)做用:設置要關聯的表。

to_field

  (1)做用:設置要關聯的字段。

on_delete

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

四:測試操做

(1)做用:在進行通常操做時先配置一下參數,使得咱們能夠直接在Django頁面中運行咱們的測試腳本

(2)在Python腳本中調用Django環境

img

這樣就能夠直接運行你的test.py文件來運行測試

(3)必知必會13條

操做下面的操做以前,咱們實現建立好了數據表,這裏主要演示下面的操做,再也不細講建立準備過程

<1> all(): 查詢全部結果

img

*<2> filter(*kwargs): 它包含了與所給篩選條件相匹配的對象

img

*<3> get(*kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。

img

img

*<4> exclude(*kwargs): 它包含了與所給篩選條件不匹配的對象 img

<5> values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列model的實例化對象,而是一個可迭代的字典序列 img

<6> values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列 img

<7> order_by(*field): 對查詢結果排序

<8> reverse(): 對查詢結果反向排序,請注意reverse()一般只能在具備已定義順序的QuerySet上調用(在model類的Meta中指定ordering或調用order_by()方法)。

<9> distinct(): 從返回結果中剔除重複紀錄(若是你查詢跨越多個表,可能在計算QuerySet時獲得重複的結果。此時可使用distinct(),注意只有在PostgreSQL中支持按字段去重。)

<10> count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。 img

<11> first(): 返回第一條記錄 img

<12> last(): 返回最後一條記錄

<13> exists(): 若是QuerySet包含數據,就返回True,不然返回False

(4)13個必會操做總結

返回QuerySet對象的方法有

(1)all()

(2)filter()

(3)exclude()

(4)order_by()

(5)reverse()

(6)distinct()

特殊的QuerySet

(1)values() 返回一個可迭代的字典序列

(2)values_list() 返回一個可迭代的元祖序列

返回具體對象的

(1)get()

(2)first()

last()

返回布爾值的方法有

exists()

返回數字的方法有

count()

將SQL語句打印到終端顯示:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

將SQL語句打印到終端顯示

五:下劃線單表查詢

(1)表格數據

img

例如:

單表雙下劃線查詢:

# 查詢價格大於200的書籍
    book_obj = models.Book.objects.filter(price__gt=200).first()
    print(book_obj)   # 水滸傳

    # 查詢價格小於200的數據
    book_obj1 = models.Book.objects.filter(price__lt=200).values('title','price')
    print(book_obj1)  # <QuerySet [{'title': '三國演義', 'price': Decimal('99.99')}, {'title': '紅樓夢', 'price': Decimal('199.99')}]>


    # 查詢價格小於等於199.99的書籍
    book_obj = models.Book.objects.filter(price__lte=199.99).values('title','price')
    print(book_obj)  # <QuerySet [{'title': '三國演義', 'price': Decimal('99.99')}, {'title': '紅樓夢', 'price': Decimal('199.99')}]>

    # 查詢價格大於於等於199.99的書籍
    book_obj = models.Book.objects.filter(price__gte=199.99).values('title','price')
    print(book_obj)  # <QuerySet [{'title': '水滸傳', 'price': Decimal('1999.99')}, {'title': '西遊記', 'price': Decimal('999.99')}]>

      # 價格要麼是199,999,1999 python對數字不敏感 因此此時寫成整形
    res = models.Book.objects.filter(price__in=[199,999,1999]).values('title','price')
    print(res)  # <QuerySet [{'title': '紅樓夢', 'price': Decimal('199.00')}, {'title': '水滸傳', 'price': Decimal('1999.00')}, {'title': '西遊記', 'price': Decimal('999.00')}]>

    # 價格範圍在(99-199)顧頭顧尾
    res1 = models.Book.objects.filter(price__range=(99,199)).values('title','price')
    print(res1)  # <QuerySet [{'title': '三國演義', 'price': Decimal('99.00')}, {'title': '紅樓夢', 'price': Decimal('199.00')}]>

    # 拿書名包含sr的
    res2 = models.Book.objects.filter(title__contains='sr')
    print(res2)  # <QuerySet [<Book: 水滸傳sr>]> 僅僅只能去小寫

    res3 = models.Book.objects.filter(title__icontains='sr')
    print(res3)  # <QuerySet [<Book: 三國演義SR>, <Book: 水滸傳sr>]> 忽略大小寫

    # 查詢書名以什麼開頭
    res4 = models.Book.objects.filter(title__startswith='三')
    print(res4)  # <QuerySet [<Book: 三國演義SR>]>
    res5 = models.Book.objects.filter(title__endswith='r')
    print(res5)  # <QuerySet [<Book: 水滸傳sr>]>

六:ForeignKey增刪改查

(1)增長

例如:

# 方法一
    models.Book.objects.create(title='聊齋',price=666.66,publish_id=2)

    # 方法二
    book_obj = models.Publish.objects.filter(pk=2).first()  
    models.Book.objects.create(title='你的名字',price=888.88,publish=book_obj)

PS:

  (1)在方法一中 若是直接寫表格中的字段 須要填寫關聯另一張表的主鍵

  (2)在方法二中 經過獲取另一張表生成的對象 而後在本地關聯這個對象

(2)修改

例如:

  # 數字版的
    models.Book.objects.filter(pk=5).update(title='爲了你 木子李')

    # 傳對象版本的
    publish_obj = models.Publish.objects.filter(name='南方').first()

    models.Book.objects.filter(title='爲了你 木子李').update(publish=publish_obj)

(3)刪除

models.Book.objects.filter(pk=5).delete()

(7)多對多增刪改查

(1)增長

增長:

book_obj = models.Book.objects.filter(pk=10).first()
    res = book_obj.author   # 跳到另一張表
    res.add(1,2)  # 給book添加了兩個做者
    
    author1 = models.Author.objects.filter(pk=1).first()
    author2 = models.Author.objects.filter(pk=2).first()

    book_obj = models.Book.objects.filter(pk=3).first()
    res = book_obj.author  
    res.add(author1,author2)

PS:

  (1)在添加值中 既能夠寫數字也能夠寫對象

  (2)同時支持一次性填寫多個

(2)修改

多表修改:

# 將主鍵爲3的書本 做者改爲id爲5
    book_obj = models.Book.objects.filter(pk=3).first()
    res = book_obj.author
    res.set(5)  # 報錯 'int' object is not iterable 必須傳入一個可迭代對象
    res.set([5,]) #

    # 將主鍵爲10的書本 做者改爲id爲3和5
    book_obj1 = models.Book.objects.filter(pk=10).first()
    author3 = models.Author.objects.filter(pk=3).first()
    author5 = models.Author.objects.filter(pk=5).first()
    res = book_obj1.author
    res.set([author3,author5])

PS:

  (1)set()括號內 須要傳一個可迭代對象   (2)可迭代對象中 能夠是多個數字組合   (3)也能夠是多個對象組合 可是不能混合使用

(3)刪除

多表刪除:

# 將主鍵爲3的書籍做者刪除
    book_obj = models.Book.objects.filter(pk=3).first()
    res = book_obj.author
    res.remove(5)

    # 將主鍵值爲10的對應做者id爲3與5刪除
    book_obj = models.Book.objects.filter(pk=10).first()
    author3 = models.Author.objects.filter(pk=3).first()
    author5 = models.Author.objects.filter(pk=5).first()
    res = book_obj.author
    res.remove(author3,author5)

    # 將主鍵值爲3的書籍所對應的做者都刪除
    book_obj = models.Book.objects.filter(pk=3).first()
    res = book_obj.author
    res.clear()

PS:

  (1)remove()括號內既能夠傳數字 也能夠傳對象

  (2)而且支持傳對個 逗號隔開便可

  (3)clear括號內不須要傳任何參數 直接清除全部

八:多對多三種表格建立方式

(1)方式一:

class Book(models.Model):
    book_name = models.CharField(max_length=255)
    authors = models.ManyToManyField(to='Author')   # 字段建立表格

class Author(models.Model):
    author_name = models.CharField(max_length=255)

PS:

  (1)優勢:第三張虛擬表不須要手動建立

  (2)缺點:因爲第三張表格本身沒法操做 不能再虛擬表進行新的字段添加

(2)方式二

class Book(models.Model):
    book_name = models.CharField(max_length=255)

class Author(models.Model):
    author_name = models.CharField(max_length=255)

class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    create_time = models.DateField(auto_now_add=True)

PS:

  (1)優勢:第三張關聯表 本身建立 能夠進行操做 添加新的字段

  (2)缺點:可是ORM查詢不方便 模型表中沒有關聯字段

(3)方式三

class Book(models.Model):
    book_name = models.CharField(max_length=255)
    '''
    through:與哪張虛擬表作關聯
    through_fields:與虛擬表那個字段作關聯
    
    '''
    authors = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book', 'author'))


class Author(models.Model):
    author_name = models.CharField(max_length=255)


class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    create_time = models.DateField(auto_now_add=True)

PS:

  (1)優勢:虛擬表能夠在建立新的字段,同時有關聯字段

九:跨表查詢

(1)正向與反向的概念

正反向概念:

一對一
正向:author---關聯字段在author表裏--->authordetail        按字段
反向:authordetail---關聯字段在author表裏--->author        按表名小寫


一對多
正向:book---關聯字段在book表裏--->publish        按字段
反向:publish---關聯字段在book表裏--->book        按表名小寫_set.all() 由於一個出版社對應着多個圖書

多對多
正向:book---關聯字段在book表裏--->author        按字段
反向:author---關聯字段在book表裏--->book        按表名小寫_set.all() 由於一個做者對應着多個圖書

PS:

  (1)正向查詢經過關聯字段

  (2)反向查詢經過表名小寫便可

基礎班多表查詢:

# 1.查詢書籍id是3 的出版社名稱
    book_obj = models.Book.objects.filter(pk=3).first()
    res = book_obj.publish  # 關聯字段 調到出版社表格
    print(res.name)  # 南方


    # 2.查詢書籍id是6 的做者姓名
    book_obj = models.Book.objects.filter(pk=6).first()
    res = book_obj.author
    # print(res)  # app01.Author.None 當查詢結果又多個的時候 會顯示None
    res1 = res.all()
    print(res1)  # <QuerySet [<Author: SR>]>


    # 3.查詢做者是SR的家庭住址
    author_obj = models.Author.objects.filter(name='SR').first()
    res = author_obj. author_detail
    print(res.addr)  # 南京

    # 4.查詢出版社是東方出版社出版的書籍
    publish_obj = models.Publish.objects.filter(name='東方').first()
    res = publish_obj.book_set
    print(res)  # app01.Book.None
    print(res.all())  # <QuerySet [<Book: 三國演義SR>]>

PS:

  (1)若是查詢結果有多個的時候 須要用到_set

  (2)不然直接表名小寫便可

正反向查詢:

# 查詢SR這個做者的年齡和手機號
    #正向查詢
    author_obj = models.Author.objects.filter(name='SR').first()
    res = author_obj.author_detail
    print(res.addr)  # 南京
    print(res.phone) # 110
    
    # 反向查詢
    res = models.AuthorDetail.objects.filter(author__name='SR').values('addr','phone')
    print(res)  # <QuerySet [{'addr': '南京', 'phone': 110}]>
    
    # 查詢手機號是130的做者年齡
    # 正向
    author_obj = models.AuthorDetail.objects.filter(phone=130).first()
    res = author_obj.author
    print(res.age)  # 18

    # 反向
    res = models.Author.objects.filter(author_detail__phone=130).values('age')
    print(res)  # <QuerySet [{'age': 18}]>
    
    # 查詢書籍id是6 的做者的電話號碼
    book_obj = models.Book.objects.filter(pk=6).values('author__author_detail__phone')
    print(book_obj)  # <QuerySet [{'author__author_detail__phone': 110}]>

  # 1.查詢出版社爲北方出版社的全部圖書的名字和價格
    res = models.Publish.objects.filter(name='北方出版社').values('book__title','book__price')
    print(res)

    # 2.查詢北方出版社出版的價格大於19的書
    res = models.Book.objects.filter(price__gt=19,publish__name='北方出版社').values('title','publish__name')
    print(res)

(2)聚合查詢/分組查詢:

聚合查詢:

# 聚合查詢(aggregate)

from django.db.models import Max,Min,Count,Avg,Sum

# res = models.Book.objects.aggregate(Sum('price'))
res1 = models.Book.objects.aggregate(Avg('price'))
res2 = models.Book.objects.aggregate(Count('price'))
res3 = models.Book.objects.aggregate(Max('price'))
res4 = models.Book.objects.aggregate(Min('price'))
res5 = models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price'))

分組查詢:

# 統計每一本書的做者個數
    from django.db.models import Max, Min, Count, Avg, Sum  
    res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title')  # author_num 其別名
    print(res)

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

    # 統計不止一個做者的圖書
    res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)
    print(res)

(3)F/Q查詢

  (1)F查詢:

    (1)能夠進行多個字段的比較

    (2)本質就是從數據庫獲取某個字段的值

F查詢:

# 查詢庫存數大於賣出數的書籍
    res = models.Book.objects.filter(kucun__gt=F('maichu'))
    print(res)


    # 將書籍庫存數所有增長1000
    models.Book.objects.update(kucun=F('kucun')+1000)

    # 把全部書名後面加上'新款'

    from django.db.models.functions import Concat
    from django.db.models import Value

    ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))
    models.Book.objects.update(title = F('title')+'新款')  # 不能這麼寫

  (2)Q查詢

    (1)filter() 等方法中逗號隔開的條件是與的關係。

    (2)若是你須要執行更復雜的查詢(例如OR語句),你可使用Q對象

Q查詢:

from django.db.models import Q
    # 查詢書籍名稱是三國演義或者價格是444.44
    res = models.Book.objects.filter(title='三國演義',price=444.44)  # filter只支持and關係
    res1 = models.Book.objects.filter(Q(title='三國演義'),Q(price=444))  # 若是用逗號 那麼仍是and關係
    res2 = models.Book.objects.filter(Q(title='三國演義')|Q(price=444))
    res3 = models.Book.objects.filter(~Q(title='三國演義')|Q(price=444))
    print(res2)

Q高階用法:

q = Q()
    q.connector = 'or'  # 修改查詢條件的關係   默認是and
    q.children.append(('title__contains','三國演義'))  # 往列表中添加篩選條件
    q.children.append(('price__gt',444))  # 往列表中添加篩選條件
    res = models.Book.objects.filter(q)  # filter支持你直接傳q對象  可是默認仍是and關係
    print(res)

十:事務

(1)做用:

  (1)將多個sql操做變成原子性操做,要麼同時成功 若是有一條數據失敗了 則回滾

  (2)保證數據的一致性

(2)使用方式:

# 事務
    # 買一本 跟老男孩學Linux 書
    # 在數據庫層面要作的事兒
    # 1. 建立一條訂單數據
    # 2. 去產品表 將賣出數+1, 庫存數-1
    from django.db.models import F
    from django.db import transaction
    # 開啓事務處理
    try:
        with transaction.atomic():
            # 建立一條訂單數據
            models.Order.objects.create(num="110110111", product_id=1, count=1)
            # 能執行成功
            models.Product.objects.filter(id=1).update(kucun=F("kucun")-1, maichu=F("maichu")+1)
    except Exception as e:
        print(e)
相關文章
相關標籤/搜索