Django知识第五天

查询集

查询集表示从数据库中获取的对象集合,在管理器上调用某些过滤器方法会返回查询集,查询集可以含有零个、一个或多个过滤器。过滤器基于所给的参数限制查询的结果,从Sql的角度,查询集和select语句等价,过滤器像where和limit子句。

过滤器

返回查询集的过滤器如下:
# all():返回所有数据。
list = BookInfo.objects.all()
# filter():返回满足条件的数据。
list = BookInfo.objects.filter(id__gt=2)
# exclude():返回满足条件之外的数据,相当于sql语句中where部分的not关键字。
list = BookInfo.objects.exclude(id=1)
# order_by():对结果进行排序。
list = BookInfo.objects.all().order_by()
返回单个值的过滤器如下:
get():返回单个满足条件的对象
如果未找到会引发"模型类.DoesNotExist"异常。
如果多条被返回,会引发"模型类.MultipleObjectsReturned"异常。
count():返回当前查询结果的总条数。
aggregate():聚合,返回一个字典。

判断某一个查询集中是否有数据:
exists():判断查询集中是否有数据,如果有则返回True,没有则返回False。

两大特性

  • (1) 惰性执行:创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用。
  • (2) 缓存:使用同一个查询集,第一次使用时会发生数据库的查询,然后把结果缓存下来,再次使用这个查询集时会使用缓存的数据。

我们在应用查询集时有两种状态,下面是两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载。

from booktest.models import BookInfo
# 建立一个查询集,与数据库发生一次交互
[book.id for book in BookInfo.objects.all()]
# 再次新建一个查询集,再次与数据库发生交互
[book.id for book in BookInfo.objects.all()]

下面是经过存储后,可以重用查询集,第二次使用缓存中的数据。

# 创建一个查询集
list = BookInfo.objects.all()
# 执行查询集
[book.id for book in list]
# 复用以前的查询集,不会去数据库中在此执行,实际应用的是缓存内数据
[book.id for book in list]

限制查询集

可以对查询集进行取下标或切片操作,等同于sql中的limit和offset子句。

  • 注意:

1.不支持负数索引。
2.对查询集进行切片后返回一个新的查询集,不会立即执行查询。
3.如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发 IndexError异常,[0:1].get()如果没有数据引发does not exist异常。
如果获取一个对象,可以直接使用对象[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,[0:1].get()如果没有数据引发DoesNotExist异常。

>>> books = BookInfo.objects.filter(id__lte=3)
>>> books
[<BookInfo: BookInfo object>, <BookInfo: BookInfo object>, <BookInfo: BookInfo object>]
>>> books2 = books[:2]  # 切片会返回新的对象
>>> books2
[<BookInfo: BookInfo object>, <BookInfo: BookInfo object>]
>>> books3 = books[0:1]
>>> books3
[<BookInfo: BookInfo object>]
>>> books4 = books[0:0]
>>> books4
[]
>>> books4[0]
# 上面会引发IndexError异常。
>>> books4[0:0].get()
# 上面会引发DoesNotExist异常。
>>> books4.exists()
False
>>> books3.exists()
True

模型类关系

关系型数据库的关系包括三种类型:

  1. 一对多关系

ForeignKey:将字段定义在多的一端中。
例:图书类-英雄类

#定义图书模型类BookInfo
class BookInfo(models.Model):
    btitle = models.CharField(max_length=20)#书名
    bpub_date = models.DateField()#发布日期
    bread = models.IntegerField(default=0)#阅读量
    bcomment = models.IntegerField(default=0)#评论量
    isDelete = models.BooleanField(default=False)#逻辑删除

#定义英雄模型类HeroInfo
class HeroInfo(models.Model):
    hname = models.CharField(max_length=20)#姓名
    hgender = models.BooleanField(default=True)#性别
    isDelete = models.BooleanField(default=False)#逻辑删除
    hcomment = models.CharField(max_length=200)#描述信息
    hbook = models.ForeignKey('BookInfo')
    #英雄与图书表的关系为一对多,所以属性定义在英雄模型类中
  1. 多对多关系

ManyToManyField:将字段定义在任意一端中。
例:新闻类-新闻类型类 体育新闻 国际新闻

class TypeInfo(models.Model):
  tname = models.CharField(max_length=20) #新闻类别

class NewsInfo(models.Model):
  ntitle = models.CharField(max_length=60) #新闻标题
  ncontent = models.TextField() #新闻内容
  npub_date = models.DateTimeField(auto_now_add=True) #新闻发布时间
  ntype = models.ManyToManyField('TypeInfo') 
#通过ManyToManyField建立TypeInfo类和NewsInfo类之间多对多的关系
  1. 一对一关系

OneToOneField:将字段定义在任意一端中。
例:员工基本信息类-员工详细信息类. 员工工号

class EmployeeBasicInfo(models.Model):
    name = models.CharField(max_length=20)# 姓名
    gender = models.BooleanField(default=False)# 性别
    age = models.IntegerField()# 年龄
    employee_detail = models.OneToOneField('EmployeeDetailInfo')# 关系属性

# 员工详细信息类
class EmployeeDetailInfo(models.Model):

    addr = models.CharField(max_length=256) #地址

关联查询

一对多关联查询

  • 由一到多的访问语法:
    一对应的模型类对象.多对应的模型类名小写_set

例:查询id为1的图书关联的英雄信息

b = BookInfo.objects.get(id=1)
b.heroinfo_set.all()
  • 由多到一的访问语法:
    多对应的模型类对象.多对应的模型类中的关系类属性名

例:查询id为1的英雄 所属的 图书信息

h = HeroInfo.objects.get(id=1)
h.hbook

通过模型类执行关联查询

由多模型类条件查询一模型类数据:

语法如下:
关联模型类名小写属性名条件运算符=值

如果没有"__运算符"部分,表示等于,结果和sql中的inner join相同。

例:查询图书,要求图书中英雄的描述包含'八'。

BookInfo.objects.filter(heroinfo__hcontent__contains='八')

由一模型类条件查询多模型类数据: 语法如下:
一模型类关联属性名一模型类属性名条件运算符=值

例:查询书名为“天龙八部”的所有英雄。

HeroInfo.objects.filter(hbook__btitle='天龙八部')
例题
  1. 查询性别为男的英雄
heros = HeroInfo.objects.filter(hgender=True)
[hero.hname for hero in heros]
  1. 查询姓黄的男性英雄
from django.db.models import Q
heros = HeroInfo.objects.filter(Q(hname__contains='黄')&Q(hgender=True)
[hero.hname for hero in heros]
  1. 查询图书名为“天龙八部”的英雄
heros = HeroInfo.objects.filter(hbook__btitle='天龙八部')
[hero.hname for hero in heros]
  1. 查询编号小于5或性别为女的英雄
from django.db.models import Q
heros = HeroInfo.objects.filter(Q(id__lt=5)|Q(hgender=False))
[hero.name for hero in heros]
  1. 查询女生总人数
HeroInfo.objects.filter(hgender=False).count()

自关联

对于地区信息、分类信息等数据,表结构非常类似,每个表的数据量十分有限,为了充分利用数据表的大量数据存储功能,可以设计成一张表,内部的关系字段指向本表的主键,这就是自关联的表结构。

  • 关系属性使用self指向本类,要求null和blank允许为空,因为一级数据是没有父级的

打开booktest/models.py文件,定义AreaInfo类。

#定义地区模型类,存储省、市、区县信息
class AreaInfo(models.Model):
    atitle=models.CharField(max_length=30)#名称
    aParent=models.ForeignKey('self',null=True,blank=True)#关系

迁移。

python manage.py makemigrations
python manage.py migrate

打开mysql命令行,导入数据。打开booktest/views.py文件,定义视图area和它的下级地区。

def area(request):
    area = AreaInfo.objects.filter(aParent__isnull=True)
    return render(request,'area/index.html',{'area':area})

def larea(request,bid):
    areas = AreaInfo.objects.filter(aParent_id=int(bid))
    aname = AreaInfo.objects.get(id=int(bid))
    return render(request,'area/index2.html',{'areas':areas,'aname':aname})

打开booktest/urls.py文件,新建url。

urlpatterns = [
    url(r'^$',views.area ),
    url(r'^(\d+)$',views.larea)
]

在templates/booktest目录下,新建index.html文件和index2.html文件。
index.html

<html>
<head>
    <title>地区</title>
</head>
<body>
<ul>
    {%for a in area%}
    <li><a href="{{ a.id }}">{{a.atitle}}</a></li>
    {%endfor%}
</ul>
</body>
</html>

index2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<h1>上级地区:{{ aname.aParent.atitle }}</h1>
<br>
<hr>
<h2>当前地区:{{ aname.atitle }}</h2>
<br>
<hr>
<ul>
    {% for area in areas %}
        <li><a href="{{ area.id }}">{{ area.atitle }}</a> </li>
    {% endfor %}
</ul>
</body>
</html>


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容

  • 生成迁移文件:1.进入虚拟环境 或 创建虚拟环境 mkvirtualenv cc / workon cc2....
    恬恬i阿萌妹O_o阅读 448评论 0 0
  • 查询集(QuerySet) 查询集表示从数据库中获取的对象集合(类似列表可以遍历),在管理器上调用某些过滤器方法会...
    __method__阅读 332评论 0 2
  • 生成迁移文件:1.进入虚拟环境 或 创建虚拟环境 mkvirtualenv cc / workon cc2....
    恬恬i阿萌妹O_o阅读 540评论 0 0
  • MVT图解 项目准备 创建项目 创建应用 更换python解释器:按需选择 安装应用 本地化 模板路径在应用同级目...
    阿孝不会飞阅读 776评论 0 2
  • 高一班级,各种试卷,老成,老万,老王,老万训了老成,老成和老王在做题,我,气球尿,xuahiyu,xuchunxu...
    眼泪_阅读 198评论 0 0