­

Django ORM 單表操作

Django ORM單表操作

img

Django 測試環境搭建

注意pycharm鏈接數據庫都需要提前下載對應的驅動,自帶的sqlite3對日期格式數據不敏感,如果後續業務需要使用日期輔助篩選數據那麼不推薦使用sqlite3

搭建方式

  1. 任意創建一個py文件,在該文件內書寫固定的配置
import os
if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day06.settings")
    import django
    django.setup()
  1. 直接使用pycharm提供的python console

image

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 類型數據

注意:

  • 對模型類的對象去重沒有意義,因為每個對象都是一個不一樣的存在(主鍵不一樣),去重的前提是數據必須是一模一樣
  • 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
'''