1. 程式人生 > 其它 >django操作資料庫常用命令

django操作資料庫常用命令

     

一文讀懂|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})

 

釋出於 2019-07-20 11:33 Django(框架) Django-ORM  

推薦閱讀

關於Django效能優化 你不可不知的基礎(主要針對ORM)

酷酷的運動圓

一篇文章帶你瞭解Django ORM操作(高階篇)

來源:Python爬蟲與資料探勘 作者:Python進階者 前言上次兩篇基本學完的Django ORM各種操作,怎麼查,各種查。感興趣的小夥伴可以戳這兩篇文章學習下,一篇文章帶你瞭解Django ORM操作(進…

CDA資料...發表於大資料分析...

Django ORM Cookbook精選摘錄(下) 使用訊號和重寫save方法哪個好?

大江狗發表於Pytho...

Django從入門到大作業:5-ORM操作

上一節涉及到對資料庫初步的操作,歡迎移步 koko可可:Django從入門到大作業:4-資料庫0. ORM(Object Relational Mapping)上一章解釋了一下,但沒有深入應用ORM,後臺也僅限於賬戶的操作…

koko可可

5 條評論

寫下你的評論...          
  • 曲中人02-11 感謝!
  • 狒狒2020-01-03

    太牛逼了,比百度出來的詳細太多了!

  • 狐狸老爹2019-09-13 非常感謝,雪中送炭
  • 冰先生2019-07-24 感謝,作者,寫的非常細