Django ORM單表操作
Django 測試環境搭建
注意pycharm連結資料庫都需要提前下載對應的驅動,自帶的sqlite3對日期格式資料不敏感,如果後續業務需要使用日期輔助篩選資料那麼不推薦使用sqlite3
搭建方式
- 任意建立一個py檔案,在該檔案內書寫固定的配置
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day06.settings")
import django
django.setup()
- 直接使用pycharm提供的
python console
ORM 建立表
# Mysql配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'orm_simple',
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': 'root',
'CHARSET':'utf8'
}
}
'''__init__.py'''
import pymysql
pymysql.install_as_MySQLdb()
建立表
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5,decimal_places=2)
publish = models.CharField(max_length=32)
publish_data = models.DateField() # 出版時間
# 路由
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/', views.book),
]
ORM 新增資料
有兩種新增資料的方式:
- 方式一:模型類例項化物件
- 方式二:通過 ORM 提供的 objects 提供的方法 create 來實現(推薦)
from django.shortcuts import render,HttpResponse
from app01 import models
def book(request):
'''新增資料的兩種方式'''
# 方式1
book_obj = models.Book(title='Python',price='99',publish='Hammer出版社',publish_data='2022-2-2')
book_obj.save()
# 方式2
models.Book.objects.create(title='Java',price='88',publish='Hans出版社',publish_data='2021-2-1')
return HttpResponse('<p>資料新增成功</p>')
ORM 查詢資料
all 查詢
all()
方法查詢所有資料,返回一個QuerySet物件,類似list,可以通過索引來獲取列表中的物件,這裡不支援負索引
from django.shortcuts import render,HttpResponse
from app01 import models
def book(request):
book_obj = models.Book.objects.all()
print(book_obj) # <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]>
print(book_obj[0]) # Book object (1)
print(book_obj.first()) # Book object (1) 等價於[0]
print(book_obj.first().title) # Python 獲取值
return HttpResponse('<p>資料查詢成功</p>')
filter 查詢
filter() 方法用於查詢符合條件的資料
返回的是 QuerySet 型別資料,類似於 list,裡面放的是滿足條件的模型類的物件,可用索引下標取出模型類的物件;
def book(request):
book_obj = models.Book.objects.filter(pk=2)
print(book_obj)
print(book_obj.first().title) # JavaScript
book_obj1 = models.Book.objects.filter(title='JavaScript',price='99')
print(book_obj1.first().pk) # 2
return HttpResponse('<p>資料查詢成功</p>')
exclude 取反查詢
exclude() 方法用於查詢不符合條件的資料,返回的是 QuerySet 型別資料,類似於 list,裡面放的是不滿足條件的模型類的物件,可用索引下標取出模型類的物件;
def book(request):
book_obj = models.Book.objects.exclude(pk=2)
print(book_obj) # <QuerySet [<Book: Python>, <Book: C>, <Book: PHP>, <Book: C++>, <Book: 資料結構>]>
for i in book_obj.all():
print(i.title) # Python C PHP C++ 資料結構
return HttpResponse('<p>資料查詢成功</p>')
get 查詢
get() 方法用於查詢符合條件的返回模型類的物件符合條件的物件只能為一個,如果符合篩選條件的物件超過了一個或者沒有一個都會丟擲錯誤
區別filter()如果獲取不到符合條件的資料,返回一個空物件,不報錯
from django.shortcuts import render,HttpResponse
from app01 import models
def book(request):
book_obj = models.Book.objects.get(pk=1)
print(book_obj)
return HttpResponse('<p>資料查詢成功</p>')
order_by 排序
order_by() 方法用於對查詢結果進行排序,返回的是 QuerySet型別資料,類似於list,裡面放的是排序後的模型類的物件,可用索引下標取出模型類的物件
- 引數的欄位名要加引號
- 降序為在欄位前面加個負號 -
def book(request):
# 升序排序
book_obj = models.Book.objects.order_by('id')
for i in book_obj:
print(i.title) # Python JavaScript C PHP C++ 資料結構
# 降序排序
book_obj1 = models.Book.objects.order_by('-id')
for i in book_obj1:
print(i.title) # 資料結構 C++ PHP C JavaScript Python
return HttpResponse('<p>資料查詢成功</p>')
reverse 反轉
reverse() 方法用於對查詢結果進行反轉,返回的是 QuerySe t型別資料,類似於 list,裡面放的是反轉後的模型類的物件,可用索引下標取出模型類的物件
使用反轉函式前先排序
def book(request):
# 按照價格升序排列:降序再反轉
books = models.Book.objects.order_by("-price").reverse()
return HttpResponse("<p>查詢成功!</p>")
count 彙總數量
count() 方法用於查詢資料的數量返回的資料是整數
def book(request):
book_obj = models.Book.objects.count()
print(book_obj) # 查詢所有資料的數量>>>6
book_obj1 = models.Book.objects.filter(price=200).count() # 查詢符合條件資料的數量
return HttpResponse('<p>資料查詢成功</p>')
exists 判斷
exists() 方法用於判斷查詢的結果 QuerySet 列表裡是否有資料,返回的資料型別是布林,有為 true,沒有為 false。
from django.shortcuts import render,HttpResponse
from app01 import models
def book(request):
books = models.Book.objects.exists()
# True
books = models.Book.objects.count().exists()
# 報錯,判斷的資料型別只能為QuerySet型別資料,不能為整型
books = models.Book.objects.first().exists()
# 報錯,判斷的資料型別只能為QuerySet型別資料,不能為模型類物件
return HttpResponse("<p>查詢成功!</p>")
values 查詢欄位
返回的是 QuerySet 型別資料,類似於 list,裡面不是模型類的物件,而是一個可迭代的字典序列,字典裡的鍵是欄位,值是資料
def book(request):
book_obj = models.Book.objects.values('price','title')
print(book_obj) # 返回所有price和title欄位,以列表套字典的形式
# <QuerySet [{'price': Decimal('99.00'), 'title': 'Python'}]
book_obj1 = models.Book.objects.filter(pk=1).values('title')
print(book_obj1,book_obj[0].get('title')) # <QuerySet [{'title': 'Python'}]> Python
return HttpResponse('<p>資料查詢成功</p>')
values_list 查詢部分欄位
values_list() 方法用於查詢部分欄位的資料,values_list() 方法用於查詢部分欄位的資料
def book(request):
book_obj = models.Book.objects.values_list('price','title')
print(book_obj) # 返回所有price和title欄位,以列表套元組的形式
# <QuerySet [(Decimal('99.00'), 'Python')]
for title in book_obj:
print(title[1]) # 獲取所有title
return HttpResponse('<p>資料查詢成功</p>')
values和values_list區別
- values查詢返回的結果是列表套字典的形式,欄位名和資料都能夠獲取到
- values_list查詢返回的結果是列表套元組的形式,只返回資料
distinct 去重
distinct() 方法用於對資料進行去重,返回的是 QuerySet 型別資料
注意:
- 對模型類的物件去重沒有意義,因為每個物件都是一個不一樣的存在(主鍵不一樣),去重的前提是資料必須是一模一樣,不能加主鍵,有unique的也沒意義
- distinct() 一般是聯合 values 或者 values_list 使用
from django.shortcuts import render,HttpResponse
from app01 import models
def book(request):
# 查詢一共有多少個出版社
books = models.Book.objects.values_list("publish").distinct() # 可以去重
books = models.Book.objects.distinct()
# 對模型類的物件去重沒有意義,因為每個物件都是一個不一樣的存在,主鍵不一樣
return HttpResponse("<p>查詢成功!</p>")
ORM 雙下劃線方法
__in
類似sql的成員運算,用於讀取區間,= 號後面為列表
注意:filter 中運算子號只能使用等於號 = ,不能使用大於號 > ,小於號 < ,等等其他符號
- 格式:欄位__in = [a,b]
def book(request):
book_obj = models.Book.objects.filter(price__in=[100,300])
print(book_obj) # <QuerySet [<Book: Book object (2)>, <Book: Book object (22)>]>
return HttpResponse('<p>資料查詢成功</p>')
__gt __gte
大於、大於等於
# 價格大於100的資料
book_obj = models.Book.objects.filter(price__gt=100)
# 價格大於等於100的資料
book_obj = models.Book.objects.filter(price__gte=100)
__lt __lte
小於、小於等於
# 價格小於100的資料
book_obj = models.Book.objects.filter(price__lt=100)
# 價格小於等於100的資料
book_obj = models.Book.objects.filter(price__lte=100)
__range
表示範圍,在···之間,類似sql的between··and,左閉右區間,= 號後面為兩個元素的列表
# 價格在100到200之間的資料
book_obj = models.Book.objects.filter(price__range=[100,300])
__contains
包含關係,=號後面為字串,類似sql的模糊查詢,LIKE
# 查詢包含Py字元的書名
book_obj = models.Book.objects.filter(title__contains='Py')
__icontains
不區分大小寫,和
contains
一樣
# 查詢包含Py字元的書名
book_obj = models.Book.objects.filter(title__contains='py')
__startswith
查詢以指定字元開頭,= 號後面為字串
book_obj = models.Book.objects.filter(title__startswith='P')
__endswith
查詢以指定字元結尾,=號後面為字串
book_obj = models.Book.objects.filter(title__endswith='構')
__year
__year 是 DateField 資料型別的年份,= 號後面為數字
# 2022年出版的資料
book_obj = models.Book.objects.filter(publish_date__year=2022)
__month
查詢月份
# 3月出版的資料
book_obj = models.Book.objects.filter(publish_date__month=3)
__day
__day 是DateField 資料型別的天數,= 號後面為數字
# 所有17號出版的資料
book_obj = models.Book.objects.filter(publish_date__day=17)
ORM 刪除資料
方式一:使用模型類的 物件.delete()
返回值:元組,第一個元素為受影響的行數
book_obj=models.Book.objects.filter(pk=8).first().delete()
方式二:使用 QuerySet 型別資料.delete()(推薦)
返回值:元組,第一個元素為受影響的行數。
books=models.Book.objects.filter(pk__in=[1,2]).delete()
注意:
- Django 刪除資料時,會模仿 SQL約束 ON DELETE CASCADE 的行為,也就是刪除一個物件時也會刪除與它相關聯的外來鍵物件;
- delete() 方法是 QuerySet 資料型別的方法,但並不適用於 Manager 本身。也就是想要刪除所有資料,不能不寫 all;
ORM 修改資料
方式一:
模型類的物件.屬性 = 更改的屬性值
模型類的物件.save()
def book(request):
book_obj = models.Book.objects.filter(pk=23).first()
print(book_obj)
book_obj.title='如何傍富婆,從入門到入贅'
book_obj.save()
return HttpResponse('<p>入贅成功</p>')
方式二:QuerySet 型別資料.update(欄位名=更改的資料)(推薦)
返回值:整數,受影響的行數
def book(request):
book_obj = models.Book.objects.filter(pk=23).update(title='人活一口氣,打死不入贅')
return HttpResponse(book_obj) # 1
ORM 逆轉到 SQL
方式一:
如果想列印orm轉換過程中的sql,需要在settings中進行如下配置:
'''settings.py'''
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
ps:本質是日誌的監控,可以在test下測試
方式二:使用物件.query獲取原生SQL()
from app01 import models
res = models.Book.objects.filter(pk=2)
print(res.query)
'''
SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish`, `app01_book`.`publish_date` FROM `app01_book` WHERE `app01_book`.`id` = 2
'''