05-01 Django之模型層第一篇:單表操作


Django之模型層第一篇:單表操作

一 ORM簡介

​ 我們在使用Django框架開發web應用的過程中,不可避免地會涉及到數據的管理操作(如增、刪、改、查),而一旦談到數據的管理操作,就需要用到數據庫管理軟件,例如mysql、oracle、Microsoft SQL Server等。

​ 如果應用程序需要操作數據(比如將用戶注冊信息永久存放起來),那么我們需要在應用程序中編寫原生sql語句,然后使用pymysql模塊遠程操作mysql數據庫,詳見圖1

但是直接編寫原生sql語句會存在兩方面的問題,嚴重影響開發效率,如下

#1. sql語句的執行效率:應用開發程序員需要耗費一大部分精力去優化sql語句
#2. 數據庫遷移:針對mysql開發的sql語句無法直接應用到oracle數據庫上,一旦需要遷移數據庫,便需要考慮跨平台問題

為了解決上述問題,django引入了ORM的概念,ORM全稱Object Relational Mapping,即對象關系映射,是在pymysq之上又進行了一層封裝,對於數據的操作,我們無需再去編寫原生sql,取代代之的是基於面向對象的思想去編寫類、對象、調用相應的方法等,ORM會將其轉換/映射成原生SQL然后交給pymysql執行,詳見圖2

。。。。。。插圖1

插圖1

原生SQL與ORM的對應關系示例如下

插圖2

若圖片需要修改,則查看地址:https://www.processon.com/diagraming/588d8be2e4b098bf4d1ecb1d

插圖2

如此,開發人員既不用再去考慮原生SQL的優化問題,也不用考慮數據庫遷移的問題,ORM都幫我們做了優化且支持多種數據庫,這極大地提升了我們的開發效率,下面就讓我們來詳細學習ORM的使用吧

1554205022372

二 單表操作

2.1 按步驟創建表

2.1.1 創建django項目,新建名為app01的app,在app01的models.py中創建模型
class Employee(models.Model): # 必須是models.Model的子類
    id=models.AutoField(primary_key=True)

    name=models.CharField(max_length=16)

    gender=models.BooleanField(default=1)

    birth=models.DateField()

    department=models.CharField(max_length=30)

    salary=models.DecimalField(max_digits=10,decimal_places=1)
2.1.2 django的orm支持多種數據庫,如果想將上述模型轉為mysql數據庫中的表,需要settings.py中
# 刪除\注釋掉原來的DATABASES配置項,新增下述配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # 使用mysql數據庫
        'NAME': 'db1',          # 要連接的數據庫
        'USER': 'root',         # 鏈接數據庫的用於名
        'PASSWORD': '',         # 鏈接數據庫的用於名                  
        'HOST': '127.0.0.1',    # mysql服務監聽的ip  
        'PORT': 3306,           # mysql服務監聽的端口  
        'ATOMIC_REQUEST': True, #設置為True代表同一個http請求所對應的所有sql都放在一個事務中執行 
                                #(要么所有都成功,要么所有都失敗),這是全局性的配置,如果要對某個
                                #http請求放水(然后自定義事務),可以用non_atomic_requests修飾器 
        'OPTIONS': {
            "init_command": "SET storage_engine=INNODB", #設置創建表的存儲引擎為INNODB
        }
    }
}
2.1.3 在鏈接mysql數據庫前,必須事先創建好數據庫
mysql> create database db1; # 數據庫名必須與settings.py中指定的名字對應上
2.1.4 其實python解釋器在運行django程序時,django的orm底層操作數據庫的python模塊默認是mysqldb而非pymysql,然而對於解釋器而言,python2.x解釋器支持的操作數據庫的模塊是mysqldb,而python3.x解釋器支持的操作數據庫的模塊則是pymysql,,毫無疑問,目前我們的django程序都是運行於python3.x解釋器下,於是我們需要修改django的orm默認操作數據庫的模塊為pymysql,具體做法如下

插圖3

插圖3

2.1.5 確保配置文件settings.py中的INSTALLED_APPS中添加我們創建的app名稱,django2.x與django1.x處理添加方式不同
# django1.x版本,在下述列表中新增我們的app名字即可
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',
    # 'app02' # 若有新增的app,依次添加即可
]

# django2.x版本,可能會幫我們自動添加app,只是換了一種添加方式
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config', # 如果默認已經添加了,則無需重復添加
    # 'app02.apps.App02Config', # 若有新增的app,按照規律依次添加即可
]

2.1.6 如果想打印orm轉換過程中的sql,需要在settings中進行配置日志:
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}
2.1.7 最后在命令行中執行兩條數據庫遷移命令,即可在指定的數據庫db1中創建表 :
$ python manage.py makemigrations
$ python manage.py migrate

# 注意:
# 1、makemigrations只是生成一個數據庫遷移記錄的文件,而migrate才是將更改真正提交到數據庫執行
# 2、數據庫遷移記錄的文件存放於app01下的migrations文件夾里
# 3、了解:使用命令python manage.py showmigrations可以查看沒有執行migrate的文件

注意1:在使用的是django1.x版本時,如果報如下錯誤

django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.3 or newer is required; you have 0.7.11.None

那是因為MySQLclient目前只支持到python3.4,如果使用的更高版本的python,需要找到文件C:\Programs\Python\Python36-32\Lib\site-packages\Django-2.0-py3.6.egg\django\db\backends\mysql\base.py
這個路徑里的文件(mac或linux請在終端執行pip show django查看django的安裝路徑,找到base.py即可)

# 注釋下述兩行內容即可
if version < (1, 3, 3):
     raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)

注意2:當我們直接去數據庫里查看生成的表時,會發現數據庫中的表與orm規定的並不一致,這完全是正常的,事實上,orm的字段約束就是不會全部體現在數據庫的表中,比如我們為字段gender設置的默認值default=1,去數據庫中查看會發現該字段的default部分為null

mysql> desc app01_employee; # 數據庫中標簽前會帶有前綴app01_
+------------+---------------+------+-----+---------+----------------+
| Field      | Type          | Null | Key | Default | Extra          |
+------------+---------------+------+-----+---------+----------------+
| id         | int(11)       | NO   | PRI | NULL    | auto_increment |
| name       | varchar(16)   | NO   |     | NULL    |                |
| gender     | tinyint(1)    | NO   |     | NULL    |                |
| birth      | date          | NO   |     | NULL    |                |
| department | varchar(30)   | NO   |     | NULL    |                |
| salary     | decimal(10,1) | NO   |     | NULL    |                |
+------------+---------------+------+-----+---------+----------------+

,雖然數據庫沒有增加默認值,但是我們在使用orm插入值時,完全為gender字段插入空,orm會按照自己的約束將空轉換成默認值后,再提交給數據庫執行

2.1.8 在表生成之后,如果需要增加、刪除、修改表中字段,需要這么做
# 一:增加字段
#1.1、在模型類Employee里直接新增字段,強調:對於orm來說,新增的字段必須用default指定默認值
publish = models.CharField(max_length=12,default='人民出版社',null=True)
#1.2、重新執行那兩條數據庫遷移命令


# 二:刪除字段
#2.1 直接注釋掉字段
#2.2 重新執行那兩條數據庫遷移命令

# 三:修改字段
#2.1 將模型類中字段修改
#2.2 重新執行那兩條數據庫遷移命令

2.2 添加記錄

方式一:

# 1、用模型類創建一個對象,一個對象對應數據庫表中的一條記錄
obj = Employee(name="Egon", gender=0, birth='1997-01-27', department="財務部", salary=100.1)
# 2、調用對象下的save方法,即可以將一條記錄插入數據庫
obj.save()

方式二:

# 每個模型表下都有一個objects管理器,用於對該表中的記錄進行增刪改查操作,其中增加操作如下所示
obj = Employee.objects.create(name="Egon", gender=0, birth='1997-01-27', department="財務部", salary=100.1)

2.3 查詢記錄

2.3.1 查詢API

模型Employee對應表app01_employee,表app01_employee中的每條記錄都對應類Employee的一個對象,我們以該表為例,來介紹查詢API,讀者可以自行添加下述記錄,然后配置url、編寫視圖測試下述API

mysql> select * from app01_employee;
+----+-------+--------+------------+------------+--------+
| id | name  | gender | birth      | department | salary |
+----+-------+--------+------------+------------+--------+
|  1 | Egon  |      0 | 1997-01-27 | 財務部     |  100.1 |
|  2 | Kevin |      1 | 1998-02-27 | 技術部     |   10.1 |
|  3 | Lili  |      0 | 1990-02-27 | 運營部     |   20.1 |
|  4 | Tom   |      1 | 1991-02-27 | 運營部     |   30.1 |
|  5 | Jack  |      1 | 1992-02-27 | 技術部     |   11.2 |
|  6 | Robin |      1 | 1988-02-27 | 技術部     |  200.3 |
|  7 | Rose  |      0 | 1989-02-27 | 財務部     |   35.1 |
|  8 | Egon  |      0 | 1997-01-27 | 財務部     |  100.1 |
|  9 | Egon  |      0 | 1997-01-27 | 財務部     |  100.1 |
+----+-------+--------+------------+------------+--------+

每個模型表下都有一個objects管理器,用於對該表中的記錄進行增刪改查操作,其中查詢操作如下所示

Part1:

!!!強調!!!:下述方法(除了count外)的返回值都是一個模型類Employee的對象,為了后續描述方便,我們統一將模型類的對象稱為"記錄對象",每一個”記錄對象“都唯一對應表中的一條記錄,

# 1. get(**kwargs)
# 1.1: 有參,參數為篩選條件
# 1.2: 返回值為一個符合篩選條件的記錄對象(有且只有一個),如果符合篩選條件的對象超過一個或者沒有都會拋出錯誤。
obj=Employee.objects.get(id=1)
print(obj.name,obj.birth,obj.salary) #輸出:Egon 1997-01-27 100.1

# 2、first()
# 2.1:無參
# 2.2:返回查詢出的第一個記錄對象
obj=Employee.objects.first() # 在表所有記錄中取第一個
print(obj.id,obj.name) # 輸出:1 Egon

# 3、last()
# 3.1: 無參
# 3.2: 返回查詢出的最后一個記錄對象
obj = Employee.objects.last() # 在表所有記錄中取最后一個
print(obj.id, obj.name)  # 輸出:9 Egon

# 4、count():
# 4.1:無參
# 4.2:返回包含記錄對象的總數量
res = Employee.objects.count() # 統計表所有記錄的個數
print(res) # 輸出:9

# 注意:如果我們直接打印Employee的對象將沒有任何有用的提示信息,我們可以在模型類中定義__str__來進行定制
class Employee(models.Model):
    ......
	# 在原有的基礎上新增代碼如下
    def __str__(self):
        return "<%s:%s>" %(self.id,self.name)
# 此時我們print(obj)顯示的結果就是: <本條記錄中id字段的值:本條記錄中name字段的值>

1554205141851

Part2:

!!!強調!!!:下述方法查詢的結果都有可能包含多個記錄對象,為了存放查詢出的多個記錄對象,django的ORM自定義了一種數據類型Queryeset,所以下述方法的返回值均為QuerySet類型的對象,QuerySet對象中包含了查詢出的多個記錄對象

# 1、filter(**kwargs):
# 1.1:有參,參數為過濾條件
# 1.2:返回值為QuerySet對象,QuerySet對象中包含了符合過濾條件的多個記錄對象
queryset_res=Employee.objects.filter(department='技術部')
# print(queryset_res) # 輸出: <QuerySet [<Employee: <2:Kevin>>, <Employee: <5:Jack>>, <Employee: <6:Robin>>]>

# 2、exclude(**kwargs)
# 2.1: 有參,參數為過濾條件
# 2.2: 返回值為QuerySet對象,QuerySet對象中包含了不符合過濾條件的多個記錄對象
queryset_res=Employee.objects.exclude(department='技術部')

# 3、all()
# 3.1:無參
# 3.2:返回值為QuerySet對象,QuerySet對象中包含了查詢出的所有記錄對象
queryset_res = Employee.objects.all() # 查詢出表中所有的記錄對象

# 4、order_by(*field):
# 4.1:有參,參數為排序字段,可以指定多個字段,在字段1相同的情況下,可以按照字段2進行排序,以此類推,默認升序排列,在字段前加橫桿代表降序排(如"-id")
# 4.2:返回值為QuerySet對象,QuerySet對象中包含了排序好的記錄對象
queryset_res = Employee.objects.order_by("salary","-id") # 先按照salary字段升序排,如果salary相同則按照id字段降序排

# 5、values(*field)
# 5.1:有參,參數為字段名,可以指定多個字段
# 5.2:返回值為QuerySet對象,QuerySet對象中包含的並不是一個個的記錄對象,而上多個字典,字典的key即我們傳入的字段名
queryset_res = Employee.objects.values('id','name')
print(queryset_res) # 輸出:<QuerySet [{'id': 1, 'name': 'Egon'}, {'id': 2, 'name': 'Kevin'}, ......]>
print(queryset_res[0]['name']) # 輸出:Egon

# 6、values_list(*field):
# 6.1:有參,參數為字段名,可以指定多個字段
# 6.2:返回值為QuerySet對象,QuerySet對象中包含的並不是一個個的記錄對象,而上多個小元組,字典的key即我們傳入的字段名
queryset_res = Employee.objects.values_list('id','name')
print(queryset_res) # 輸出:<QuerySet [(1, 'Egon'), (2, 'Kevin'),), ......]>
print(queryset_res[0][1]) # 輸出:Egon

Part3:

Part2中所示查詢API的返回值都是QuerySet類型的對象,QuerySet類型是django ORM自定義的一種數據類型,專門用來存放查詢出的多個記錄對象,該類型的特殊之處在於
1、queryset類型類似於python中的列表,支持索引操作

# 過濾出符合條件的多個記錄對象,然后存放到QuerySet對象中
queryset_res=Employee.objects.filter(department='技術部') 
# 按照索引從QuerySet對象中取出第一個記錄對象
obj=queryset_res[0]
print(obj.name,obj.birth,obj.salary)

2、管理器objects下的方法queryset下同樣可以調用,並且django的ORM支持鏈式操作,於是我們可以像下面這樣使用

# 簡單示范:
res=Employee.objects.filter(gender=1).order_by('-id').values_list('id','name')
print(res) # 輸出:<QuerySet [(6, 'Robin'), (5, 'Jack'), (4, 'Tom'), (2, 'Kevin')]>

Part4:

其他查詢API

# 1、reverse():
# 1.1:無參
# 1.2:對排序的結果取反,返回值為QuerySet對象
queryset_res = Employee.objects.order_by("salary", "-id").reverse()

# 2、exists():
# 2.1:無參
# 2.2:返回值為布爾值,如果QuerySet包含數據,就返回True,否則返回False
res = Employee.objects.filter(id=100).exists()
print(res)  # 輸出:False

# 3、distinct():
# 3.1:如果使用的是Mysql數據庫,那么distinct()無需傳入任何參數
# 3.2:從values或values_list的返回結果中剔除重復的記錄對象,返回值為QuerySet對象
res = Employee.objects.filter(name='Egon').values('name', 'salary').distinct()
print(res) # 輸出:<QuerySet [{'name': 'Egon', 'salary': Decimal('100.1')}]>

res1 = Employee.objects.filter(name='Egon').values_list('name', 'salary').distinct()
print(res1) # 輸出:<QuerySet [('Egon', Decimal('100.1'))]>

2.3.2 基於雙下划線的模糊查詢

插圖4

插圖4

1554205197411

2.3.3 F與Q查詢

F查詢

在上面所有的例子中,我們在進行條件過濾時,都只是用某個字段與某個具體的值做比較。如果我們要對兩個字段的值做比較,那該怎么做呢?

Django 提供 F() 來做這樣的比較。F() 的實例可以在查詢中引用字段,來比較兩個不同字段的值,如下

# 一張書籍表中包含字段:評論數commentNum、收藏數keepNum,要求查詢:評論數大於收藏數的書籍
from django.db.models import F
Book.objects.filter(commnetNum__lt=F('keepNum'))

Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操作

# 查詢評論數大於收藏數2倍的書籍
from django.db.models import F
Book.objects.filter(commnetNum__lt=F('keepNum')*2)

修改操作也可以使用F函數,比如將每一本書的價格提高30元:

Book.objects.all().update(price=F("price")+30) 

更新字段等於字段本身再拼接一個字符串應該這樣做

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

Employee.objects.filter(nid__lte=3).update(name=Concat(F('name'),Value('_sb')))

Q查詢

filter() 等方法中逗號分隔開的多個關鍵字參數都是邏輯與(AND) 的關系。 如果我們需要使用邏輯或(OR)來連接多個條件,就用到了Django的Q對象

可以將條件傳給類Q來實例化出一個對象,Q的對象可以使用&| 操作符組合起來,&等同於and,|等同於or

from django.db.models import Q
Employee.objects.filter(Q(id__gt=5) | Q(name="Egon"))

# 等同於sql:select * from app01_employee where id < 5 or name = 'Egon';

Q 對象可以使用~ 操作符取反,相當於NOT

from django.db.models import Q
Employee.objects.filter(~Q(id__gt=5) | Q(name="Egon"))

# 等同於sql:select * from app01_employee where not (id < 5) or name = 'Egon';

當我們的過濾條件中既有or又有and,則需要混用Q對象與關鍵字參數,但Q 對象必須位於所有關鍵字參數的前面

from django.db.models import Q
Employee.objects.filter(Q(id__gt=5) | Q(name="Egon"),salary__lt=100)

# 等同於sql:select * from app01_employee where (id < 5 or name = 'Egon') and salary < 100;

1554205249918

2.3.4 聚合查詢

聚合查詢aggregate()是把所有查詢出的記錄對象整體當做一個組,我們可以搭配聚合函數來對整體進行一個聚合操作

from django.db.models import Avg, Max, Sum, Min, Max, Count # 導入聚合函數

# 1. 調用objects下的aggregate()方法,會把表中所有記錄對象整體當做一組進行聚合
res1=Employee.objects.aggregate(Avg("salary")) # select avg(salary) as salary__avg from app01_employee;
print(res1) # 輸出:{'salary__avg': 70.73}

# 2、aggregate()會把QuerySet對象中包含的所有記錄對象當成一組進行聚合
res2=Employee.objects.all().aggregate(Avg("salary")) # select avg(salary) as salary__avg from app01_employee;
print(res2) # 輸出:{'salary__avg': 70.73}

res3=Employee.objects.filter(id__gt=3).aggregate(Avg("salary")) # select avg(salary) as salary__avg from app01_employee where id > 3;
print(res3) # 輸出:{'salary__avg': 71.0}

aggregate()的返回值為字典類型,字典的key是由”聚合字段的名稱___聚合函數的名稱”合成的,例如

Avg("salary") 合成的名字為 'salary__avg'

若我們想定制字典的key名,我們可以指定關鍵參數,如下

res1=Employee.objects.all().aggregate(avg_sal=Avg('salary')) # select avg(salary) as avg_sal from app01_employee;

print(res1) # 輸出:{'avg_sal': 70.73} # 關鍵字參數名就會被當做字典的key

如果我們想得到多個聚合結果,那就需要為aggregate傳入多個參數

res1=Employee.objects.all().aggregate(nums=Count('id'),avg_sal=Avg('salary'),max_sal=Max('salary')) 
# 相當於SQL:select count(id) as nums,avg(salary) as avg_sal,max(salary) as max_sal from app01_employee;

print(res1) # 輸出:{'nums': 10, 'avg_sal': 70.73, 'max_sal': Decimal('200.3')}

1554205296521

2.3.5 分組查詢

分組查詢annotate()相當於sql語句中的group by,是在分組后,對每個組進行單獨的聚合,需要強調的是,在進行單表查詢時,annotate()必須搭配values()使用:values("分組字段").annotate(聚合函數),如下

# 表中記錄
mysql> select * from app01_employee;
+----+-------+--------+------------+------------+--------+
| id | name  | gender | birth      | department | salary |
+----+-------+--------+------------+------------+--------+
|  1 | Egon  |      0 | 1997-01-27 | 財務部     |  100.1 |
|  2 | Kevin |      1 | 1998-02-27 | 技術部     |   10.1 |
|  3 | Lili  |      0 | 1990-02-27 | 運營部     |   20.1 |
|  4 | Tom   |      1 | 1991-02-27 | 運營部     |   30.1 |
|  5 | Jack  |      1 | 1992-02-27 | 技術部     |   11.2 |
|  6 | Robin |      1 | 1988-02-27 | 技術部     |  200.3 |
|  7 | Rose  |      0 | 1989-02-27 | 財務部     |   35.1 |
+----+-------+--------+------------+------------+--------+

# 查詢每個部門下的員工數
res=Employee.objects.values('department').annotate(num=Count('id')) 
# 相當於sql:
# select department,count(id) as num from app01_employee group by department;

print(res) 
# 輸出:<QuerySet [{'department': '財務部', 'num': 2}, {'department': '技術部', 'num': 3}, {'department': '運營部', 'num': 2}]>

跟在annotate前的values方法,是用來指定分組字段,即group by后的字段,而跟在annotate后的values方法,則是用來指定分組后要查詢的字段,即select 后跟的字段

res=Employee.objects.values('department').annotate(num=Count('id')).values('num')
# 相當於sql:
# select count(id) as num from app01_employee group by department;

print(res)
# 輸出:<QuerySet [{'num': 2}, {'num': 3}, {'num': 2}]>

跟在annotate前的filter方法表示where條件,跟在annotate后的filter方法表示having條件,如下

# 查詢男員工數超過2人的部門名
res=Employee.objects.filter(gender=1).values('department').annotate(male_count=Count("id")).filter(male_count__gt=2).values('department')

print(res) # 輸出:<QuerySet [{'department': '技術部'}]>

# 解析:
# 1、跟在annotate前的filter(gender=1) 相當於 where gender = 1,先過濾出所有男員工信息
# 2、values('department').annotate(male_count=Count("id")) 相當於group by department,對過濾出的男員工按照部門分組,然后聚合出每個部門內的男員工數賦值給字段male_count
# 3、跟在annotate后的filter(male_count__gt=2) 相當於 having male_count > 2,會過濾出男員工數超過2人的部門
# 4、最后的values('department')代表從最終的結果中只取部門名

總結:

1、values()在annotate()前表示group by的字段,在后表示取值
1、filter()在annotate()前表示where條件,在后表示having

需要注意的是,如果我們在annotate前沒有指定values(),那默認用表中的id字段作為分組依據,而id各不相同,如此分組是沒有意義的,如下

res=Employee.objects.annotate(Count('name')) # 每條記錄都是一個分組
res=Employee.objects.all().annotate(Count('name')) # 同上

2.4 修改記錄

2.5.1 直接修改單條記錄

可以修改記錄對象屬性的值,然后執行save方法從而完成對單條記錄的直接修改

# 1、獲取記錄對象
obj=Employee.objects.filter(name='Egon')[0]
# 2、修改記錄對象屬性的值
obj.name='EGON'
obj.gender=1
# 3、重新保存
obj.save()

2.5.2 修改QuerySet中的所有記錄對象

QuerySet對象下的update()方法可以更QuerySet中包含的所有對象,該方法會返回一個整型數值,表示受影響的記錄條數(相當於sql語句執行結果的rows)

queryset_obj=Employee.objects.filter(id__gt=5)
rows=queryset_obj.update(name='EGON',gender=1)

2.5 刪除記錄

2.5.1 直接刪除單條記錄

可以直接調用記錄對象下的delete方法,該方法運行時立即刪除本條記錄而不返回任何值,如下

obj=Employee.objects.first()
obj.delete()

2.5.2 刪除QuerySet中的所有記錄對象

每個 QuerySet下也都有一個 delete() 方法,它一次性刪除 QuerySet 中所有的對象(如果QuerySet對象中只有一個記錄對象,那也就只刪一條),如下

queryset_obj=Employee.objects.filter(id__gt=5)
rows=queryset_obj.delete()

需要強調的是管理objects下並沒有delete方法,這是一種保護機制,是為了避免意外地調用 Employee.objects.delete() 方法導致所有的記錄被誤刪除從而跑路。但如果你確認要刪除所有的記錄,那么你必須顯式地調用管理器下的all方法,拿到一個QuerySet對象后才能調用delete方法刪除所有

Employee.objects.all().delete()

1554205424515


免責聲明!

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



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