一、django ORM簡介

O(objects):類和對象。R(Relation):關係,關係資料庫中的表格。M(Mapping):映射。

Django ORM框架的功能:

  1. 建立模型類和表之間的對應關係,允許我們通過面向對象的方式來操作資料庫。
  2. 根據設計的模型類生成資料庫中的表格。
  3. 通過方便的配置就可以進行資料庫的切換。

二、 資料庫的配置

Django可以配置使用sqlite3,mysql,oracle,postgresql等資料庫。Django默認使用的是sqlite3資料庫,settigs.py裡面:

DATABASES = {
default: {
ENGINE: django.db.backends.sqlite3,#默認使用的資料庫引擎是sqlite3,項目自動創建
NAME: os.path.join(BASE_DIR, db.sqlite3),#指定資料庫所在的路徑
}
}

Django項目也可以配置使用mysql資料庫,使用如下配置:

DATABASES = {
default: {
ENGINE: django.db.backends.mysql,#表示使用的是mysql資料庫的引擎
NAME: db1, #資料庫的名字,可以在mysql的提示符下先創建好
USER:root, #資料庫用戶名
PASSWORD:, #資料庫密碼
HOST:, #資料庫主機,留空默認為"localhost"
PORT:3306, #資料庫使用的埠
}
}

配置好資料庫的信息後還必須安裝資料庫的驅動程序,Django默認導入的mysql的驅動程序是MySQLdb,然而MySQLdb對於py3支持不全,所以這裡使用PyMySQL。

pip install pymysql

在項目名文件下的__init__.py文件中寫入如下配置:

import pymysql
pymysql.install_as_MySQLdb()

三、創建資料庫表結構文件

對應app目錄下的models.py

1、生成一個簡單的資料庫表:

在未指定primary_key的情況下,Django會默認創建一個id自增欄位作為主鍵。

from django.db import models

class Account(models.Model):
account_name = models.CharField(max_length=20)
account_id = models.IntegerField(primary_key=True)
balance = models.DecimalField(max_digits=2, decimal_places=2)

2、執行命令生成到資料庫

python manage.py makemigrations
python manage.py migrate # 生成數據表

四、資料庫欄位

AutoField(Field) - int自增列,必須填入參數 primary_key=True
BigAutoField(AutoField) - bigint自增列,必須填入參數 primary_key=True
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)- 二進位類型

五、資料庫欄位參數

null 資料庫中欄位是否可以為空
db_column 資料庫中欄位的列名
default 資料庫中欄位的默認值
primary_key 資料庫中欄位是否為主鍵
db_index 資料庫中欄位是否可以建立索引
unique 資料庫中欄位是否可以建立唯一索引
unique_for_date 資料庫中欄位【日期】部分是否可以建立唯一索引
unique_for_month 資料庫中欄位【月】部分是否可以建立唯一索引
unique_for_year 資料庫中欄位【年】部分是否可以建立唯一索引
verbose_name Admin中顯示的欄位名稱
blank Admin中是否允許用戶輸入為空
editable Admin中是否可以編輯
help_text Admin中該欄位的提示信息
choices Admin中顯示選擇框的內容,用不變動的數據放在內存中從而避免跨表操作
如:gf = models.IntegerField(choices=[(0, 何穗),(1, 大表姐),],default=1)
error_messages 自定義錯誤信息(字典類型),從而定製想要顯示的錯誤信息;
字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
如:{null: "不能為空.", invalid: 格式錯誤}
validators 自定義錯誤驗證(列表類型),從而定製想要的驗證規則
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator,URLValidator,DecimalValidator,
MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
如:
test = models.CharField(
max_length=32,
error_messages={
c1: 優先錯信息1,
c2: 優先錯信息2,
c3: 優先錯信息3,
},
validators=[
RegexValidator(regex=root_d+, message=錯誤了, code=c1),
RegexValidator(regex=root_112233d+, message=又錯誤了, code=c2),
EmailValidator(message=又錯誤了, code=c3), ]

)

六、資料庫Meta元信息

class UserInfo(models.Model):
nid = models.AutoField(primary_key=True)
username = models.CharField(max_length=32)
class Meta:
# 資料庫中生成的表名稱 默認 app名稱 + 下劃線 + 類名
db_table = "table_name"
# 聯合索引
index_together = [
("pub_date", "deadline"),
]

# 聯合唯一索引
unique_together = (("driver", "restaurant"),)

# admin中顯示的表名稱
verbose_name

# verbose_name加s
verbose_name_plural

七、關係欄位

關係欄位用於保存數據表之間的關係,包括ForeignKey, ManyToManyField等。

1、ForeignKey

ForeignKey(ForeignObject) # ForeignObject(RelatedField)
to, # 要進行關聯的表名
to_field=None, # 要關聯的表中的欄位名稱
on_delete=None, # 當刪除關聯表中的數據時,當前表與其關聯的行的行為
- models.CASCADE,刪除關聯數據,與之關聯也刪除
- 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),)
related_name=None, # 反向操作時,使用的欄位名,用於代替 【表名_set】 如: obj.表名_set.all()
related_query_name=None, # 反向操作時,使用的連接前綴,用於替換【表名】 如: models.UserGroup.objects.filter(表名__欄位名=1).values(表名__欄位名)
limit_choices_to=None, # 在Admin或ModelForm中顯示關聯數據時,提供的條件:
# 如:
- limit_choices_to={nid__gt: 5}
- limit_choices_to=lambda : {nid__gt: 5}

from django.db.models import Q
- limit_choices_to=Q(nid__gt=10)
- limit_choices_to=Q(nid=8) | Q(nid__gt=10)
- limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption=root)
db_constraint=True # 是否在資料庫中創建外鍵約束
parent_link=False # 在Admin中是否顯示關聯數據

2、OneToOneField

OneToOneField(ForeignKey)
to, # 要進行關聯的表名
to_field=None # 要關聯的表中的欄位名稱
on_delete=None, # 當刪除關聯表中的數據時,當前表與其關聯的行的行為

###### 對於一對一 ######
# 1. 一對一其實就是 一對多 + 唯一索引
# 2.當兩個類之間有繼承關係時,默認會創建一個一對一欄位
# 如下會在A表中額外增加一個c_ptr_id列且唯一:
class C(models.Model):
nid = models.AutoField(primary_key=True)
part = models.CharField(max_length=12)

class A(C):
id = models.AutoField(primary_key=True)
code = models.CharField(max_length=1)

3、ManyToManyField

ManyToManyField(RelatedField)
to, # 要進行關聯的表名
related_name=None, # 反向操作時,使用的欄位名,用於代替 【表名_set】 如: obj.表名_set.all()
related_query_name=None, # 反向操作時,使用的連接前綴,用於替換【表名】 如: models.UserGroup.objects.filter(表名__欄位名=1).values(表名__欄位名)
limit_choices_to=None, # 在Admin或ModelForm中顯示關聯數據時,提供的條件:
# 如:
- limit_choices_to={nid__gt: 5}
- limit_choices_to=lambda : {nid__gt: 5}

from django.db.models import Q
- limit_choices_to=Q(nid__gt=10)
- limit_choices_to=Q(nid=8) | Q(nid__gt=10)
- limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption=root)
symmetrical=None, # 僅用於多對多自關聯時,symmetrical用於指定內部是否創建反向操作的欄位
# 做如下操作時,不同的symmetrical會有不同的可選欄位
models.BB.objects.filter(...)

# 可選欄位有:code, id, m1
class BB(models.Model):

code = models.CharField(max_length=12)
m1 = models.ManyToManyField(self,symmetrical=True)

# 可選欄位有: bb, code, id, m1
class BB(models.Model):

code = models.CharField(max_length=12)
m1 = models.ManyToManyField(self,symmetrical=False)

through=None, # 自定義第三張表時,使用欄位用於指定關係表
through_fields=None, # 自定義第三張表時,使用欄位用於指定關係表中那些欄位做多對多關係表
from django.db import models

class Person(models.Model):
name = models.CharField(max_length=50)

class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(
Person,
through=Membership,
through_fields=(group, person),
)

class Membership(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
inviter = models.ForeignKey(
Person,
on_delete=models.CASCADE,
related_name="membership_invites",
)
invite_reason = models.CharField(max_length=64)
db_constraint=True, # 是否在資料庫中創建外鍵約束
db_table=None, # 默認創建第三張表時,資料庫中表的名稱

八、資料庫基本操作

?#創建一個書的類,繼承models類
class Book(models.Model):

#用models類創建書的名字,類型為字元串,CharField相當於mysql語句中的varchar,欄位最長為32
title = models.CharField(max_length=32)

#創建書的價格,類型為浮點型,小數點前最長4位,小數點後最長2位
price = models.DecimalField(max_digits=6, decimal_places=2)

#創建書的出版社信息,其與出版社的外鍵關係為一對多,所以用外鍵
publish = models.ForeignKey(Publish)

#創建書的出版日期,類型為日期
publication_date = models.DateField()

#創建書的類型信息,為字元串類型,最長為20
classification=models.CharField(max_length=20)

#創建書的作者信息,書籍與作者的關係為多對多,所以使用many-to-many
authors = models.ManyToManyField("Author")
?

1、增

1.1一對一信息的創建

a、使用create方式

方式一: Publish.objects.create("name"="人民出版社",city="北京"}

方式二: Publish.objects.create(**{"name":"文藝出版社","city":"上海"}}

b、使用save方式

方式一:

book1=Book(title="python",price="88",publish_id="1",publication_date="2017-06-18")

book1.save()

方式二:

author1=Author(name="jerry")

author1.save()

1.2一對多的信息的創建(Foreignkey)

方式一:

#獲取出版社對象
publish_obj=Publish.objects.get(id=4)

#將出版社的對象綁定到書籍的記錄中
Book.objects.create(
title="python",
price=48.00,
publication_date="2017-07-12",
publish=publish_obj,
)

方式二:

#直接把出版社的id號插入到書籍的記錄中
Book.objects.create(
title="python",
price=48.00,
publish_id=2,
publication_date="2017-06-18",
)

1.3多對多信息的創建(ManyToManyField())

a、為一本書添加多個作者

author1=Author.objects.get(id=1)#獲取id號為1的作者對象
author2=Author.objects.filter(name="tom")#獲取名字為"tom"的作者對象
book1=Book.objects.get(id=2)#獲取id號為2的書籍對象
book1.authors.add(author1,author2)#為書籍對象添加多個作者對象

也可以用這種方式:

book1.authors.add(*[author1,author2])#為書籍對象添加作者對象的列表
book1.authors.remove(*[author1,author2])#刪除指定書籍的所有作者

b、為一個作者添加多本書

author_obj = Author.objects.filter(name="jerry")#獲取名字為"jerry"的作者對象
book_obj=Book.objects.filter(id__gt=3)#獲取id大於3的書籍對象集合
author_obj.book_set.add(*book_obj)#為作者對象添加書籍對象集合
author_obj.book_set.remove(*book_obj)#刪除指定作者對象所有的書籍

使用models.ManyToManyField()會自動創建第三張表

1.4手動創建多對多的作者與書籍信息表

class Book2Author(models.Models):
author=models.ForeignKey("Author")#為作者指定Author這張表做為外鍵
book=models.ForeignKey("Book")#為書籍指定Book這張表做為外鍵

author_obj=models.Author.objects.filter(id=3)[0]#獲取Author表中id為3的作者對象
book_obj=models.Book.objects.filter(id=4)[0]#獲取Book表中id為4的書籍對象

方式一:

obj1=Book2Author.objects.create(author=author_obj,book=book_obj)
obj1.save()

方式二:

obj2=Book2Author(author=author_obj,book=book_obj)
obj2.save()

2、刪

Book.objects.filter(id=1).delete()

3、改

3.1使用save方法將所有屬性重新設定一遍,效率低

author1=Author.objects.get(id=3)#獲取id為3的作者對象

author1.name="jobs"#修改作者對象的名字

author1.save()#把更改寫入資料庫

3.2使用update方法直接設置對就的屬性

Publish.objects.filter(id=2).update(name="北京出版社")

注意:update()是QuerySet對象的一個方法,get返回的是一個model對象,其沒有update方法.

filter返回的是一個QuerySet對象,filter裏可以設定多個過濾條件

4、查

查詢數據使用QuerySet API。 QuerySet是惰性執行的,創建Query Set不會訪問資料庫,只有在訪問具體查詢結果的時候才會訪問資料庫。

4.1查詢方法:

filter(**kwargs) 包含了與所給篩選條件相匹配的對象
all() 查詢所有結果
get(**kwargs) 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,如果符合篩選條件的對象超過一個或者沒有都是報錯
values(*field) 返回一個ValueQuerySet,運行後得到的並不是一系列model的實例化對象,而是一個可迭代的字典序列
exclude(**kwargs) 包含了與所給的篩選條件不匹配的對象
order by(*field) 對查詢結果排序
reverse() 對查詢結果反向排序
distinct() 從返回結果中剔除重複記錄
values_list(*field) 與values()非常相似,返回一個元組序列,values返回一個字典序列
count() 返回資料庫中匹配的記錄的數量
first() 返回資料庫中匹配的對象的第一個對象
last() 返回資料庫中匹配的對象的最後一個對象
exists() 判斷一個對象集合中是否包含指定對象,包含返回True,不包含返回False
exclude() 排除滿足條件的對象
annotate() 使用聚合函數
dates() 根據日期獲取查詢集
datetimes() 根據時間獲取查詢集
none() 創建空的查詢集
union() 並集
intersection() 交集
difference() 差集
select_related() 附帶查詢關聯對象
prefetch_related() 預先查詢
extra() 附加SQL查詢
defer() 不載入指定欄位
only() 只載入指定的欄位
using() 選擇資料庫
select_for_update() 鎖住選擇的對象,直到事務結束。
raw() 接收一個原始的SQL查詢

1.filter():

filter(**kwargs)

返回滿足查詢參數的對象集合。

查找的參數(**kwargs)應該滿足下文欄位查找中的格式。多個參數之間是和AND的關係。

Student.objects.filter(age__lt=10)#查詢滿足年齡小於10歲的所有學生對象

2.exclude()

exclude(**kwargs)

返回一個新的QuerySet,它包含不滿足給定的查找參數的對象

Student.objects.exclude(age__gt=20, name=lin)#排除所有年齡大於20歲且名字為「lin」的學員集

3.annotate():

nnotate(args, *kwargs)

使用提供的聚合表達式查詢對象。

表達式可以是簡單的值、對模型(或任何關聯模型)上的欄位的引用或者聚合表達式(平均值、總和等)。

annotate()的每個參數都是一個annotation,它將添加到返回的QuerySet每個對象中。

關鍵字參數指定的Annotation將使用關鍵字作為Annotation 的別名。 匿名參數的別名將基於聚合函數的名稱和模型的欄位生成。 只有引用單個欄位的聚合表達式纔可以使用匿名參數。 其它所有形式都必須用關鍵字參數。

例如,如果正在操作一個Blog列表,你可能想知道每個Blog有多少Entry:

>>> from django.db.models import Count

>>> q = Blog.objects.annotate(Count(entry))

# The name of the first blog

>>> q[0].name

Blogasaurus

# The number of entries on the first blog

>>> q[0].entry__count

42

4.order_by():

order_by(*fields)

默認情況下,根據模型的Meta類中的ordering屬性對QuerySet中的對象進行排序

Student.objects.filter(school="陽關小學").order_by(-age, name)

上面的結果將按照age降序排序,然後再按照name升序排序。"-age"前面的負號表示降序順序。 升序是默認的。 要隨機排序,使用"?",如下所示:

Student.objects.order_by(?)

5. reverse():

reverse()

反向排序QuerySet中返回的元素。 第二次調用reverse()將恢復到原有的排序。

如要獲取QuerySet中最後五個元素,可以這樣做:

my_queryset.reverse()[:5]

這與Python直接使用負索引有點不一樣。 Django不支持負索引。

6.distinct():

distinct(*fields)

去除查詢結果中重複的行。

默認情況下,QuerySet不會去除重複的行。當查詢跨越多張表的數據時,QuerySet可能得到重複的結果,這時候可以使用distinct()進行去重。

7. values():

values(fields, *expressions)

返回一個包含數據的字典的queryset,而不是模型實例。

每個字典表示一個對象,鍵對應於模型對象的屬性名稱。如:

# 列表中包含的是Student對象

>>> Student.objects.filter(name__startswith=Lin)

<QuerySet [<Student: Lin Student>]>

# 列表中包含的是數據字典

>>> Student.objects.filter(name__startswith=Lin).values()

<QuerySet [{id: 1, name: Linxiao, age: 20}]>

另外該方法接收可選的位置參數*fields,它指定values()應該限制哪些欄位。如果指定欄位,每個字典將只包含指定的欄位的鍵/值。如果沒有指定欄位,每個字典將包含資料庫表中所有欄位的鍵和值。如下:

>>> Student.objects.filter(name__startswith=Lin).values()

<QuerySet [{id: 1, name: Linxiao, age: 20}]>

>>> Blog.objects.values(id, name)

<QuerySet [{id: 1, name: Linxiao}]>

8.values_list():

values_list(*fields, flat=False)

與values()類似,只是在迭代時返回的是元組而不是字典。每個元組包含傳遞給values_list()調用的相應欄位或表達式的值,因此第一個項目是第一個欄位等。 像這樣:

>>> Student.objects.values_list(id, name)

獲取數據表的全部數據記錄:

Account.objects.all()

返回值可以進行切片,但不支持負索引。或者使用:

Account.objects.get(field_name=val)

示例:

Account.objects.get(account_name=john)

或者使用過濾器查詢多條記錄:

Account.objects.filter(accounnt_name=val)

嚴格等於

Account.objects.filter(account_name__iexact=val)

忽略大小寫

Account.objects.filter(account_name__contains=val)

名稱中包含val

Account.objects.filter(account_name__icontains=val)

忽略大小寫,包含

Account.objects.filter(account_name__regex=val)

正則表達式

Account.objects.filter(account_name__iregex=val)

正則表達式,忽略大小寫

與filter相反exclude用於返回不滿足條件的查詢結果。

Account.objects.exclude(account_name__contains=val)

filter與exclude可以進行鏈式查詢

Account.objects.exclude(account_name__contains=john).exlucde(balance=0)

對於查詢結果可以使用distinct()去重或者使用order_by(field)進行排序。

Account.objects.filter(account_name__regex=val).distinct()

Account.objects.filter(account_name__regex=val).oreder_by(balance)

使用reverse()方法可以反轉結果集中的元素順序,調用兩次將會恢復原順序。

從SQL 的角度,QuerySet和SELECT 語句等價,過濾器是像WHERE 和LIMIT 一樣的限制子句。

like:

__exact 精確等於 like aaa
__iexact 精確等於 忽略大小寫 ilike aaa
__contains 包含 like %aaa%
__icontains 包含,忽略大小寫 ilike %aaa%,但是對於sqlite來說,contains的作用效果等同於icontains。

in:

__in

查詢在某一範圍的書
Book.objects.filter(publish__in=[10, 20, 30])

is null / is not null:

__isnull 判空

Book.objects.filter(name__isnull=True) // 查詢用戶名為空的書
Publish.objects.filter(name__isnull=False) // 查詢用戶名不為空的書

不等於/不包含於:

Book.objects.filter().excute(publishe=10) // 查詢出版社不為10的書
Book.objects.filter().excute(publish__in=[10, 20]) // 查詢出版社不在 [10, 20] 的書

其他常用模糊查詢:

__startswith 以…開頭
__istartswith 以…開頭 忽略大小寫
__endswith 以…結尾
__iendswith 以…結尾,忽略大小寫
__range 在…範圍內
__year 日期欄位的年份
__month 日期欄位的月份
__day 日期欄位的日

4.2雙下劃線(__)查詢

a、雙下劃線(__)之單表條件查詢

例子:

table1.objects.filter(id__lt=10,id__gt=1)#獲取id小於10,且大於1的記錄
table1.objects.filter(id__in=[11,22,33,44])#獲取id在[11,22,33,44]中的記錄
table1.objects.exclude(id__in=[11,22,33,44])#獲取id不在[11,22,33,44]中的記錄
table1.objects.filter(name__contains="content1")#獲取name中包含有"contents"的記錄(區分大小寫)
table1.objects.filter(name__icontains="content1")#獲取name中包含有"content1"的記錄(不區分大小寫)

table1.objects.filter(id__range=[1,4])#獲取id在1到4(不包含4)之間的的記錄

b、雙下劃線(__)之多表條件查詢

正向查找(條件)之一對一查詢

#查詢書名為"python"的書的id號
res3=Book.objects.filter(title="python").values("id")
print(res3)

正向查找(條件)之一對多查詢

#查詢書名為"python"的書對應的出版社的地址
res4=Book.objects.filter(title="python").values("publisher__city")
print(res4)

#查詢"aaa"作者所寫的所有的書的名字
res5=Book.objects.filter(author__name="aaa").values("title")
print(res5)

#查詢"aaa"作者所寫的所有的書的名字(與上面的用法沒區別)
res6=Book.objects.filter(author__name="aaa").values("title")
print(res6)

反向查找之一對多查詢

#查詢出版了書名為"python"這本書的出版社的名字
res7=Publisher.objects.filter(book__title="python").values("name")
print(res7)

#查詢寫了書名為"python"的作者的名字
res8=Publisher.objects.filter(book__title="python").values("book__authors")
print(res8)

反向查找之多對多查詢

#查詢所寫的書名為"python"的作者的名字
res9=Author.objects.filter(bool__title="python").values("name")
print(res9)
條件查詢即與對象查詢對應,是指filter,values等方法中的通過__來明確查詢條件

4.3F查詢和Q查詢

F查詢專門取對象中某列值的操作,F的作用:用來批量修改數據的

#導入F
from django.db.models import F
#把table1表中的num列中的每一個值在的基礎上加10
table1.objects.all().update(num=F("num")+10)

Q構建搜索條件, Q的作用:Q是用來做條件查詢的

#導入Q
from django.db.models import Q

Q對象可以對關鍵字參數進行封裝,從而更好的應用多個查詢
#查詢table2表中以"aaa"開頭的所有的title列
q1=table2.objects.filter(Q(title__startswith="aaa")).all()
print(q1)

Q對象可以組合使用&,|操作符,當一個操作符是用於兩個Q對象時,會產生一個新的Q對象

#查找以"aaa"開頭,或者以"bbb"結尾的所有title
Q(title__startswith="aaa") | Q(title__endswith="bbb")

Q對象可以用"~"操作符放在表達式前面表示否定,也可允許否定與不否定形式的組合

#查找以"aaa"開頭,且不以"bbb"結尾的所有title
Q(title__startswith="aaa") & ~Q(title__endswith="bbb")

Q對象可以與關鍵字參數查詢一起使用,Q對象放在關鍵字查詢參數的前面

查詢條件:

#查找以"aaa"開頭,以"bbb"結尾的title且書的id號大於4的記錄
Q(title__startswith="aaa") | Q(title__endswith="bbb"),book_id__gt=4

九、實例

1、Django的ORM中如何判斷查詢結果是否為空,判斷django中的orm為空

result= Booking.objects.filter()

方法一 .exists()

if result.exists():
print "QuerySet has Data"
else:
print "QuerySet is empty"

方法二 .count()==0

if result.count() == 0:
print "empty"

方法三

if result:
print "QuerySet has Data"
else:
print "QuerySet is empty"

總結:

QuerySet.exists() > QuerySet.count()==0 > QuerySet

2、模板中顯示資料庫內容的方法

a、創建資料庫

from django.db import models
from django.db import models

class Business(models.Model):
caption = models.CharField(max_length=32)
code = models.CharField(max_length=32)

class Host(models.Model):
nid = models.AutoField(primary_key=True)
hostname = models.CharField(max_length=32,db_index=True)
ip = models.GenericIPAddressField(protocol=both,db_index=True)
port = models.IntegerField()
business = models.ForeignKey(to=Business,to_field=id,on_delete=models.CASCADE)

business.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>業務線列表(對象)</h1>
<ul>
{% for row in v1 %}
<li>{{ row.id }}-{{ row.caption }}-{{ row.code }}</li>
{% endfor %}
</ul>
<h1>業務線列表(字典)</h1>
<ul>
{% for row2 in v2 %}
<li>{{ row2.id }}-{{ row2.caption }}</li>
{% endfor %}
</ul>

</body>
</html>

host.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>主機列表(對象)</h1>
<table border="1">
<tread>
<tr>
<th>主機ID</th>
<th>IP</th>
<th>埠</th>
<th>業務線名稱</th>
</tr>
</tread>
<tbody>
{% for row in v1 %}
<tr>
<td>{{ row.hostname }}</td>
<td>{{ row.ip }}</td>
<td>{{ row.port }}</td>
<td>{{ row.business.caption }}</td>
</tr>
{% endfor %}
</tbody>
</table>

<h1>主機列表(字典)</h1>
<table border="1">
<tread>
<tr>
<th>主機ID</th>
<th>主機名</th>
<th>業務線ID</th>
<th>業務線名稱</th>
</tr>
</tread>
<tbody>
{% for row in v2 %}
<tr>
<td>{{ row.nid }}</td>
<td>{{ row.hostname }}</td>
<td>{{ row.business__id }}</td>
<td>{{ row.business__caption }}</td>
</tr>
{% endfor %}
</tbody>
</table>

<h1>主機列表(元祖)</h1>
<table border="1">
<tread>
<tr>
<th>主機ID</th>
<th>主機名</th>
<th>業務線ID</th>
<th>業務線名稱</th>
</tr>
</tread>
<tbody>
{% for row in v3 %}
<tr>
<td>{{ row.0 }}</td>
<td>{{ row.1 }}</td>
<td>{{ row.2 }}</td>
<td>{{ row.3 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>

views.py

from django.shortcuts import render,HttpResponse
from app01 import models

def business(request):
# 第一種方式(是個對象)
v1 = models.Business.objects.all()
# 第二種方式,只取id和caption(是個字典)
v2 = models.Business.objects.all().values(id,caption)
return render(request,business.html,{v1:v1,v2:v2})

def host(request):
#總共三種方式,對象,字典,列表
v1 = models.Host.objects.all()
v2 = models.Host.objects.filter(nid__gt=0).values(nid,hostname,business__id,business__caption)
v3 = models.Host.objects.filter(nid__gt=0).values_list(nid,hostname,business__id,business__caption)
return render(request,host.html,{v1:v1,v2:v2,v3:v3})

推薦閱讀:

相關文章