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)方法如下:
- 需要在項目的settings.py中設(shè)置數(shù)據(jù)庫信息泉沾,具體參考前面的章節(jié)。
- 構(gòu)建虛擬對象數(shù)據(jù)庫妇押,在App的models.py文件中以類的形式定義模型跷究。
- 通過模型在目標數(shù)據(jù)庫中創(chuàng)建相應的數(shù)據(jù)表。
- 在視圖函數(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)凳寺,