[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環境
這樣就能夠直接運行你的test.py文件來運行測試
(3)必知必會13條
操做下面的操做以前,咱們實現建立好了數據表,這裏主要演示下面的操做,再也不細講建立準備過程
<1> all(): 查詢全部結果
*<2> filter(*kwargs): 它包含了與所給篩選條件相匹配的對象
*<3> get(*kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。
*<4> exclude(*kwargs): 它包含了與所給篩選條件不匹配的對象
<5> values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列model的實例化對象,而是一個可迭代的字典序列
<6> values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列
<7> order_by(*field): 對查詢結果排序
<8> reverse(): 對查詢結果反向排序,請注意reverse()一般只能在具備已定義順序的QuerySet上調用(在model類的Meta中指定ordering或調用order_by()方法)。
<9> distinct(): 從返回結果中剔除重複紀錄(若是你查詢跨越多個表,可能在計算QuerySet時獲得重複的結果。此時可使用distinct(),注意只有在PostgreSQL中支持按字段去重。)
<10> count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。
<11> first(): 返回第一條記錄
<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)表格數據
例如:
單表雙下劃線查詢:
# 查詢價格大於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)