Django中的ORM詳解(最新推薦)
Django 的 ORM(Object-Relational Mapping,對(duì)象關(guān)系映射)是 Django 框架提供的數(shù)據(jù)庫(kù)抽象層,允許開發(fā)者使用 Python 代碼操作數(shù)據(jù)庫(kù),而無(wú)需直接編寫 SQL 語(yǔ)句。它提供了一種高效、直觀的方式來(lái)管理數(shù)據(jù)庫(kù)模型和查詢數(shù)據(jù)。
1 ORM介紹
1.1 ORM概念
對(duì)象關(guān)系映射(Object Relational Mapping,簡(jiǎn)稱ORM)模式是一種為了解決面向?qū)ο笈c關(guān)系數(shù)據(jù)庫(kù)存在的互不匹配的現(xiàn)象的技術(shù)。
簡(jiǎn)單的說(shuō),ORM是通過(guò)使用描述對(duì)象和數(shù)據(jù)庫(kù)之間映射的元數(shù)據(jù),將程序中的對(duì)象自動(dòng)持久化到關(guān)系數(shù)據(jù)庫(kù)中。
ORM在業(yè)務(wù)邏輯層和數(shù)據(jù)庫(kù)層之間充當(dāng)了橋梁的作用。
1.2 ORM由來(lái)
讓我們從O/R開始。字母O起源于"對(duì)象"(Object),而R則來(lái)自于"關(guān)系"(Relational)。
幾乎所有的軟件開發(fā)過(guò)程中都會(huì)涉及到對(duì)象和關(guān)系數(shù)據(jù)庫(kù)。在用戶層面和業(yè)務(wù)邏輯層面,我們是面向?qū)ο蟮摹.?dāng)對(duì)象的信息發(fā)生變化的時(shí)候,我們就需要把對(duì)象的信息保存在關(guān)系數(shù)據(jù)庫(kù)中。
按照之前的方式來(lái)進(jìn)行開發(fā)就會(huì)出現(xiàn)程序員會(huì)在自己的業(yè)務(wù)邏輯代碼中夾雜很多SQL語(yǔ)句用來(lái)增加、讀取、修改、刪除相關(guān)數(shù)據(jù),而這些代碼通常都是重復(fù)的。
1.3 ORM的優(yōu)勢(shì)和劣勢(shì)
1.3.1ORM的優(yōu)勢(shì)
ORM解決的主要問(wèn)題是對(duì)象和關(guān)系的映射。它通常把一個(gè)類和一個(gè)表一一對(duì)應(yīng),類的每個(gè)實(shí)例對(duì)應(yīng)表中的一條記錄,類的每個(gè)屬性對(duì)應(yīng)表中的每個(gè)字段。
ORM提供了對(duì)數(shù)據(jù)庫(kù)的映射,不用直接編寫SQL代碼,只需像操作對(duì)象一樣從數(shù)據(jù)庫(kù)操作數(shù)據(jù)。
讓軟件開發(fā)人員專注于業(yè)務(wù)邏輯的處理,提高了開發(fā)效率。
1.3.2 ORM的劣勢(shì)
ORM的缺點(diǎn)是會(huì)在一定程度上犧牲程序的執(zhí)行效率。
ORM用多了SQL語(yǔ)句就不會(huì)寫了,關(guān)系數(shù)據(jù)庫(kù)相關(guān)技能退化…
1.4 ORM總結(jié)
ORM只是一種工具,工具確實(shí)能解決一些重復(fù),簡(jiǎn)單的勞動(dòng)。這是不可否認(rèn)的。
但我們不能指望某個(gè)工具能一勞永逸地解決所有問(wèn)題,一些特殊問(wèn)題還是需要特殊處理的。
但是在整個(gè)軟件開發(fā)過(guò)程中需要特殊處理的情況應(yīng)該都是很少的,否則所謂的工具也就失去了它存在的意義。
2 Django models常用字段
2.1 Django models常用字段
from django.db import models
class ForeignKey(models.Model):
pass
class ForeignMany(models.Model):
pass
class Event(models.Model):
# int自增列,必須填入?yún)?shù) primary_key=True。當(dāng)model中沒有指定主鍵,django自動(dòng)會(huì)創(chuàng)建一個(gè)列名為id的列,做為主鍵。
a = models.AutoField(primary_key=True) # 主鍵
# 最常用的字段,必須指定max_length字符長(zhǎng)度
b = models.CharField(max_length=24, null=False) # 項(xiàng)目名稱
# 布爾型和NullBooleanField有區(qū)別,True/False,本類型不允許出現(xiàn)null。
c = models.BooleanField(default=True) # 是否有效
# 可以為null的布爾型
d = models.NullBooleanField(default=True) # 是否顯示
# json類型
e = models.JSONField() # 事件明細(xì)
# UUID
f = models.UUIDField()
# 小整數(shù) - 32768 ~ 32767
g = models.SmallIntegerField()
# 正小整數(shù) 0 ~ 32767
h = models.PositiveSmallIntegerField()
# 整數(shù)列(有符號(hào)的) -2147483648 ~ 2147483647
i = models.IntegerField()
# 正整數(shù) 0 ~ 2147483647
j = models.PositiveIntegerField()
# 長(zhǎng)整型(有符號(hào)的) -9223372036854775808 ~ 9223372036854775807
k = models.BigIntegerField()
# 長(zhǎng)整數(shù),時(shí)間間隔,數(shù)據(jù)庫(kù)中按照bigint存儲(chǔ),ORM中獲取的值為datetime.timedelta類型
l = models.DurationField()
# 浮點(diǎn)型
m = models.FloatField()
# 金額型->100.12
n = models.DecimalField(max_digits=5, decimal_places=2)
# 二進(jìn)制類型
o = models.BinaryField()
# 一對(duì)多
p = models.ForeignKey(to=ForeignKey, # 關(guān)聯(lián)那張表
to_field='project_id', # 關(guān)聯(lián)表的那個(gè)字段,可以不指定,不指定就和關(guān)聯(lián)表的主鍵關(guān)聯(lián)
db_constraint=False, # 是否生成外鍵約束(默認(rèn)為True)
related_name="_project_id", # 反向查詢名稱
on_delete=models.PROTECT, # 關(guān)聯(lián)刪除選項(xiàng)
db_column='project_id', # 設(shè)置表中的名稱
help_text='關(guān)聯(lián)到Event表的project_id', # 說(shuō)明字段,會(huì)顯示在admin后臺(tái),不會(huì)同步到數(shù)據(jù)庫(kù)
)
# 一對(duì)一,和一對(duì)多系統(tǒng),只是默認(rèn)加了unique=True
q = models.OneToOneField(to=ForeignKey, # 關(guān)聯(lián)那張表
to_field='project_id', # 關(guān)聯(lián)表的那個(gè)字段,可以不指定,不指定就和關(guān)聯(lián)表的主鍵關(guān)聯(lián)
db_constraint=False, # 是否生成外鍵約束(默認(rèn)為True)
related_name="_project_id", # 反向查詢名稱
on_delete=models.PROTECT, # 關(guān)聯(lián)刪除選項(xiàng)
db_column='project_id', # 設(shè)置表中的名稱
help_text='關(guān)聯(lián)到Event表的project_id', # 說(shuō)明字段,會(huì)顯示在admin后臺(tái),不會(huì)同步到數(shù)據(jù)庫(kù)
)
# 多對(duì)多
# 手動(dòng)創(chuàng)建第三張表,雖然可以使用orm的查詢方法,但不支持使用add(), set(), remove(), clear()
r = models.ManyToManyField(to='ForeignKey', # 關(guān)聯(lián)那張表,也就是說(shuō)和那張表關(guān)聯(lián)
through='ForeignMany', # 自定義第三張表,可以不設(shè)置,不設(shè)置Django就自動(dòng)生成第三張表
through_fields=('book', 'author') # 自定義第三張表中,那個(gè)二個(gè)字段管理主表和關(guān)聯(lián)表,可以不設(shè)置
)
# 創(chuàng)建時(shí)間,創(chuàng)建數(shù)據(jù)記錄的時(shí)候會(huì)把當(dāng)前時(shí)添加到數(shù)據(jù)庫(kù)。
s = models.DateTimeField(auto_now_add=True)
# 修改時(shí)間,每次更新數(shù)據(jù)記錄的時(shí)候會(huì)更新該字段。
t = models.DateTimeField(auto_now=True)
class Meta:
# 模型在數(shù)據(jù)庫(kù)中的表名默認(rèn)是 APP名稱_類名,可以通過(guò)db_table重新默認(rèn)值,相當(dāng)于指定模型在數(shù)據(jù)庫(kù)中的表明
db_table = 'project_event'2.2 Django models字段參數(shù) null
用于表示某個(gè)字段可以為空。
unique
如果設(shè)置為unique=True 則該字段在此表中必須是唯一的 。
db_index
如果db_index=True 則代表著為此字段設(shè)置數(shù)據(jù)庫(kù)索引。
default
為該字段設(shè)置默認(rèn)值。
auto_now_add
時(shí)間字段獨(dú)有,DatetimeField、DateField、TimeField這個(gè)三個(gè)時(shí)間字段,都可以設(shè)置如下屬性。
配置auto_now_add=True,創(chuàng)建數(shù)據(jù)記錄的時(shí)候會(huì)把當(dāng)前時(shí)間添加到數(shù)據(jù)庫(kù)。
auto_now
時(shí)間字段獨(dú)有,DatetimeField、DateField、TimeField這個(gè)三個(gè)時(shí)間字段,都可以設(shè)置如下屬性。
配置上auto_now=True,每次更新數(shù)據(jù)記錄的時(shí)候會(huì)更新該字段。
2.3 Django models關(guān)系字段
2.3.1 ForeignKey
外鍵類型在ORM中用來(lái)表示外鍵關(guān)聯(lián)關(guān)系,一般把ForeignKey字段設(shè)置在 '一對(duì)多’中’多’的一方。
ForeignKey可以和其他表做關(guān)聯(lián)關(guān)系同時(shí)也可以和自身做關(guān)聯(lián)關(guān)系。
字段參數(shù)
to
設(shè)置要關(guān)聯(lián)的表
to_field
設(shè)置要關(guān)聯(lián)的表的字段
related_name
反向操作時(shí),使用的字段名,用于代替原反向查詢時(shí)的’表名_set’。
例如:
class Classes(models.Model):
name = models.CharField(max_length=32)
class Student(models.Model):
name = models.CharField(max_length=32)
theclass = models.ForeignKey(to="Classes")當(dāng)我們要查詢某個(gè)班級(jí)關(guān)聯(lián)的所有學(xué)生(反向查詢)時(shí),我們會(huì)這么寫:
models.Classes.objects.first().student_set.all()
當(dāng)我們?cè)贔oreignKey字段中添加了參數(shù) related_name 后,
class Student(models.Model):
name = models.CharField(max_length=32)
theclass = models.ForeignKey(to="Classes", related_name="students")當(dāng)我們要查詢某個(gè)班級(jí)關(guān)聯(lián)的所有學(xué)生(反向查詢)時(shí),我們會(huì)這么寫:
models.Classes.objects.first().students.all()
related_query_name
反向查詢操作時(shí),使用的連接前綴,用于替換表名。
on_delete
當(dāng)刪除關(guān)聯(lián)表中的數(shù)據(jù)時(shí),當(dāng)前表與其關(guān)聯(lián)的行的行為。
| 參數(shù) | 操作 |
|---|---|
| models.CASCADE | 刪除關(guān)聯(lián)數(shù)據(jù),與之關(guān)聯(lián)也刪除 |
| models.DO_NOTHING | 刪除關(guān)聯(lián)數(shù)據(jù),引發(fā)錯(cuò)誤IntegrityError |
| models.PROTECT | 刪除關(guān)聯(lián)數(shù)據(jù),引發(fā)錯(cuò)誤ProtectedError |
| models.SET_NULL | 刪除關(guān)聯(lián)數(shù)據(jù),與之關(guān)聯(lián)的值設(shè)置為null(前提FK字段需要設(shè)置為可空) |
| models.SET_DEFAULT | 刪除關(guān)聯(lián)數(shù)據(jù),與之關(guān)聯(lián)的值設(shè)置為默認(rèn)值(前提FK字段需要設(shè)置默認(rèn)值) |
| models.SET | 刪除關(guān)聯(lián)數(shù)據(jù), a. 與之關(guān)聯(lián)的值設(shè)置為指定值,設(shè)置:models.SET(值) b. 與之關(guān)聯(lián)的值設(shè)置為可執(zhí)行對(duì)象的返回值,設(shè)置:models.SET(func():return 10) |
db_constraint
是否在數(shù)據(jù)庫(kù)中創(chuàng)建外鍵約束,默認(rèn)為True。
2.3.2 OneToOneField
一對(duì)一字段。
通常一對(duì)一字段用來(lái)擴(kuò)展已有字段。
一對(duì)一的關(guān)聯(lián)關(guān)系多用在當(dāng)一張表的不同字段查詢頻次差距過(guò)大的情況下,將本可以存儲(chǔ)在一張表的字段拆開放置在兩張表中,然后將兩張表建立一對(duì)一的關(guān)聯(lián)關(guān)系。
字段參數(shù)
to
設(shè)置要關(guān)聯(lián)的表。
to_field
設(shè)置要關(guān)聯(lián)的字段。
on_delete
同F(xiàn)oreignKey字段。
2.3.3 ManyToManyField
用于表示多對(duì)多的關(guān)聯(lián)關(guān)系。在數(shù)據(jù)庫(kù)中通過(guò)第三張表來(lái)建立關(guān)聯(lián)關(guān)系。
字段參數(shù)
to
設(shè)置要關(guān)聯(lián)的表
related_name
同F(xiàn)oreignKey字段。
related_query_name
同F(xiàn)oreignKey字段。
symmetrical
僅用于多對(duì)多自關(guān)聯(lián)時(shí),指定內(nèi)部是否創(chuàng)建反向操作的字段。默認(rèn)為True。
舉個(gè)例子:
class Person(models.Model):
name = models.CharField(max_length=16)
friends = models.ManyToManyField("self")此時(shí),person對(duì)象就沒有person_set屬性。
class Person(models.Model):
name = models.CharField(max_length=16)
friends = models.ManyToManyField("self", symmetrical=False)此時(shí),person對(duì)象現(xiàn)在就可以使用person_set屬性進(jìn)行反向查詢。
through
在使用ManyToManyField字段時(shí),Django將自動(dòng)生成一張表來(lái)管理多對(duì)多的關(guān)聯(lián)關(guān)系。
但我們也可以手動(dòng)創(chuàng)建第三張表來(lái)管理多對(duì)多關(guān)系,此時(shí)就需要通過(guò)through來(lái)指定第三張表的表名。
through_fields
設(shè)置關(guān)聯(lián)的字段。
db_table
默認(rèn)創(chuàng)建第三張表時(shí),數(shù)據(jù)庫(kù)中表的名稱。
多對(duì)多關(guān)聯(lián)關(guān)系的三種方式
方式一:自行創(chuàng)建第三張表
class Book(models.Model):
title = models.CharField(max_length=32, verbose_name="書名")
class Author(models.Model):
name = models.CharField(max_length=32, verbose_name="作者姓名")
# 自己創(chuàng)建第三張表,分別通過(guò)外鍵關(guān)聯(lián)書和作者
class Author2Book(models.Model):
author = models.ForeignKey(to="Author")
book = models.ForeignKey(to="Book")
class Meta:
unique_together = ("author", "book")2.方式二:通過(guò)ManyToManyField自動(dòng)創(chuàng)建第三張表
class Book(models.Model):
title = models.CharField(max_length=32, verbose_name="書名")
# 通過(guò)ORM自帶的ManyToManyField自動(dòng)創(chuàng)建第三張表
class Author(models.Model):
name = models.CharField(max_length=32, verbose_name="作者姓名")
books = models.ManyToManyField(to="Book", related_name="authors")3.方式三:設(shè)置ManyTomanyField并指定自行創(chuàng)建的第三張表
class Book(models.Model):
title = models.CharField(max_length=32, verbose_name="書名")
# 自己創(chuàng)建第三張表,并通過(guò)ManyToManyField指定關(guān)聯(lián)
class Author(models.Model):
name = models.CharField(max_length=32, verbose_name="作者姓名")
books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book"))
# through_fields接受一個(gè)2元組('field1','field2'):
# 其中field1是定義ManyToManyField的模型外鍵的名(author),field2是關(guān)聯(lián)目標(biāo)模型(book)的外鍵名。
class Author2Book(models.Model):
author = models.ForeignKey(to="Author")
book = models.ForeignKey(to="Book")
class Meta:
unique_together = ("author", "book")注意:
當(dāng)我們需要在第三張關(guān)系表中存儲(chǔ)額外的字段時(shí),就要使用第三種方式。
但是當(dāng)我們使用第三種方式創(chuàng)建多對(duì)多關(guān)聯(lián)關(guān)系時(shí),就無(wú)法使用set、add、remove、clear方法來(lái)管理多對(duì)多的關(guān)系了,需要通過(guò)第三張表的model來(lái)管理多對(duì)多關(guān)系。
2.4 元信息
ORM對(duì)應(yīng)的類里面包含另一個(gè)Meta類,而Meta類封裝了一些數(shù)據(jù)庫(kù)的信息。主要字段如下:
class Meta:
#app_label聲明屬于哪個(gè)應(yīng)用
app_label='Grade_manager'
#table_name自定義表名、如果沒有指定表名會(huì)是:應(yīng)用名_類名
db_table='grade'
#有些數(shù)據(jù)庫(kù)有數(shù)據(jù)庫(kù)表空間,比如Oracle。你可以通過(guò)db_tablespace來(lái)指定這個(gè)模型對(duì)應(yīng)的數(shù)據(jù)庫(kù)表放在哪個(gè)數(shù)據(jù)庫(kù)表空間。
db_tablespace = "user"
#個(gè) DateField 或 DateTimeField 字段的名字. 若提供該選項(xiàng), 該模塊將擁有一個(gè) get_latest() 函數(shù)以得到 "最新的" 對(duì)象(依據(jù)那個(gè)字段): 得到最近一 條order_date字段記錄、
get_latest_by = "order_date"
#給這個(gè)模型取一個(gè)更簡(jiǎn)單、好讀的名字
verbose_name = "pizza"
#模型的復(fù)數(shù)形式是什么
verbose_name_plural
# 聯(lián)合索引
index_together=("grade","user")
# 指定默認(rèn)按什么字段排序,只有設(shè)置了該屬性,我們查詢到的結(jié)果才可以被reverse()。
ordering="grade"2.5 blank和null的區(qū)別
- blank
設(shè)置為True時(shí),字段可以為空。設(shè)置為False時(shí),字段是必須填寫的。字符型字段CharField和TextField是用空字符串來(lái)存儲(chǔ)空值的。
如果為True,字段允許為空,默認(rèn)不允許。
- null
設(shè)置為True時(shí),django用Null來(lái)存儲(chǔ)空值。日期型、時(shí)間型和數(shù)字型字段不接受空字符串。所以設(shè)置IntegerField,DateTimeField型字段可以為空時(shí),
需要將blank,null均設(shè)為True。
如果為True,空值將會(huì)被存儲(chǔ)為NULL,默認(rèn)為False。
如果想設(shè)置BooleanField為空時(shí)可以選用NullBooleanField型字段。
一句話概括,null 是針對(duì)數(shù)據(jù)庫(kù)而言,如果 null=True, 表示數(shù)據(jù)庫(kù)的該字段可以為空。blank 是針對(duì)表單的,如果 blank=True,表示你的表單填寫該字段的時(shí)候可以不填,比如 admin 界面下增加 model 一條記錄的時(shí)候。直觀的看到就是該字段不是粗體
2.6 Django models字段與mysql字段對(duì)照
| django字段 | mysql字段 | 準(zhǔn)備 |
|---|---|---|
| AutoField | integer AUTO_INCREMENT | 自增主鍵,Django Model默認(rèn)提供,能夠被重寫。 |
| BigAutoField | bigint AUTO_INCREMENT | |
| BooleanField | tinyint(1) | 布爾類型字段,通常用于記錄狀態(tài)標(biāo)記。 |
| BinaryField | longblob | |
| CharField | varchar(%(max_length)s) | |
| CommaSeparatedIntegerField | varchar(%(max_length)s) | |
| DecimalField | numeric((max_digits)s , %(decimal_places)s) | 開發(fā)對(duì)數(shù)據(jù)精準(zhǔn)要求較高大的業(yè)務(wù)時(shí)考慮使用。 models.DecimalField(max_length=8, decimal_places=2) 就是定義長(zhǎng)度為8位、精度位2位的數(shù)字,例如數(shù)字:666666.66 |
| IntergerField | int(11) | 同AutoField同樣,惟一的差異就是不自增。 |
| PositiveIntegerField | int(11) | 同IntegerField,只包含正整數(shù)。 |
| SmallIntegerField | smallint | 小整數(shù)時(shí)通常會(huì)用到。 |
| CommaSeparatedIntegerField | varchar(%(max_length)s) | |
| DateField | date | |
| DateTimeField | datetime | |
| 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) |
2.7 Django models字段與Sql語(yǔ)句
下面這個(gè)例子定義了一個(gè) Person 模型,包含 first_name 和 last_name。
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)first_name 和 last_name 是模型的字段。每個(gè)字段被指定為一個(gè)類屬性,每個(gè)屬性映射到一個(gè)數(shù)據(jù)庫(kù)列。
上面的 Person 模型將會(huì)像這樣創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)表:
CREATE TABLE myapp_person (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);一些說(shuō)明:
- 表myapp_person的名稱是自動(dòng)生成的,如果你要自定義表名,需要在model的Meta類中指定 db_table 參數(shù),強(qiáng)烈建議使用小寫表名,特別是使用MySQL作為后端數(shù)據(jù)庫(kù)時(shí)。
- id字段是自動(dòng)添加的,如果你想要指定自定義主鍵,只需在其中一個(gè)字段中指定 primary_key=True 即可。如果Django發(fā)現(xiàn)你已經(jīng)明確地設(shè)置了Field.primary_key,它將不會(huì)添加自動(dòng)ID列。
- 本示例中的CREATE TABLE SQL使用PostgreSQL語(yǔ)法進(jìn)行格式化,但值得注意的是,Django會(huì)根據(jù)配置文件中指定的數(shù)據(jù)庫(kù)后端類型來(lái)生成相應(yīng)的SQL語(yǔ)句。
- Django支持MySQL5.5及更高版本。
3 Django中的ORM
3.1 Django項(xiàng)目使用MySQL數(shù)據(jù)庫(kù)
- 在Django項(xiàng)目的settings.py文件中,配置數(shù)據(jù)庫(kù)連接信息:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": "你的數(shù)據(jù)庫(kù)名稱", # 需要自己手動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)
"USER": "數(shù)據(jù)庫(kù)用戶名",
"PASSWORD": "數(shù)據(jù)庫(kù)密碼",
"HOST": "數(shù)據(jù)庫(kù)IP",
"POST": 3306
}
}在Django項(xiàng)目的__init__.py文件中寫如下代碼,告訴Django使用pymysql模塊連接MySQL數(shù)據(jù)庫(kù):
import pymysql pymysql.install_as_MySQLdb()
3.2 Models自定義字段(了解為主)
class UnsignedIntegerField(models.IntegerField):
def db_type(self, connection):
return 'integer UNSIGNED'class FixedCharField(models.Field):
"""
自定義的char類型的字段類
"""
def __init__(self, max_length, *args, **kwargs):
super().__init__(max_length=max_length, *args, **kwargs)
self.length = max_length
def db_type(self, connection):
"""
限定生成數(shù)據(jù)庫(kù)表的字段類型為char,長(zhǎng)度為length指定的值
"""
return 'char(%s)' % self.length
class Class(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=25)
# 使用上面自定義的char類型的字段
cname = FixedCharField(max_length=25)4.Django ORM查詢常用方法
4.1 常用查詢操作
# 獲取到所有的書籍對(duì)象,結(jié)果是對(duì)象列表
models.Book.objects.all()
# 獲取符合條件的對(duì)象
models.Book.objects.get(**kwargs)
# 篩選所有符合條件的,結(jié)果是對(duì)象列表
models.Book.objects.filter(**kwargs)
# 篩選出所有不符合條件的,結(jié)果是對(duì)象列表,這個(gè)地方一直有個(gè)疑問(wèn),好像exclude里面如果是外鍵排除就不起作用
models.Book.objects.exclude(**kwargs)
# 字典列表[{id:1,name:20},{id:2,name:18} ],values(‘id')括號(hào)內(nèi)不指定時(shí)顯示全部,如指定則只顯示指定的,[ {id:1},{id:2,}]
models.Book.objects.all().values("id","name")
# 元組列表,[ (1,20),(2,18) ]同上,指定時(shí)顯示指定內(nèi)容
models.Book.objects.all().values_list("id","name")
# 按照id升序就行排列
models.Book.objects.all().order_by("id")
# 按照id降序就行排列
models.Book.objects.all().order_by("-id")
# 先按age升序,age相同的按id進(jìn)行降序排列
models.Book.objects.all().order_by("age", "-id")
# 對(duì)結(jié)果反轉(zhuǎn); 注意reverse前必須排序,否則reverse無(wú)效; 或在model.py文件中Book類中的Meta中指定ordering=("id", )注意逗號(hào)必須有
models.Book.objects.all().order_by("id").reverse()
# 去重,當(dāng)獲取到的結(jié)果Queryset列表中同一對(duì)象出現(xiàn)多次時(shí)去重,只留一個(gè)
models.Book.objects.all().values("id","name").distinct():
# 計(jì)數(shù),可統(tǒng)計(jì)結(jié)果個(gè)數(shù),如對(duì)Queryset內(nèi)元素?cái)?shù)進(jìn)行統(tǒng)計(jì).
models.Book.objects.all().count()
# 獲取結(jié)果中的第一條,即使前面結(jié)果列表為空,也不會(huì)報(bào)錯(cuò)
models.Book.objects.all().first()
# 獲取結(jié)果中的最后一條
models.Book.objects.filter().last()
# 判斷Queryset列表是否有東西,結(jié)果為True或False;
models.Book.objects.filter().exists() 4.2 返回值
返回對(duì)象列表(Queryset)的方法有
- all()
- filter()
- ordey_by()
- exclude()
- values()
- values_list()
- reverse()
- distinct()
返回單個(gè)對(duì)象的方法有
- first()
- last()
- get()
- create()
返回判斷布爾值的有
- exists()
返回返回?cái)?shù)字的有
- count()
4.3 查詢API(QuerySet API)
4.3.1 ------ filter -----
filter(**kwargs)
返回一個(gè)新的 QuerySet ,它包含了與所給的篩選條件相匹配的對(duì)象。
這些篩選條件(**kwargs)在下面的字段篩選(Field lookups) 中有詳細(xì)介紹。多個(gè)條件之間在 SQL 語(yǔ)句中是 AND 關(guān)系。
# 條件查詢。(可以通過(guò)逗號(hào),連接多個(gè)條件) 返回QuerySet查詢集(可以遍歷) # __exact 等于。 __exact 可以省略。 (__iexact 不區(qū)分大小寫) BookInfo.objects.filter(title__exact='天龍八部') # 等價(jià)BookInfo.objects.filter(title__exact='天龍八部') BookInfo.objects.filter(title='天龍八部') # __contains 包含。模糊查詢。 (__icontains 不區(qū)分大小寫) BookInfo.objects.filter(title__contains='天') # __endswith 以..結(jié)尾。 __startswith 以..開頭。 (__iendswith 不區(qū)分大小寫) BookInfo.objects.filter(title__endswith='部') # __isnull 是否為空。 True:表示為null。 False表示not null。 BookInfo.objects.filter(title__isnull=False) # __in 范圍查詢。 BookInfo.objects.filter(id__in=[1, 3, 5]) # __range 范圍查詢,查詢1到5的id BookInfo.objects.filter(id__range=[1, 5]) # 大于小于 BookInfo.objects.filter(id__gt=3) # 大于 BookInfo.objects.filter(id__lt=3) # 小于 BookInfo.objects.filter(id__gte=3) # 大于等于 BookInfo.objects.filter(id__lte=3) # 小于等于 # 日期查詢,其中__gt,__lt,__gte,__lte都使用日期 BookInfo.objects.filter(pub_date__gt=date(1980, 1, 1)) # 日期查詢 BookInfo.objects.filter(pub_date__year=1980) # 年 BookInfo.objects.filter(pub_date__month=1980) # 月 BookInfo.objects.filter(pub_date__day=1980) # 日 BookInfo.objects.filter(pub_date__week_day=1980) # 周級(jí) BookInfo.objects.filter(pub_date__hour=1980) # 時(shí) BookInfo.objects.filter(pub_date__minute=1980) # 分 BookInfo.objects.filter(pub_date__second=1980) # 秒
到此這篇關(guān)于Django的ORM詳解的文章就介紹到這了,更多相關(guān)Django ORM內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Django ORM外鍵查詢與反向查詢技巧
- django里面的forms模塊詳解
- Django ORM查詢操作方式
- Django ORM數(shù)據(jù)庫(kù)操作處理全面指南
- django orm模糊查詢、正則匹配多個(gè)值方式
- Django框架ORM操作數(shù)據(jù)庫(kù)不生效問(wèn)題示例解決方法
- Django中ModelForm組件的簡(jiǎn)單配置與使用教程
- 使用Django框架中ORM系統(tǒng)實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)數(shù)據(jù)增刪改查
- Django中ORM的基本使用教程
- 使用 django orm 寫 exists 條件過(guò)濾實(shí)例
- Django中ORM找出內(nèi)容不為空的數(shù)據(jù)實(shí)例
相關(guān)文章
Python不使用庫(kù)進(jìn)行矩陣運(yùn)算詳解
這篇文章主要介紹了Python不使用庫(kù)進(jìn)行矩陣運(yùn)算詳解,矩陣乘法中,需要判斷兩個(gè)矩陣是否可以進(jìn)行相乘,即前一個(gè)矩陣的列是否等于后一個(gè)矩陣的行,,需要的朋友可以參考下2023-08-08
Python實(shí)現(xiàn)識(shí)別圖片為文字的示例代碼
這篇文章主要為大家詳細(xì)介紹了Python如何不調(diào)用三方收費(fèi)接口,照樣實(shí)現(xiàn)識(shí)別圖片為文字的功能。文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-08-08
Pycharm虛擬環(huán)境創(chuàng)建并使用命令行指定庫(kù)的版本進(jìn)行安裝
Pycharm創(chuàng)建的項(xiàng)目,使用了虛擬環(huán)境,對(duì)庫(kù)的版本進(jìn)行管理,有些項(xiàng)目的對(duì)第三方庫(kù)的版本要求不同,可使用虛擬環(huán)境進(jìn)行管理,直接想通過(guò)pip命令安裝可以參考下本文的操作步驟2022-07-07
詳解Python開發(fā)語(yǔ)言中的基本數(shù)據(jù)類型
數(shù)據(jù)類型想必大家都知道是什么含義,指的是輸入數(shù)據(jù)的類型,任何數(shù)據(jù)都有明確的數(shù)據(jù)類型。本文主要和大家聊聊Python的三種基本數(shù)據(jù)類型,感興趣的可以了解一下2022-10-10
python四種出行路線規(guī)劃的實(shí)現(xiàn)
路徑規(guī)劃中包括步行、公交、駕車、騎行等不同方式,今天借助高德地圖web服務(wù)api,實(shí)現(xiàn)出行路線規(guī)劃。感興趣的可以了解下2021-06-06

