- Django ORM操做 - 目錄 - 1、ORM字段和字段的參數 - 2、ORM的查詢-13種方法 - 3、單表的雙下滑線的使用 - 4、外鍵的方法 - 5、多對多的方法 - 6、聚合和分組 - 7、F查詢 和 Q查詢
- 總結 - 看專業的官方文檔,作專業的程序員:https://docs.djangoproject.com/en/1.11/ref/models/querysets/
1、ORM字段和字段的參數
- 經常使用字段
經常使用字段 AutoField 自增的整形字段,必填參數primary_key=True,則成爲數據庫的主鍵。無該字段時,django自動建立。 一個model不能有兩個AutoField字段。 IntegerField 一個整數類型。數值的範圍是 -2147483648 ~ 2147483647。 CharField 字符類型,必須提供max_length參數。max_length表示字符的長度。 DateField 日期類型,日期格式爲YYYY-MM-DD,至關於Python中的datetime.date的實例 參數: auto_now:每次修改時修改成當前日期時間。 auto_now_add:新建立對象時自動添加當前日期時間。 auto_now和auto_now_add和default參數是互斥的,不能同時設置。 DatetimeField 日期時間字段,格式爲YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],至關於Python中的datetime.datetime的實例。 BooleanField(Field) 布爾值類型
- 字段類型
AutoField(Field) - int自增列,必須填入參數 primary_key=True BigAutoField(AutoField) - bigint自增列,必須填入參數 primary_key=True 注:當model中若是沒有自增列,則自動會建立一個列名爲id的列 from django.db import models class UserInfo(models.Model): # 自動建立一個列名爲id的且爲自增的整數列 username = models.CharField(max_length=32) class Group(models.Model): # 自定義自增列 nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) 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) - 二進制類型
- 自定義字段
- 自定義char數據類型 自定義一個char類型字段: class MyCharField(models.Field): """ 自定義的char類型的字段類 """ def __init__(self, max_length, *args, **kwargs): self.max_length = max_length super(MyCharField, self).__init__(max_length=max_length, *args, **kwargs) def db_type(self, connection): """ 限定生成數據庫表的字段類型爲char,長度爲max_length指定的值 """ return 'char(%s)' % self.max_length - 使用自定義char類型字段: class Class(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=25) # 使用自定義的char類型的字段 cname = MyCharField(max_length=25)
- 自定義一個二進制字段,以及Django字段與數據庫字段類型的對應關係。
自定義一個二進制字段,以及Django字段與數據庫字段類型的對應關係。 - class UnsignedIntegerField(models.IntegerField): def db_type(self, connection): return 'integer UNSIGNED' # PS: 返回值爲字段在數據庫中的屬性。 # Django字段與數據庫字段類型對應關係以下: 'AutoField': 'integer AUTO_INCREMENT', 'BigAutoField': 'bigint AUTO_INCREMENT', 'BinaryField': 'longblob', 'BooleanField': 'bool', 'CharField': 'varchar(%(max_length)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 'DateField': 'date', 'DateTimeField': 'datetime', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', '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)', - 字段參數 - null # 在數據庫層面作的操做,數據庫中字段是否能夠爲空 - blank # Admin中是否容許用戶爲空 與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'), ] ) - Model Meta 參數 - https://docs.djangoproject.com/en/1.11/ref/models/options/#model-meta-options - class UserInfo(models.Model): nid = models.AutoField(primary_key=True) username = models.CharField(max_length=32) class Meta: # 數據庫中生成的表名稱 默認 app名稱 + 下劃線 + 類名 db_table = "table_name" # admin中顯示的表名稱 verbose_name = '我的信息' # verbose_name加s verbose_name_plural = '全部用戶信息' # 聯合索引 index_together = [ ("pub_date", "deadline"), # 應爲兩個存在的字段 ] # 聯合惟一索引 unique_together = (("driver", "restaurant"),) # 應爲兩個存在的字段
- 字段參數python
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'), ] )
- Model Meta參數git
class UserInfo(models.Model): nid = models.AutoField(primary_key=True) username = models.CharField(max_length=32) class Meta: # 數據庫中生成的表名稱 默認 app名稱 + 下劃線 + 類名 db_table = "table_name" # admin中顯示的表名稱 verbose_name = '我的信息' # verbose_name加s verbose_name_plural = '全部用戶信息' # 聯合索引 index_together = [ ("pub_date", "deadline"), # 應爲兩個存在的字段 ] # 聯合惟一索引 unique_together = (("driver", "restaurant"),) # 應爲兩個存在的字段
- 多表關係和參數程序員
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中是否顯示關聯數據 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) 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, # 默認建立第三張表時,數據庫中表的名稱
2、ORM的查詢-13種方法
- 13中方法 1)all(): 查詢全部結果 2)get(**kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有出現就會拋出錯誤 3)filter(**kwargs): 他包含了與所給篩選條件匹配的對象 4)exclude(**kwargs): 他包含了與所給篩選條件不匹配的對象 5)values(*filed): 返回一個ValueQuerySet一個特殊的QuerySet,運行後獲得的並非一系列model的實例化對象,而是一個可迭代的字典序列 6)values_list(*filed): 他與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列 7)order_by(*filed): 對查詢結果進行排序 8)reverse(): 對查詢結果反向排序,請注意reverse()一般只能在具備已定義的順序的QuerySet上調用(在model類的Meta中指定ordering或者調用order_by()) 9)distinct(): 從返回結果中剔除重複記錄(若是查詢跨越多個表,可能在計算QuerySet時獲得重複的結果。此時可使用distinct(),注意只有在PostgreSQL中支持按字段去重) 10) count(): 返回數據庫中匹配查詢(QuerySet)的對象數量 11)first(): 返回第一條記錄 12)last(): 返回最後一條記錄 13)exists(): 若是QuerySet包含數據,就返回True,不然返回False - 總結 - 返回QuerySet對象的方法有 - all() - filter() - exclude() - order_by() - reverse() - distinct() - 特殊的QuerySet - values() 返回一個可迭代的字典序列 - values_list() 返回一個可迭代的元組序列 - 返回具體對象的 - get() - first() - last() - 返回布爾值的方法 - exists() - 返回數字的方法 - count()
3、單表的雙下滑線的使用
- models.Tb1.object.filter(id__lt=10, id__gt=1) # 返回id大於1小於10的值 - models.Tb1.object.filter(id__in=[1, 2, 3]) # 獲取id等於1,2,3的數據 - models.Tb1.object.exclude(id__in=[1, 2, 3]) # not in - models.Tb1.object.filter(name__contains="ward") # 獲取name字段包含"ward的" - models.Tb1.object.filer(name__icontains="ward") # icontains 大小寫不敏感 - models.Tb1.object.filter(id__range[1, 3]) # id範圍是1到3的,等價於SQL的 between and - 相似的還有: startswith, istartswith, endswith, iendswith - date字段還能夠 - models.Class.object.filter(first_day__year=2018) - models.Class.object.filter(first_day__year=2018, first_day__month=2018)
4、外鍵的方法
- 正向查詢 - 對象查找(跨表) - 語法: 對象.關聯字段.字段 - 實例: book_obj = models.Book.objects.first() # 第一本書對象 book_obj.publisher # 獲得這本書關聯的出版社對象 book_obj.publisher.name # 獲得出版社對象的名稱 - 字段查找 - 語法:關聯字段__字段 - 實例 models.Book.objects.values_list("publisher__name") - 反向查詢 - 對象查找 - 語法:obj.表名_set - 實例: publisher_obj = models.Publisher.objects.first() # 找到第一個出版社對象 books = publisher_obj.book_set.all() # 找到第一個出版社的全部書 title = books.values_list("title") # 找到第一個出版社出版的全部書的書名 - 字段查找 - 語法:表名__字段 - 實例: titles = models.Publisher.objects.values_list("book__title")
5、多對多的方法
- class RelatedManager - "關聯管理器"是在一對多或者多對多的關聯上下文中使用的管理器 - 它存在下面兩種狀況 - 外鍵關係的方向查詢 - 多對多關聯關係 - 方法 - create() - 建立一個新的對象,保存對象,並將她添加到關聯對象集之中,返回新建立的對象 >>> import datetime >>> models.Author.objects.first().book_set.create(title="python從入門到精通", publish_date=datetime.date.today()) - add() - 把指定的model對象添加到關聯對象集中 - 添加對象 >>> author_objs = models.Author.objects.filter(id__lt=3) >>> models.Book.objects.first().authors.add(*author_objs) - 添加id >>> models.Book.objects.first().authors.add(*[1, 2]) - set() - 更新model對象的關聯對象 >>> book_obj = models.Book.objects.first() >>> book_obj.authors.set([2, 3]) - remove() - 從關聯對象集合中移除執行的model對象 >>> book_obj = models.Book.objects.first() >>> book_obj.authors.remove(3) - clear() - 從關聯對象集合中移除一切對象 >>> book_obj = models.Book.objects.first() >>> book_obj.authors.clear() - 注意: - 對於ForeignKey對象,clear()和remove()方法僅在null=True時存在 - 舉個例子: ForeignKey字段沒設置null=True時, class Book(models.Model): title = models.CharField(max_length=32) publisher = models.ForeignKey(to=Publisher) 沒有clear()和remove()方法: >>> models.Publisher.objects.first().book_set.clear() Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'RelatedManager' object has no attribute 'clear' 當ForeignKey字段設置null=True時, class Book(models.Model): name = models.CharField(max_length=32) publisher = models.ForeignKey(to=Class, null=True) 此時就有clear()和remove()方法: >>> models.Publisher.objects.first().book_set.clear() 注意: 對於全部類型的關聯字段,add()、create()、remove()和clear(),set()都會立刻更新數據庫。 換句話說,在關聯的任何一端,都不須要再調用save()方法。
6、聚合和分組
- 聚合 - aggregate()是QuerySet的一個終止字句,意思是說,他返回一個包含一些鍵值對的字典 - 鍵的名稱是聚合值得標識符,值是計算出來的聚合值,鍵的名稱是按照字段和聚合該函數的名稱自動生成出來的 - 用到的內置函數 from django.db.models import Avg, Sum, Max, Min, Count 實例: >>> from django.db.models import Avg, Sum, Max, Min, Count >>> models.Book.objects.all().aggregate(Avg("price")) {'price__avg': 13.233333} - 若是想要爲聚合值指定一個名稱,能夠向聚合字句提供他 >>> models.Book.objects.aggregate(average_price=Avg('price')) {'average_price': 13.233333} - 若是但願不止一個聚合,能夠向aggregate()本身中添加另外一個參數。 - 因此,若是想知道全部圖書的價格的最大值,最小值,也能夠這樣查詢 >>> models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price")) {'price__avg': 13.233333, 'price__max': Decimal('19.90'), 'price__min': Decimal('9.90')} - 分組 - 假設有一張公司職員表(employee): id name age salary province dept 1 張三 23 2000 北京 財務部 ... - 使用原生SQl語句,按照部門分組求平均工資 - select dept, AVG(salary) from employee group by dept; ORM查詢 - from django.db.models import Avg - Employee.objects.values("dept").annotate(avg=Avg("salary")).values("dept", "avg") - 假設有一張employee表和一張dept表 employee表 id name age salary province dept_id 1 張三 23 2000 北京 1 ... dept表 id name 1 財務部 ... - 連表查詢的分組 使用原生SQL語句 - select dept.name,AVG(salary) from employee inner join dept on (employee.dept_id=dept.id) group by dept_id; ORM查詢 - from django.db.models import Avg - models.Dept.objects.annotate(avg=Avg("employee__salary")).values("name", "avg") - 更多實例 示例1:統計每一本書的做者個數 >>> book_list = models.Book.objects.all().annotate(author_num=Count("author")) >>> for obj in book_list: print(obj.author_num) 示例2:統計出每一個出版社買的最便宜的書的價格 >>> publisher_list = models.Publisher.objects.annotate(min_price=Min("book__price")) >>> for obj in publisher_list: ... print(obj.min_price) 9.90 19.90 方法二: >>> models.Book.objects.values("publisher__name").annotate(min_price=Min("price")) <QuerySet [{'publisher__name': '沙河出版社', 'min_price': Decimal('9.90')}, {'publisher__name': '人民出版社', 'min_price': Decimal('19.90')}]> 示例3:統計不止一個做者的圖書 >>> models.Book.objects.annotate(author_num=Count("author")).filter(author_num__gt=1) <QuerySet [<Book: 番茄物語>]> 示例4:根據一本圖書做者數量的多少對查詢集 QuerySet進行排序 >>> models.Book.objects.annotate(author_num=Count("author")).order_by("author_num") <QuerySet [<Book: 香蕉物語>, <Book: 橘子物語>, <Book: 番茄物語>]> 示例5:查詢各個做者出的書的總價格 >>> models.Author.objects.annotate(sum_price=Sum("book__price")).values("name", "sum_price") <QuerySet [{'name': '小精靈', 'sum_price': Decimal('9.90')}, {'name': '小仙女', 'sum_price': Decimal('29.80')}, {'name': '小魔女', 'sum_price': Decimal('9.90')}]>
7、F查詢 和 Q查詢
- F 查詢 在上面全部的例子中,咱們構造的過濾器都只是將字段值與某個常量作比較。若是咱們要對兩個字段的值作比較,那該怎麼作呢? Django 提供 F() 來作這樣的比較。F() 的實例能夠在查詢中引用字段,來比較同一個 model 實例中兩個不一樣字段的值。 示例1: 查詢評論數大於收藏數的書籍 from django.db.models import F models.Book.objects.filter(commnet_num__gt=F('keep_num')) Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操做。 models.Book.objects.filter(commnet_num__lt=F('keep_num')*2) 修改操做也可使用F函數,好比將每一本書的價格提升30元 models.Book.objects.all().update(price=F("price")+30) - 引伸: 若是要修改char字段咋辦? 如:把全部書名後面加上(初版) >>> from django.db.models.functions import Concat >>> from django.db.models import Value >>> models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("初版"), Value(")"))) - Q 查詢 filter() 等方法中的關鍵字參數查詢都是一塊兒進行「AND」 的。 若是你須要執行更復雜的查詢(例如OR語句),你可使用Q對象。 示例1: 查詢做者名是小仙女或小魔女的 models.Book.objects.filter(Q(authors__name="小仙女")|Q(authors__name="小魔女")) 你能夠組合& 和| 操做符以及使用括號進行分組來編寫任意複雜的Q 對象。同時,Q 對象可使用~ 操做符取反,這容許組合正常的查詢和取反(NOT) 查詢。 示例:查詢做者名字是小仙女而且不是2018年出版的書的書名。 >>> models.Book.objects.filter(Q(author__name="小仙女") & ~Q(publish_date__year=2018)).values_list("title") <QuerySet [('番茄物語',)]> 查詢函數能夠混合使用Q 對象和關鍵字參數。全部提供給查詢函數的參數(關鍵字參數或Q 對象)都將"AND」在一塊兒。可是,若是出現Q 對象,它必須位於全部關鍵字參數的前面。 例如:查詢出版年份是2017或2018,書名中帶物語的全部書。 >>> models.Book.objects.filter(Q(publish_date__year=2018) | Q(publish_date__year=2017), title__icontains="物語") <QuerySet [<Book: 番茄物語>, <Book: 香蕉物語>, <Book: 橘子物語>]>
一、必會的13條數據庫
返回對象列表的django
allapp
filteride
exclude函數
order_byui
reverseatom
distinct
特殊的對象列表
values
values_list
返回對象的
get
first
last
返回布爾值
exist
返回數字的
count
二、單表中雙下滑線
__gt
__lt
__in
__range
__countains
__icountains
__startswith
__istartswith
__endswith
__iendswith
__isnull
正向查詢
按照對象查詢,這個時候只要屢清楚外鍵設置在哪一個方向,按照對象一步一步的
往過屢就ok。
反向查詢
反向查詢的時候經過表名(小寫的類名)_set,拿到這個管理對象,對這個對象
能夠進行表的一些操做。
按字段查詢
按字段查詢的時候就沒有必要屢主外鍵在哪方面,只須要看着要查的結果和條件
而後按雙下劃線方法去查找就ok
正向查詢
Obj.多對多關係 -》 管理對象
add()
remove()
clear()
set() []
create()
反向查詢
Obj.表名(小寫的類名)_set -》 管理對象
聚合是一個終止語句 aggregate
分組的目的是爲了進行聚合操做
分組的結果放到了字段中(values中)
正着來
若是不指定分組對象,那麼按照表名(表名id)分
反着來
這樣是指定values(字段)(也就是分組名稱)來分組
拿到的是對象
from django.db.model import F
兩個字段之間的比較
子段__gt=F("字段")
字段=F(「字段」) * 2
from django.db.model import Q
兩個條件之間的或關係
Q(篩選條件) | Q(篩選條件)
二者條件之間的與關係
Q(篩選條件) & Q(篩選條件)
條件取反
~Q(篩選條件)
把一些列的操做(步驟)看成一個事務
所有的步驟都成功才成功
經典例子:銀行轉帳
代碼實現:
import os
if name == 'main': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup()
import datetime
from app01 import models
try:
from django.db import transaction # 事務
with transaction.atomic(): # 裏面是執行的全部步驟
new_publisher = models.Publisher.objects.create(name="火星出版社")
models.Book.objects.create(title="橘子物語", publish_date=datetime.date.today(), publisher_id=10) # 指定一個不存在的出版社id
except Exception as e:
print(str(e))