字段 | DB Type |
---|---|
AutoField | integer AUTO_INCREMENT |
BigAutoField | bigint AUTO_INCREMENT |
BinaryField | longblob |
BooleanField | bool |
CharField | varchar |
CommaSeparatedIntegerField | varchar |
DateField | date |
DateTimeField | datetime |
DecimalField | numeric |
DurationField | bigint |
FileField | varchar |
FilePathField | varchar |
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 |
SmallIntegerField | smallint |
TextField | longtext |
TimeField | time |
UUIDField | char(32) |
字段 | 說明 |
---|---|
AutoField | int自增列,必須填入參數 primary_key=True。當model中若是沒有自增列,則自動會建立一個列名爲id的列。 |
IntegerField | 一個整數類型,範圍在 -2147483648 to 2147483647。 |
CharField | 字符類型,必須提供max_length參數, max_length表示字符長度。 |
DateField | 日期字段,日期格式 YYYY-MM-DD,至關於Python中的datetime.date()實例。 |
DateTimeField | 日期時間字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],至關於Python中的datetime.datetime()實例。 |
BigAutoField | bigint自增列,必須填入參數 primary_key=True。當model中若是沒有自增列,則自動會建立一個列名爲id的列。 |
SmallIntegerField | 小整數 -32768 ~ 32767 |
PositiveSmallIntegerField | 正小整數 0 ~ 32767 |
PositiveIntegerField | 正整數 0 ~ 2147483647 |
BigIntegerField | 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807 |
BooleanField | 布爾值類型 |
NullBooleanField | 能夠爲空的布爾值 |
TextField | 文本類型 |
EmailField | 字符串類型,Django Admin以及ModelForm中提供驗證機制 |
IPAddressField | 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制 |
GenericIPAddressField | 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6 |
URLField | 字符串類型,Django Admin以及ModelForm中提供驗證 URL |
SlugField | 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號) |
CommaSeparatedIntegerField | 字符串類型,格式必須爲逗號分割的數字 |
UUIDField | 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證 |
FilePathField | 字符串,路徑保存在數據庫,文件上傳到指定目錄 |
ImageField | 字符串,路徑保存在數據庫,文件上傳到指定目錄 |
TimeField | 時間格式 HH:MM[:ss[.uuuuuu]] |
DurationField | 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型 |
FloatField | 浮點型 |
DecimalField | 10進制小數 |
BinaryField | 二進制類型 |
此處示例爲建立一個對應db中char類型的字段git
1 class FixedCharField(models.Field): 2 """ 3 自定義的char類型的字段類 4 """ 5 def __init__(self, max_length, *args, **kwargs): 6 self.max_length = max_length 7 super(FixedCharField, self).__init__(max_length=max_length, *args, **kwargs) 8 9 def db_type(self, connection): 10 """ 11 限定生成數據庫表的字段類型爲char,長度爲max_length指定的值 12 """ 13 return 'char(%s)' % self.max_length
1 class Class(models.Model): 2 id = models.AutoField(primary_key=True) 3 # 使用自定義的char類型的字段 4 name= FixedCharField(max_length=25)
參數 | 說明 | 可用字段 |
---|---|---|
null | 用於表示某個字段能夠爲空。 | all |
unique | 若是設置爲unique=True 則該字段在此表中必須是惟一的 。 | all |
db_index | 若是db_index=True 則表明着爲此字段設置索引。 | all |
default | 爲該字段設置默認值。 | all |
auto_now_add | 配置auto_now_add=True,建立數據記錄的時候會把當前時間添加到數據庫 | DateField和DateTimeField |
auto_now | 配置上auto_now=True,每次更新數據記錄的時候會更新該字段。 | DateField和DateTimeField |
外鍵類型在ORM中用來表示外鍵關聯關係,通常把ForeignKey字段設置在 '一對多'中'多'的一方。ForeignKey能夠和其餘表作關聯關係同時也能夠和自身作關聯關係。spring
設置要關聯的表sql
設置要關聯的表的字段數據庫
反向操做時,使用的字段名,用於代替原反向查詢時的'表名_set'。django
1 # 班級 2 class Classes(models.Model): 3 name = models.CharField(max_length=32) 4 # 學生 5 class Student(models.Model): 6 name = models.CharField(max_length=32) 7 theclass = models.ForeignKey(to="Classes") 8 9 # 當咱們要查詢某個班級關聯的全部學生(反向查詢)時,咱們會這麼寫: 10 models.Classes.objects.first().student_set.all() 11 12 # 當咱們在ForeignKey字段中添加了參數related_name後: 13 class Student(models.Model): 14 name = models.CharField(max_length=32) 15 theclass = models.ForeignKey(to="Classes", related_name="students") 16 17 # 當咱們要查詢某個班級關聯的全部學生(反向查詢)時,咱們會這麼寫: 18 models.Classes.objects.first().students.all()
反向查詢操做時,使用的鏈接前綴,用於替換表名。api
當刪除關聯表中的數據時,當前表與其關聯的行的行爲。數據結構
值 | 說明 |
---|---|
models.CASCADE | 刪除關聯數據,與之關聯也刪除 |
models.DO_NOTHING | 刪除關聯數據,引起錯誤IntegrityError |
models.PROTECT | 刪除關聯數據,引起錯誤ProtectedError |
models.SET_NULL | 刪除關聯數據,與之關聯的值設置爲null(前提FK字段須要設置爲可空) |
models.SET_DEFAULT | 刪除關聯數據,與之關聯的值設置爲默認值(前提FK字段須要設置默認值) |
models.SET | 刪除關聯數據,app a. 與之關聯的值設置爲指定值,設置:models.SET(值)。ide b. 與之關聯的值設置爲可執行對象的返回值,設置:models.SET(可執行對象)。函數 ![]() 1 def func(): 2 return 10 3 4 5 class MyModel(models.Model): 6 user = models.ForeignKey( 7 to="User", 8 to_field="id", 9 on_delete = models.SET(func) 10 ) |
是否在數據庫中建立外鍵約束,默認爲True。
一對一字段。一般用來擴展已有字段。
一對一的關聯關係多用在當一張表的不一樣字段查詢頻次差距過大的狀況下,將本能夠存儲在一張表的字段拆開放置在兩張表中,而後將兩張表創建一對一的關聯關係。
1 class Author(models.Model): 2 name = models.CharField(max_length=32) 3 info = models.OneToOneField(to='AuthorInfo') 4 5 6 class AuthorInfo(models.Model): 7 phone = models.CharField(max_length=11) 8 email = models.EmailField()
設置要關聯的表。
設置要關聯的字段。
同ForeignKey字段。
用於表示多對多的關聯關係。在數據庫中經過第三張表來創建關聯關係。
設置要關聯的表。
同ForeignKey字段。
同ForeignKey字段。
僅用於多對多自關聯時,指定內部是否不建立反向操做的屬性(表名_set)。默認爲True(不建立)。
1 class Person(models.Model): 2 name = models.CharField(max_length=16) 3 friends = models.ManyToManyField("self") 4 # 此時,person對象就沒有person_set屬性。 5 6 class Person(models.Model): 7 name = models.CharField(max_length=16) 8 friends = models.ManyToManyField("self", symmetrical=False) 9 # 此時,person對象如今就可使用person_set屬性進行反向查詢。
在使用ManyToManyField字段時,Django將自動生成一張表來管理多對多的關聯關係。但咱們也能夠手動建立第三張表來管理多對多關係,此時就須要經過through來指定第三張表的表名。
設置關聯的字段。
默認建立第三張表時,數據庫中表的名稱。
1 class Book(models.Model): 2 title = models.CharField(max_length=32, verbose_name="書名") 3 4 5 class Author(models.Model): 6 name = models.CharField(max_length=32, verbose_name="做者姓名") 7 8 9 # 本身建立第三張表,分別經過外鍵關聯書和做者 10 class Author2Book(models.Model): 11 author = models.ForeignKey(to="Author") 12 book = models.ForeignKey(to="Book") 13 14 class Meta: 15 unique_together = ("author", "book")
1 class Book(models.Model): 2 title = models.CharField(max_length=32, verbose_name="書名") 3 4 5 # 經過ORM自帶的ManyToManyField自動建立第三張表 6 class Author(models.Model): 7 name = models.CharField(max_length=32, verbose_name="做者姓名") 8 books = models.ManyToManyField(to="Book", related_name="authors")
1 class Book(models.Model): 2 title = models.CharField(max_length=32, verbose_name="書名") 3 4 5 # 本身建立第三張表,並經過ManyToManyField指定關聯 6 class Author(models.Model): 7 name = models.CharField(max_length=32, verbose_name="做者姓名") 8 books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book")) 9 # through_fields接受一個2元組('field1','field2'): 10 # 其中field1是定義ManyToManyField的模型外鍵的名(author),field2是關聯目標模型(book)的外鍵名。 11 12 13 class Author2Book(models.Model): 14 author = models.ForeignKey(to="Author") 15 book = models.ForeignKey(to="Book") 16 17 class Meta: 18 unique_together = ("author", "book")
注意: 當咱們須要在第三張關係表中存儲額外的字段時,就要使用第三種方式。 可是當咱們使用第三種方式建立多對多關聯關係時,就沒法使用set、add、remove、clear方法來管理多對多的關係了,須要經過第三張表的model來管理多對多關係。
ORM對應的類裏面包含另外一個Meta類,而Meta類封裝了一些數據庫的信息。主要字段以下:
ORM在數據庫中的表名默認是 app_類名,能夠經過db_table能夠重寫表名。
聯合索引。
聯合惟一索引。
指定默認按什麼字段排序。 只有設置了該屬性,咱們查詢到的結果才能夠被reverse()。
函數 | 說明 | 返回值 |
---|---|---|
all() | 查詢全部結果。 | QuerySet |
filter(**kwargs) | 它包含了與所給篩選條件相匹配的對象。 | QuerySet |
get(**kwargs) | 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。 | 單個對象 |
exclude(**kwargs) | 它包含了與所給篩選條件不匹配的對象。 | QuerySet |
values(*field) | 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列model的實例化對象,而是一個可迭代的字典序列。 | 特殊的QuerySet |
values_list(*field) | 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列。 | 特殊的QuerySet |
order_by(*field) | 對查詢結果排序。 | QuerySet |
reverse() | 對查詢結果反向排序,請注意reverse()一般只能在具備已定義順序的QuerySet上調用(在model類的Meta中指定ordering或調用order_by()方法)。 | QuerySet |
distinct() | 從返回結果中剔除重複紀錄(若是你查詢跨越多個表,可能在計算QuerySet時獲得重複的結果。此時可使用distinct(),注意只有在PostgreSQL中支持按字段去重。) | QuerySet |
count() | 返回數據庫中匹配查詢(QuerySet)的對象數量。 | integer |
first() | 返回第一條記錄。 | 單個對象 |
last() | 返回最後一條記錄。 | 單個對象 |
exists() | 若是QuerySet包含數據,就返回True,不然返回False | boolean |
1 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 獲取id大於1 且 小於10的值 2 3 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等於十一、2二、33的數據 4 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in 5 6 models.Tb1.objects.filter(name__contains="ven") # 獲取name字段包含"ven"的 7 models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 8 9 models.Tb1.objects.filter(id__range=[1, 3]) # id範圍是1到3的,等價於SQL的bettwen and 10 11 相似的還有:startswith,istartswith, endswith, iendswith 12 13 date字段還能夠: 14 models.Class.objects.filter(first_day__year=2017)
1 book_obj = models.Book.objects.first() # 第一本書對象 2 print(book_obj.publisher) # 獲得這本書關聯的出版社對象 3 print(book_obj.publisher.name) # 獲得出版社對象的名稱
1 print(models.Book.objects.values_list("publisher__name"))
1 publisher_obj = models.Publisher.objects.first() # 找到第一個出版社對象 2 books = publisher_obj.book_set.all() # 找到第一個出版社出版的全部書 3 titles = books.values_list("title") # 找到第一個出版社出版的全部書的書名
1 titles = models.Publisher.objects.values_list("book__title")
"關聯管理器"是在一對多或者多對多的關聯上下文中使用的管理器。
它存在於下面兩種狀況:
外鍵關係的反向查詢
多對多關聯關係
簡單來講就是當點(".")後面的對象可能存在多個的時候就可使用如下的方法。
建立一個新的對象,保存對象,並將它添加到關聯對象集之中,返回新建立的對象。
1 import datetime 2 models.Author.objects.first().book_set.create(title="番茄物語", publish_date=datetime.date.today())
添加對象,把指定的model對象添加到關聯對象集中。
1 author_objs = models.Author.objects.filter(id__lt=3) 2 models.Book.objects.first().authors.add(*author_objs) 3 # 直接用id關聯 4 models.Book.objects.first().authors.add(*[1, 2])
更新model對象的關聯對象。
1 book_obj = models.Book.objects.first() 2 book_obj.authors.set([2, 3])
從關聯對象集中移除執行的model對象。
1 book_obj = models.Book.objects.first() 2 book_obj.authors.remove(3)
從關聯對象集中移除一切對象。
1 book_obj = models.Book.objects.first() 2 book_obj.authors.clear()
現有模型及其數據信息以下:
1 from django.db import models 2 3 4 class Press(models.Model): 5 ''' 6 出版社 7 ''' 8 id = models.AutoField(primary_key=True) 9 name = models.CharField(max_length=50, unique=True) 10 11 12 class Book(models.Model): 13 ''' 14 書籍 15 ''' 16 id = models.AutoField(primary_key=True) 17 name = models.CharField(max_length=50, unique=True) 18 price = models.DecimalField(max_digits=5, decimal_places=2) 19 stock = models.IntegerField() 20 saleNumber = models.IntegerField() 21 press = models.ForeignKey(Press)
Press表:
Book表:

aggregate()是QuerySet 的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。 鍵的名稱是聚合值的標識符,值是計算出來的聚合值。鍵的名稱是按照字段和聚合函數的名稱自動生成出來的。
1 # 聚合 2 from django.db.models import Avg, Max, Min, Count 3 4 print(models.Book.objects.all().aggregate(Avg('price'), Max('price'), Min('price'),Count('id'))) 5 ''' 6 result: 7 {'price__avg': 44.713333, 'price__max': Decimal('65.30'), 'price__min': Decimal('32.54'), 'id__count': 3} 8 '''
使用annotate()函數,對應數據庫中的'group by'語句。
1 # 查詢每一個出版社(Press)擁有的書籍(Book)數量 2 from django.db.models import Count 3 press_list = models.Press.objects.all().annotate(book_count=Count('book')) 4 [print(press_info, '出版社名稱:{},書籍數量:{}'.format(press_info.name, press_info.book_count)) for press_info in press_list] 5 ''' 6 result: 7 Press object 出版社名稱:長江出版社,書籍數量:2 8 Press object 出版社名稱:電子工業出版社,書籍數量:1 9 Press object 出版社名稱:清華大學出版社,書籍數量:0 10 ''' 11 # values 12 press_list = models.Press.objects.all().annotate(book_count=Count('book')).values('name', 'book_count') 13 [print(press_info) for press_info in press_list] 14 ''' 15 result: 16 {'name': '長江出版社', 'book_count': 2} 17 {'name': '電子工業出版社', 'book_count': 1} 18 {'name': '清華大學出版社', 'book_count': 0} 19 ''' 20 # value_list 21 press_list = models.Press.objects.all().annotate(book_count=Count('book')).values_list('name', 'book_count') 22 [print(press_info) for press_info in press_list] 23 24 ''' 25 result: 26 ('長江出版社', 2) 27 ('電子工業出版社', 1) 28 ('清華大學出版社', 0) 29 '''
from django.db.models import F
一、原來的filter只是單個字段和具體值之間的比較,使用F函數能夠實現兩個字段值之間的比較。
1 # 查詢庫存數量大於銷售數量的書籍 2 [print(book.name) for book in models.Book.objects.all().filter(stock__gt=F('saleNumber'))] 3 ''' 4 result: 5 django深刻解析 6 spring源碼解析 7 ''' 8 9 # 操做字符串 10 # 給每本書名後加上「噹噹網出售」 11 from django.db.models.functions import Concat 12 from django.db.models import Value 13 14 models.Book.objects.update(name=Concat('F("name")', Value("噹噹網出售"))) 15 16 # result:
二、F對象也支持使用算數運算:
list.filter(bread__gte=F('bcommet') * 2)
三、F對象中還能夠寫做「模型類__列名」進行關聯查詢:
list.filter(isDelete=F('heroinfo__isDelete'))
四、對於date/time字段,可與timedelta()進行運算:
list.filter(bpub_date__lt=F('bpub_date') + timedelta(days=1))
from django.db.models import Q
一、filter() 等方法中的關鍵字參數查詢都是一塊兒進行「AND」 的。 若是你須要執行更復雜的查詢(例如OR語句),你可使用Q對象。
# 查詢賣出數量大於10 或 價格小於50的書籍 且名字裏包含‘spring’的書籍 [print(book.name) for book in models.Book.objects.filter(Q(saleNumber__gt=10) | Q(price__lt=50), name__contains='spring')] ''' result: spring源碼解析噹噹網出售 '''
二、Q對象包括AND關係和OR關係,能夠用&和|運算符進行鏈接。當以某個運算符鏈接兩個Q對象時,就會產生一個新的Q 對象。 如:下面這段語句就產生了一個Q,這是用 "OR" 關係鏈接:
Q(question__startswith='Who') | Q(question__startswith='What')
三、每種查詢函式(好比 filter(), exclude(), get())除了能接收關鍵字參數之外,也能以位置參數的形式接受一個或多個 Q 對象。若是你給查詢函式傳遞了多個 Q 對象,那麼它們彼此間都是 "AND" 關係。例如:
Poll.objects.get( Q(question__startswith='Who'), Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) )
四、也能夠經過Q對象的children屬性拼湊查詢條件,傳入條件進行查詢:
q1 = Q() q1.connector = 'OR' # 鏈接方式 還有 'AND' q1.children.append(('id', 1)) q1.children.append(('id', 2)) q1.children.append(('id', 3)) models.Tb1.objects.filter(q1)
五、還能夠將多個Q對象合併成一個Q對象進行查詢:
con = Q() q1 = Q() q1.connector = 'OR' q1.children.append(('id', 1)) q1.children.append(('id', 2)) q1.children.append(('id', 3)) q2 = Q() q2.connector = 'OR' q2.children.append(('status', '在線')) con.add(q1, 'AND') con.add(q2, 'AND') models.Tb1.objects.filter(con)
1 try: 2 from django.db import transaction 3 with transaction.atomic(): 4 new_publisher = models.Publisher.objects.create(name="火星出版社") 5 models.Book.objects.create(title="橘子物語", publish_date=datetime.date.today(), publisher_id=10) # 指定一個不存在的出版社id 6 except Exception as e: 7 print(str(e))
結果集修改器,一種提供額外查詢參數的機制。
1 # 查詢全部用戶,並多查詢出年齡是否大於20的一列 2 list = UserInfo.objects.all().extra(select={'gt20': 'age>20'}) 3 [print(u.gt20) for u in list] 4 ''' 5 result: 6 1 7 1 8 0 9 ''' 10 # 查詢年齡大於20的用戶 11 list = UserInfo.objects.all().extra(where=['age>20']) 12 # 等價於 13 list = UserInfo.objects.filter(age__gt=20)
執行原始sql並返回模型實例。
1 list = UserInfo.objects.raw('select * from UserInfo') 2 [print(i.name) for i in list]
惰性查詢,返回rawQuerySet,只有在使用時纔會真正執行。
直接執行自定義Sql(這種方式徹底不依賴model,前兩種仍是要依賴於model)。
1 from django.db import connection 2 3 cursor = connection.cursor() 4 # 插入操做 5 cursor.execute("insert into UserInfo(name,age) values('郭敬明','99')") 6 # 更新操做 7 cursor.execute("update UserInfo set name='張三' where name='張大三'") 8 # 刪除操做 9 cursor.execute("delete from UserInfo where name='張三'") 10 # 查詢操做 11 cursor.execute('select * from UserInfo') 12 for u in cursor: print(u) 13 user_list = cursor.fetchall() # 讀取全部 14 for u in user_list: print(u) 15 16 ''' 17 result: 18 (1, '張三', 21) 19 (2, '李四', 23) 20 (3, '王五', 19) 21 (4, '趙六', 40) 22 '''
現有以下模型:
class User(models.Model): nick_name = models.CharField(max_length=32) age = models.IntegerField()
首先咱們是知道 queryset.values 和 queryset.values_list 方法都是查詢模型中指定字段,可是它們返回值的數據結構是不一樣的。以下:
print(models.User.objects.values('nick_name', 'age')) # <QuerySet [{'nick_name': 'zhangsan', 'age': 12}, {'nick_name': 'lisi', 'age': 32}, {'nick_name': 'wangwu', 'age': 23}]> print(models.User.objects.values_list('nick_name', 'age')) # <QuerySet [('zhangsan', 12), ('lisi', 32), ('wangwu', 23)]>
能夠看到,前者返回的是放着字典的 queryset ,然後者返回是放着元組的 queryset 。下面再看一下 queryset.only 方法:
print(models.User.objects.only('nick_name')) # (0.000) SELECT "api_user"."id", "api_user"."nick_name" FROM "api_user" LIMIT 21; args=() # <QuerySet [<User: User object (1)>, <User: User object (2)>, <User: User object (3)>]>
從 console 打印的 sql 能夠看到, queryset.only 除了查詢指定列還默認查詢了主鍵,而返回值是對應模型對象。再看下面代碼:
user_set = models.User.objects.only('nick_name') for user in user_set: print(user.age) ''' 12 32 23 (0.000) SELECT "api_user"."id", "api_user"."nick_name" FROM "api_user"; args=() (0.000) SELECT "api_user"."id", "api_user"."age" FROM "api_user" WHERE "api_user"."id" = 1; args=(1,) (0.000) SELECT "api_user"."id", "api_user"."age" FROM "api_user" WHERE "api_user"."id" = 2; args=(2,) (0.000) SELECT "api_user"."id", "api_user"."age" FROM "api_user" WHERE "api_user"."id" = 3; args=(3,) '''
能夠看到,當咱們使用 only 中未指定的列時,這個列會即時加載。
user_set = models.User.objects.defer('nick_name') for user in user_set: print(user.age) print(user.nick_name) ''' (0.000) SELECT "api_user"."id", "api_user"."age" FROM "api_user"; args=() (0.000) SELECT "api_user"."id", "api_user"."nick_name" FROM "api_user" WHERE "api_user"."id" = 1; args=(1,) (0.000) SELECT "api_user"."id", "api_user"."nick_name" FROM "api_user" WHERE "api_user"."id" = 2; args=(2,) (0.000) SELECT "api_user"."id", "api_user"."nick_name" FROM "api_user" WHERE "api_user"."id" = 3; args=(3,) '''