(7)Django-模型與數(shù)據(jù)庫

Django對各種數(shù)據(jù)庫都提供了很好的支持,而且為這些數(shù)據(jù)庫提供了統(tǒng)一的調(diào)用API其骄,這些API統(tǒng)稱為ORM框架。通過使用Django內(nèi)置的ORM框架可以實現(xiàn)數(shù)據(jù)庫連接和讀寫操作偿渡。


構(gòu)建模型

ORM框架是一種程序技術(shù)帆谍,用于實現(xiàn)面向?qū)ο缶幊陶Z言中不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換。從效果上說行您,其實是創(chuàng)建了一個可在編程語言中使用的“虛擬對象數(shù)據(jù)庫”铭乾,通過對虛擬對象數(shù)據(jù)庫操作,從而實現(xiàn)對目標數(shù)據(jù)庫的操作娃循,虛擬對象數(shù)據(jù)庫與目標數(shù)據(jù)庫是相互對應的炕檩。在Django中,虛擬對象數(shù)據(jù)庫也稱為模型捌斧,通過模型實現(xiàn)對目標數(shù)據(jù)庫的讀寫操作笛质。實現(xiàn)方法如下:

  1. 需要在項目的settings.py中設(shè)置數(shù)據(jù)庫信息泉沾,具體參考前面的章節(jié)
  2. 構(gòu)建虛擬對象數(shù)據(jù)庫妇押,在App的models.py文件中以類的形式定義模型跷究。
  3. 通過模型在目標數(shù)據(jù)庫中創(chuàng)建相應的數(shù)據(jù)表。
  4. 在視圖函數(shù)中通過對模型操作實現(xiàn)目標數(shù)據(jù)庫的讀寫操作舆吮。
    以mysql數(shù)據(jù)庫為例揭朝,在settings.py中配置如下:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  #mysql引擎
        'NAME': 'mysite',  #數(shù)據(jù)庫名
        'USER':'root',  #用戶名
        'PASSWORD':'123456',  #密碼
        'HOST':'127.0.0.1',  #主機地址,默認本機
        'PORT':'3306',  #默認端口
    }
}

在setting.py中配置好數(shù)據(jù)庫后色冀,就可以到項目app的models.py文件中定義模型潭袱,以前文的index為例:

from django.db import models
#創(chuàng)建產(chǎn)品分類表
class Type(models.Model):
    id = models.AutoField(primary_key=True)
    type_name = models.CharField(max_length=20)
#創(chuàng)建產(chǎn)品信息表
class Product(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=50)
    weight = models.CharField(max_length=20)
    size = models.CharField(max_length=20)
    type = models.ForeignKey(Type, on_delete=models.CASCADE)

完成模型的定義后,需要通過執(zhí)行makemigrations和migrate指令來創(chuàng)建數(shù)據(jù)表锋恬,命令如下:

#項目根目錄下cmd
 python manage.py makemigrations
 python manage.py migrate

執(zhí)行完以上兩個指令后屯换,就可以在數(shù)據(jù)庫中生成相對應的數(shù)據(jù)表index_product和index_type,這兩個表分別對應模型Product和Type与学。其他數(shù)據(jù)表是Django內(nèi)置功能所使用的數(shù)據(jù)表彤悔。
上面的例子中,在模型Product和Type中定義的字段類型有整型和字符串類型索守,在實際開發(fā)中晕窑,我們需要定義不同的數(shù)據(jù)類型來滿足各種需求,Django劃分了多種不同的數(shù)據(jù)類型:

表字段 說明
models.AutoField 默認生成一個名為id的字段并未Int類型
models.CharField 字符串類型
models.BooleanField 布爾類型
models.ComaSeparatedIntegerField 用逗號分隔的整數(shù)類型
models.DateField 日期(date)類型
models.DateTimeField 日期(datetime)類型
models.Decimal 十進制小數(shù)類型
models.EmailField 字符串類型(正則表達式郵箱)
models.FloatField 浮點類型
models.IntegerField 整數(shù)類型
models.BigIntegerField 長整數(shù)類型
models.IPAddressField 字符串類型(IPv4正則表達式)
models.GenericIPAddressField 字符串類型卵佛,參數(shù)protocol可以是:both杨赤、IPv4和IPv6,驗證IP地址
models.NullBooleanField 允許為空的布爾類型
models.PositiveIntegerField 正整數(shù)的整數(shù)類型
models.PositiveSmallIntegerField 小正整數(shù)類型
models.SlugField 包含字母截汪、數(shù)字疾牲、下劃線和連字符的字符串,常用語URL
models.SmallIntegerField 小整數(shù)類型衙解,取值范圍(-32,768~+32767)
models.TextField 長文本類型
models.TimeField 時間類型阳柔,顯示時分秒HH:MM[:ss[.uuuuuu]]
models.URLField 字符串,地址為正則表達式
models.BinaryField 二進制數(shù)據(jù)類型

除了表字段類型之外蚓峦,每個表字段還可以設(shè)置相應的參數(shù)舌剂,使得表字段更加完善。

參數(shù) 說明
Null 如為True暑椰,字段是否可以為空
Blank 如為True霍转,設(shè)置在Admin站點管理中添加數(shù)據(jù)時可允許空值
Default 設(shè)置默認值
primary_key 如為True,將字段設(shè)置為主鍵
db_column 設(shè)置數(shù)據(jù)庫中的字段名稱
Unique 如為True干茉,將字段設(shè)置成唯一屬性,默認為False
db_index 如為True很泊,為字段添加數(shù)據(jù)庫索引
verbose_name 為Admin站點管理設(shè)置字段的顯示名稱
related_name 關(guān)聯(lián)對象反向引用描述符角虫,用于多表查詢沾谓,可解決一個數(shù)據(jù)表有兩個外鍵同時指向另一個數(shù)據(jù)表而出現(xiàn)重名的問題

數(shù)據(jù)表的關(guān)系

表與表之間有三種關(guān)系:一對一、一對多和多對多戳鹅。

  • 一對一關(guān)系通常是一個數(shù)據(jù)表有太多字段均驶,將常用字段抽取出來并組成一個新的數(shù)據(jù)表。在模型中可以通過OneToOneField來構(gòu)建數(shù)據(jù)表的一對一關(guān)系枫虏。
  • 一對多關(guān)系是最常見的表關(guān)系妇穴,在模型中可以通過ForeignKey來構(gòu)建數(shù)據(jù)表的一對多關(guān)系。
  • 多對多關(guān)系存在于在兩個或兩個以上的數(shù)據(jù)表中隶债,第一個表的某一行數(shù)據(jù)可以與第二個表的一到多行數(shù)據(jù)進行關(guān)聯(lián)腾它,同時在第二個表中的某一行數(shù)據(jù)也可以與第一個表的一到多行數(shù)據(jù)進行關(guān)聯(lián)。在多對多關(guān)系中死讹,需要使用新的數(shù)據(jù)表來管理兩個表的數(shù)據(jù)關(guān)系瞒滴。在模型中可以通過ManyToManyField來構(gòu)建數(shù)據(jù)表的多對多關(guān)系。
    代碼如下:
#models.py
#一對一關(guān)系
class Performer(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=20)
    nationality = models.CharField(max_length=20)
    masterpiece = models.CharField(max_length=50)

class Performer_info(models.Model):
    id = models.IntegerField(primary_key=True)
    performer = models.OneToOneField(Performer,on_delete=models.CASCADE)
    birth = models.CharField(max_length=20)

#一對多關(guān)系
class Performer(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=20)
    nationality = models.CharField(max_length=20)

class Performer_info(models.Model):
    id = models.IntegerField(primary_key=True)
    performer = models.ForeignKeyField(Performer,on_delete=models.CASCADE)
    birth = models.CharField(max_length=20)

#多對多關(guān)系
class Performer(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=20)
    nationality = models.CharField(max_length=20)

class Performer_info(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=20)
    performer = models.ManyToManyField(Performer)

數(shù)據(jù)表的讀寫

數(shù)據(jù)庫的讀寫操作主要是對數(shù)據(jù)進行增赞警、刪妓忍、改、查愧旦。

在Django中世剖,向數(shù)據(jù)表中插入數(shù)據(jù)有以下幾種方法:

方法一,通過實例化模型笤虫,再對對象屬性逐一賦值旁瘫,最后保存

>>> from index.models import *
>>> p = Product()
>>> p.name = '榮耀V9'
>>> p.weight = '111g'
>>> p.size = '120*75*7mm'
>>> p.type_id = 1
>>> p.save()

方法二,通過Django的ORM框架提供的API實現(xiàn)耕皮,使用create方法實現(xiàn)數(shù)據(jù)插入

>>> from index.models import *
>>> Product.objects.create(name='榮耀 V9', weight='111g', size='120*75*7mm',type_id = 1)
<Product: Product object (13)>

方法三境蜕,在實例化時直接設(shè)置屬性值

>>> from index.models import *
>>> p = Product(name='榮耀 V9', weight='111g', size='120*75*7mm',type_id = 1)
>>> p.save()

如果要對數(shù)據(jù)進行更新,實現(xiàn)步驟與數(shù)據(jù)插入的方法大致相同凌停,唯一的區(qū)別是在模型實例化后粱年,要更新數(shù)據(jù),需要先進行一次數(shù)據(jù)查詢罚拟,將查詢結(jié)果以對象的形式賦給p台诗,最后對p的屬性重新賦值就能實現(xiàn)數(shù)據(jù)的更新。

>>> p = Product.objects.get(id=14)
>>> p.name = '華為榮耀 V9'
>>> p.save()

除此以外赐俗,還可以使用update方法實現(xiàn)單條或多條數(shù)據(jù)的更新拉队。

查詢單條并更新
>>> Product.objects.filter(id=13).update(name='華為榮耀 V9')
1
查詢多條并更新
>>> Product.objects.filter(name='華為榮耀 V9').update(name='華為榮耀 V10')
2
不查詢,對全表數(shù)據(jù)進行更新
>>> Product.objects.update(name='華為榮耀 V9')
14

如果要對數(shù)據(jù)進行刪除阻逮,也有三種方法:

刪除一條id為1的數(shù)據(jù)
>>> Product.objects.get(id=1).delete()
(1, {'index.Product': 1})
刪除多條數(shù)據(jù)
>>> Product.objects.filter(type_id=2).delete()
(2, {'index.Product': 2})
刪除表中全部數(shù)據(jù)
>>> Product.objects.all().delete()
(11, {'index.Product': 11})

數(shù)據(jù)查詢是數(shù)據(jù)庫操作中最為復雜且內(nèi)容最多的部分粱快。

全表查詢,等同于SQL語句 select * from index_product,返回數(shù)據(jù)的列表
>>> from index.models import *
>>> p = Product.objects.all()
>>> p[1].name
'HUAWEI nova 2s'
查詢前5條數(shù)據(jù)事哭,等同于 select * from index_product LIMIT 5
>>> p = Product.objects.all()[:5]
>>> p[4].name
'PORSCHE DESIGN'
>>> p[5].name
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\models\query.py", line 303, in __getitem__
    return qs._result_cache[0]
IndexError: list index out of range
查詢某個字段漫雷,等同于Select name from index_product
values方法,以列表形式返回數(shù)據(jù)鳍咱,列表元素以字典格式表示
>>> p = Product.objects.values('name')
>>> p[1]['name']
'HUAWEI nova 2s'

values_list方法降盹,以列表形式表示返回數(shù)據(jù),列表元素以元組格式表示
>>> p = Product.objects.values_list('name')[:3]
>>> p
<QuerySet [('榮耀V10',), ('HUAWEI nova 2s',), ('榮耀Waterplay',)]>
使用get方法查詢數(shù)據(jù)谤辜,等同于Select * from index_product where id=2
>>> p = Product.objects.get(id=2)
>>> p.name
'HUAWEI nova 2s'
使用filter方法查詢數(shù)據(jù)蓄坏,注意區(qū)分get和filter的差異:filter返回的是列表
>>> p = Product.objects.filter(id=2)
>>> p[0].name
'HUAWEI nova 2s'
SQL的 and 查詢主要在filter里面添加多個查詢條件
>>> p = Product.objects.filter(id=4,name='榮耀暢玩平板')
>>> p
<QuerySet [<Product: Product object (4)>]>
SQL的 or 查詢,需要引入Q丑念,編寫格式:Q(field=value) | Q(field=value)
等同于Select * from index_product where name='華為榮耀V9' or id=6
>>> from django.db.models import Q
>>> p = Product.objects.filter(Q(name='華為榮耀V9') | Q(id=6))
>>> p
<QuerySet [<Product: Product object (6)>, <Product: Product object (9)>, <Product: Product object (10)>, <Product: Product object (11)>]>
>>>
使用count方法統(tǒng)計查詢數(shù)據(jù)的數(shù)據(jù)量
>>> p = Product.objects.filter(name='華為榮耀V9').count()
>>> p
3
去重查詢涡戳, distinct方法無須設(shè)置參數(shù),去重方法根據(jù)values設(shè)置的字段執(zhí)行
等同于 Select DISTINCT name from index_product where name='華為榮耀V9'
>>> p = Product.objects.values('name').filter(name='華為榮耀V9').distinct()
>>> p
<QuerySet [{'name': '華為榮耀V9'}]>
>>>
根據(jù)id降序排列渠欺,降序只要在order_by里面的字段前面加“ - ”即可
order_by可設(shè)置多字段排列妹蔽,如Product.objects.order_by('-id', name)
>>> p = Product.objects.order_by('-id')
>>> p
<QuerySet [<Product: Product object (11)>, <Product: Product object (10)>, <Product: Product object (9)>,
 ...
聚合查詢,實現(xiàn)對數(shù)據(jù)值求和挠将、求平均值等胳岂。Django提供annotate和aggregate方法實現(xiàn)
annotate類似于SQL的group by方法,如果不設(shè)置values舔稀,就會默認對主鍵進行g(shù)roup by 分組
等同于SQL語句 Select name,SUM(id) AS 'id_sum' from index_product GROUP BY name ORDER BY NULL
>>> from django.db.models import Sum, Count
>>> p = Product.objects.values('name').annotate(Sum('id'))
>>> p
<QuerySet [{'name': '榮耀V10', 'id__sum': Decimal('1')}, {'name': 'HUAWEI nova 2s', 'id__sum': Decimal('2')}, {'name': '榮耀Waterplay', 'id__sum': Decimal('3')}, {'name': '榮耀暢玩平板', 'id__sum': Decimal('4')}, {'name': 'PORSCHE DESIGN', 'id__sum': Decimal('5')}, {'name': '華為運動手環(huán)', 'id__sum': Decimal('6')}, {'name': '榮耀移動電源10000mAh', 'id__sum': Decimal('7')}, {'name': '榮耀體脂秤
', 'id__sum': Decimal('8')}, {'name': '華為榮耀V9', 'id__sum': Decimal('30')}]>

aggregate是將某個字段的值進行計算并只返回計算結(jié)果
等同于Select COUNT(id) as 'id_count' from index_product
>>> from django.db.models import Count
>>> p = Product.objects.aggregate(id_count=Count('id'))
>>> p
{'id_count': 11}

其他匹配符

上述代碼在查詢時主要使用等值的方法來匹配結(jié)果乳丰,如果想使用大于、不等于和模糊查詢的匹配方法内贮,則可以使用以下匹配符實現(xiàn)产园。

匹配符 使用 說明
__exact filter(name__exact='榮耀') 精確等于,如同SQL的 like '榮耀'
__iexact filter(name__iexact='榮耀') 精確等于并忽略大小寫
__contains filter(name__contains='榮耀') 模糊匹配夜郁,同SQL的 like '%榮耀%'
__icontains filter(name__icontains='榮耀') 模糊匹配什燕,忽略大小寫
__gt filter(id__gt=5) 大于
__gte filter(id__gte=5) 大于等于
__lt filter(id__lt=5) 小于
__lte filter(id__lte=5) 小于等于
__in filter(id__in=[1,2,3]) 判斷是否在列表內(nèi)
__startswith filter(name__startswith='榮耀') 以...開頭
__istartswith filter(name__istartswith='榮耀') 以...開頭,并忽略大小寫
__endswith filter(name__endswith='榮耀') 以...結(jié)尾
__iendswith filter(name__iendswith='榮耀') 以...結(jié)尾,并忽略大小寫
__range fitler(name__range='榮耀') 在...范圍內(nèi)
__year filter(date__year=2018) 日期字段的年份
__month filter(date__month=12) 日期字段的月份
__day filter(date__day=30) 日期字段的天數(shù)
__isnull filter(name__isnull=True/False) 判斷是否為空

舉個例子:

查詢 id>9 的數(shù)據(jù)
>>> p = Product.objects.filter(id__gt=9)
>>> p
<QuerySet [<Product: Product object (10)>, <Product: Product object (11)>]>
>>>

多表查詢

以上僅僅局限在單個數(shù)據(jù)表的操作蚜厉,在日常開發(fā)中,常常需要對多個數(shù)據(jù)表同時進行數(shù)據(jù)查詢技俐。多個數(shù)據(jù)表查詢需要數(shù)據(jù)表之間建立了表關(guān)系才得以實現(xiàn)雕擂。
一對一或一對多的表關(guān)系是通過外鍵實現(xiàn)關(guān)聯(lián)的谤逼,而多表查詢分為正向查詢和反向查詢。
以模型Type和Product為例:

  • 如果查詢對象的主體是模型Type,要查詢模型Type的數(shù)據(jù)列肢,那么該查詢稱為正向查詢
  • 如果查詢的主體是模型Type恰画,要通過模型Type查詢模型Product的數(shù)據(jù),那么該查詢稱為反向查詢瓷马。
>>> from index.models import *
>>> t = Type.objects.filter(product__id=11)

正向查詢
>>> t
<QuerySet [<Type: Type object (1)>]>
>>> t[0].type_name
'手機'

反向查詢
>>> t[0].product_set.values('name')
<QuerySet [{'name': '榮耀V10'}, {'name': 'HUAWEI nova 2s'}, {'name': '華為榮耀V9'}, {'name': '華為榮耀V9'}, {'name': '華為榮耀V9'}]>

正向查詢的查詢對象主體和查詢的數(shù)據(jù)都來自于模型Type拴还,因此正向查詢在數(shù)據(jù)庫中只執(zhí)行一次SQL查詢。而反向查詢先查詢模型Type的數(shù)據(jù)欧聘,然后根據(jù)第一次查詢的結(jié)果再查詢與模型Product相互關(guān)聯(lián)的數(shù)據(jù)片林。
為了減少反向查詢的查詢次數(shù),可以使用select_related方法實現(xiàn)怀骤。

select_related的使用說明如下:
  • 模型A或B均可作為查詢對象主體费封,只要兩者之間有外鍵關(guān)聯(lián)即可。
  • select_related的參數(shù)值是查詢主體模型定義的字段蒋伦,如Product.objects.select_related('type')弓摘,type是模型Product的字段。
  • 如果在查詢中需要使用另一個數(shù)據(jù)表的字段痕届,可以使用“外鍵__字段名”來指向該表的字段韧献。如type__type_name代表由模型Product的外鍵type指向模型Type的字段type_name。
查詢模型Product的字段name和模型Type的字段type_name
相當于SQL的 SELECT `name`, `type_name` FROM `index_product` INNER JOIN `index_type` ON (`type_id` = `id`)
>>> p = Product.objects.select_related('type').values('name', 'type__type_name')
>>> p
<QuerySet [{'name': '榮耀V10', 'type__type_name': '手機'}, {'name': 'HUAWEI nova 2s', 'type__type_name': '手機'}, {'name': '華為榮耀V9', 'type__type_name': '手機'}, {'name': '華為榮耀V9', 'type__type_name': '手機'}, {'name': '華為榮耀V9', 'type__type_name': '手機'}, {'name': '榮耀Waterplay', 'type__type_name': '平板電腦'}, {'name': '榮耀暢玩平板', 'type__type_name': '平板電腦'}, {'name': 'PORSCHE DESIGN', 'type__type_name': '智能穿戴'}, {'name': '華為運動手環(huán)', 'type__type_name': '智能穿戴'}, {'name': '榮耀移動電源10000mAh', 'type__type_name': '通用配件'}, {'name': '榮耀體脂秤', 'type__type_name': '通用配件'}]>
查詢兩個模型的全部數(shù)據(jù)
相當于SQL的 SELECT * FROM `index_product` INNER JOIN `index_type` ON (`type_id` = `id`)
>>> p = Product.objects.select_related('type').all()
>>> p
<QuerySet [<Product: Product object (1)>, <Product: Product object (2)>, <Product: Product object (9)>, <Product: Product object (10)>, <Product: Product object (11)>, <Product: Product object (3)>, <Product: Product object (4)>, <Product: Product object (5)>, <Product: Product object (6)>, <Product: Product object (7)>, <Product: Product object (8)>]>
獲取兩個模型的數(shù)據(jù)研叫,以模型Product的id大于8為查詢條件
相當于SQL的 SELECT * FROM `index_product` INNER JOIN `index_type` ON (`type_id` = `id`) WHERE `index_product`.`id` > 8
>>> p = Product.objects.select_related('type').filter(id__gt=8)
>>> p
<QuerySet [<Product: Product object (9)>, <Product: Product object (10)>, <Product: Product object (11)>]>
獲取兩個模型的數(shù)據(jù)锤窑,以模型Type的type_name字段等于手機為查詢條件
相當于 SQL 的 SELECT * FROM `index_product` INNER JOIN `index_type` ON (`type_id` = `id`) WHERE `index_type`.`type_name` = 手機
>>> p =Product.objects.select_related('type').filter(type__type_name='手機').all()
>>> p
<QuerySet [<Product: Product object (1)>, <Product: Product object (2)>, <Product: Product object (9)>, <Product: Product object (10)>, <Product: Product object (11)>]>
>>> p[0]
<Product: Product object (1)>
>>> p[0].type
<Type: Type object (1)>
>>> p[0].type.type_name
'手機'

除此之外,select_related還可以支持三個或三個以上的數(shù)據(jù)表同時查詢嚷炉,以常見的學校-班級-學生為例渊啰。

from django.db import models
#學校
class Schools(models.Model):
    sid = models.AutoField('序號',primary_key=True)
    sname = models.CharField('校名', max_length=50)
#班級
class Classes(models.Model):
    cid = models.AutoField('序號', primary_key=True)
    cname = models.CharField('班名', max_length=10)
    sid = models.ForeignKey(Schools, on_delete=models.CASCADE)
#學生
class Students(models.Model):
    pid = models.AutoField('序號', primary_key=True)
    pname = models.CharField('姓名', max_length=10)
    cid = models.ForeignKey(Classes, on_delete=models.CASCADE)

上面的模型中,學生表通過外鍵cid關(guān)聯(lián)到班級表渤昌,班級表通過外鍵sid關(guān)聯(lián)到學校表虽抄。執(zhí)行完遷移建好表后,我們向數(shù)據(jù)表中添加如下數(shù)據(jù):


學校表

班級表

學生表

多表查詢主要情況有兩種独柑,一種是從大往小查迈窟,即從學校查到學生;一種是從小往大查忌栅,即從學生查到學校车酣。
第一種情況:如曲稼,我們要查蘇州健雄學校下的所有學生。

>>> from school.models import Schools,Classes,Students
>>> p = Students.objects.select_related('cid__sid').filter(cid__sid__sname='蘇州健雄')
>>> p
<QuerySet [<Students: Students object (1)>, <Students: Students object (2)>, <Students: Students object (3)>]>
>>> for u in p:
...     u.pname
...
'小剛'
'小強'
'小明'

我們查到了蘇州健雄學校下的3個學生湖员,大家可以對照一下上表贫悄,是正確的。
第二種情況:我們要查小芳所在的學校娘摔。

>>> p = Students.objects.select_related('cid__sid').get(pname='小芳')
>>> p.cid.sid.sname
'蘇州大學'
或者用filter查詢窄坦,注意與get取值的差別,filter查詢結(jié)果是列表
>>> p = Students.objects.select_related('cid__sid').filter(pname='小芳')
>>> p[0].cid.sid.sname
'蘇州大學'

通過上述例子可以發(fā)現(xiàn)凳寺,

我們通過設(shè)置select_related的參數(shù)值即可實現(xiàn)三個或三個以上的多表查詢鸭津。上面例子中的參數(shù)值為‘cid__sid’,注意引號不能少肠缨。cid是模型Students的外鍵逆趋,指向模型Classes,sid是模型Classes的外鍵晒奕,指向模型School闻书。兩個外鍵之間通過雙下劃線連接且兩個字段都指向另一個模型。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末脑慧,一起剝皮案震驚了整個濱河市魄眉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌闷袒,老刑警劉巖杆融,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異霜运,居然都是意外死亡脾歇,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門淘捡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來藕各,“玉大人,你說我怎么就攤上這事焦除〖た觯” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵膘魄,是天一觀的道長乌逐。 經(jīng)常有香客問我,道長创葡,這世上最難降的妖魔是什么浙踢? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮灿渴,結(jié)果婚禮上洛波,老公的妹妹穿的比我還像新娘胰舆。我一直安慰自己,他們只是感情好蹬挤,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布缚窿。 她就那樣靜靜地躺著,像睡著了一般焰扳。 火紅的嫁衣襯著肌膚如雪倦零。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天吨悍,我揣著相機與錄音光绕,去河邊找鬼。 笑死畜份,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的欣尼。 我是一名探鬼主播爆雹,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼愕鼓!你這毒婦竟也來了钙态?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤菇晃,失蹤者是張志新(化名)和其女友劉穎册倒,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體磺送,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡驻子,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了估灿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片崇呵。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖馅袁,靈堂內(nèi)的尸體忽然破棺而出域慷,到底是詐尸還是另有隱情,我是刑警寧澤汗销,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布犹褒,位于F島的核電站,受9級特大地震影響弛针,放射性物質(zhì)發(fā)生泄漏叠骑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一削茁、第九天 我趴在偏房一處隱蔽的房頂上張望座云。 院中可真熱鬧疙赠,春花似錦、人聲如沸朦拖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽璧帝。三九已至捍岳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間睬隶,已是汗流浹背锣夹。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苏潜,地道東北人银萍。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像恤左,于是被迫代替她去往敵國和親贴唇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容