python框架之Django(5)-O/RM

字段&參數

字段與db類型的對應關係

字段 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
      Code
    • 使用
      1 class Class(models.Model):
      2     id = models.AutoField(primary_key=True)
      3     # 使用自定義的char類型的字段
      4     name= FixedCharField(max_length=25)
      Code
  • 字段參數

    參數 說明 可用字段
    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

關係字段

  • ForeignKey

    外鍵類型在ORM中用來表示外鍵關聯關係,通常把ForeignKey字段設置在 '一對多'中'多'的一方。ForeignKey能夠和其餘表作關聯關係同時也能夠和自身作關聯關係。spring

    • to

      設置要關聯的表sql

    • to_field

      設置要關聯的表的字段數據庫

    • related_name

      反向操做時,使用的字段名,用於代替原反向查詢時的'表名_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()
      例:
    • related_query_name

      反向查詢操做時,使用的鏈接前綴,用於替換表名。api

    • on_delete

      當刪除關聯表中的數據時,當前表與其關聯的行的行爲。數據結構

      說明
      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     )
      例:
    • db_constraint

      是否在數據庫中建立外鍵約束,默認爲True。

  • OneToOneField

    一對一字段。一般用來擴展已有字段。

    一對一的關聯關係多用在當一張表的不一樣字段查詢頻次差距過大的狀況下,將本能夠存儲在一張表的字段拆開放置在兩張表中,而後將兩張表創建一對一的關聯關係。

    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()
    例:
    • to

      設置要關聯的表。

    • to_field

      設置要關聯的字段。

    • on_delete

      同ForeignKey字段。

  • ManyToManyField

    用於表示多對多的關聯關係。在數據庫中經過第三張表來創建關聯關係。

    • to

      設置要關聯的表。

    • related_name

      同ForeignKey字段。

    • related_query_name

      同ForeignKey字段。

    • symmetrical

      僅用於多對多自關聯時,指定內部是否不建立反向操做的屬性(表名_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屬性進行反向查詢。
      例:
    • through

      在使用ManyToManyField字段時,Django將自動生成一張表來管理多對多的關聯關係。但咱們也能夠手動建立第三張表來管理多對多關係,此時就須要經過through來指定第三張表的表名。

    • through_fields

      設置關聯的字段。

    • db_table

      默認建立第三張表時,數據庫中表的名稱。

    • 建立多對多關係的三種方式
       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")
      方式二:經過ManyToManyField自動建立第三張表
       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")
      方式三:設置ManyTomanyField並指定自行建立的第三張表

      注意: 當咱們須要在第三張關係表中存儲額外的字段時,就要使用第三種方式。 可是當咱們使用第三種方式建立多對多關聯關係時,就沒法使用set、add、remove、clear方法來管理多對多的關係了,須要經過第三張表的model來管理多對多關係。

元信息

ORM對應的類裏面包含另外一個Meta類,而Meta類封裝了一些數據庫的信息。主要字段以下:

  • db_table

    ORM在數據庫中的表名默認是 app_類名,能夠經過db_table能夠重寫表名。

  • index_together

    聯合索引。

  • unique_together

    聯合惟一索引。

  • ordering

    指定默認按什麼字段排序。 只有設置了該屬性,咱們查詢到的結果才能夠被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)
    Code

ForeignKey操做

  • 正向

    • 查找對象
      1 book_obj = models.Book.objects.first()  # 第一本書對象
      2 print(book_obj.publisher)  # 獲得這本書關聯的出版社對象
      3 print(book_obj.publisher.name)  # 獲得出版社對象的名稱
      Code
    • 查找字段
      1 print(models.Book.objects.values_list("publisher__name"))
      Code
  • 反向

    • 查找對象
      1 publisher_obj = models.Publisher.objects.first()  # 找到第一個出版社對象
      2 books = publisher_obj.book_set.all()  # 找到第一個出版社出版的全部書
      3 titles = books.values_list("title")  # 找到第一個出版社出版的全部書的書名
      Code
    • 查找字段
      1 titles = models.Publisher.objects.values_list("book__title")
      Code

ManyToManyField

  • class RelatedManager

    "關聯管理器"是在一對多或者多對多的關聯上下文中使用的管理器。

    它存在於下面兩種狀況:

      外鍵關係的反向查詢

      多對多關聯關係

    簡單來講就是當點(".")後面的對象可能存在多個的時候就可使用如下的方法。

  • 方法

    • create()

      建立一個新的對象,保存對象,並將它添加到關聯對象集之中,返回新建立的對象。

      1 import datetime
      2 models.Author.objects.first().book_set.create(title="番茄物語", publish_date=datetime.date.today())
      Code
    • add()

      添加對象,把指定的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])
      Code
    • set()

      更新model對象的關聯對象。

      1 book_obj = models.Book.objects.first()
      2 book_obj.authors.set([2, 3])
      Code
    • remove()

      從關聯對象集中移除執行的model對象。

      1 book_obj = models.Book.objects.first()
      2 book_obj.authors.remove(3)
      Code
    • clear()

      從關聯對象集中移除一切對象。

      1 book_obj = models.Book.objects.first()
      2 book_obj.authors.clear()
      Code
  • 注意

    1. 對於經過ForeignKey關聯的對象,clear()和remove()方法僅在null=True時存在。
    2. 對於全部類型的關聯字段,即便不調用save()方法,執行add()、create()、remove()、clear()和set()也會立刻更新數據庫。

查詢

現有模型及其數據信息以下:

 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 '''
      例:
  • F和Q

    • F查詢
      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))
      例:
    • Q查詢
      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查詢時,字段查詢必須放在Q查詢後面。

      二、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))
Code

執行原生Sql

  • extra

    結果集修改器,一種提供額外查詢參數的機制。

     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)
    例:
  • raw

    執行原始sql並返回模型實例。

    1 list = UserInfo.objects.raw('select * from UserInfo')
    2 [print(i.name) for i in list]
    例:

    惰性查詢,返回rawQuerySet,只有在使用時纔會真正執行。

  • cursor

    直接執行自定義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 '''
    例:

查詢指定列之only&defer

現有以下模型:

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 方法:

  • 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 中未指定的列時,這個列會即時加載。

  • queryset.defer

    queryset.defer 與上面的 queryset.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,)
    '''
相關文章
相關標籤/搜索