一文讀懂|Django之Model操作數據庫詳解


一、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_112233\d+', 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})

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

推薦閱讀更多精彩內容