中介模型,cbv视图,和查询优化
中介模型:
处理类似搭配 pizza 和 topping 这样简单的多对多关系时,使用标准的ManyToManyField 就可以了。但是,有时你可能需要关联数据到两个模型之间的关系上。
例如,有这样一个应用,它记录音乐家所属的音乐小组。我们可以用一个ManyToManyField 表示小组和成员之间的多对多关系。但是,有时你可能想知道更多成员关系的细节,比如成员是何时加入小组的。
对于这些情况,Django 允许你指定一个中介模型来定义多对多关系。 你可以将其他字段放在中介模型里面。源模型的ManyToManyField 字段将使用through 参数指向中介模型。对于上面的音乐小组的例子,代码如下:
from
django.db
import
models
class
Person(models.Model):
name
=
models.CharField(max_length
=
128
)
def
__str__(
self
):
# __unicode__ on Python 2
return
self
.name
class
Group(models.Model):
name
=
models.CharField(max_length
=
128
)
members
=
models.ManyToManyField(Person, through
=
'Membership'
)
def
__str__(
self
):
# __unicode__ on Python 2
return
self
.name
class
Membership(models.Model):
person
=
models.ForeignKey(Person)
group
=
models.ForeignKey(Group)
date_joined
=
models.DateField()
invite_reason
=
models.CharField(max_length
=
64
)
>>> ringo
=
Person.objects.create(name
=
"Ringo Starr"
)
>>> paul
=
Person.objects.create(name
=
"Paul McCartney"
)
>>> beatles
=
Group.objects.create(name
=
"The Beatles"
)
>>> m1
=
Membership(person
=
ringo, group
=
beatles,
... date_joined
=
date(
1962
,
8
,
16
),
... invite_reason
=
"Needed a new drummer."
)
>>> m1.save()
>>> beatles.members.
all
()
[<Person: Ringo Starr>]
>>> ringo.group_set.
all
()
[<Group: The Beatles>]
>>> m2
=
Membership.objects.create(person
=
paul, group
=
beatles,
... date_joined
=
date(
1960
,
8
,
1
),
... invite_reason
=
"Wanted to form a band."
)
>>> beatles.members.
all
()
[<Person: Ringo Starr>, <Person: Paul McCartney>]
# THIS WILL NOT WORK
>>> beatles.members.add(john)
# NEITHER WILL THIS
>>> beatles.members.create(name
=
"George Harrison"
)
# AND NEITHER WILL THIS
>>> beatles.members
=
[john, paul, ringo, george]
为什么不能这样做? 这是因为你不能只创建 Person和 Group之间的关联关系,你还要指定 Membership模型中所需要的所有信息;而简单的add、create 和赋值语句是做不到这一点的。所以它们不能在使用中介模型的多对多关系中使用。此时,唯一的办法就是创建中介模型的实例。
remove()方法被禁用也是出于同样的原因。但是clear() 方法却是可用的。它可以清空某个实例所有的多对多关系:
>>>
# Beatles have broken up
>>> beatles.members.clear()
>>>
# Note that this deletes the intermediate model instances
>>> Membership.objects.
all
()
[]
def addArticle(request): if request.method=="POST":
article_form = ArticleForm(request.POST)
if article_form.is_valid():
title=article_form.cleaned_data.get("title")
content=article_form.cleaned_data.get("content") personal_cate=request.POST.get("personal_cate")
personal_tag=request.POST.getlist("personal_tag") article_obj=models.Article.objects.create(title=title,desc=content[0:30],create_time=datetime.datetime.now(),user=request.user,category_id=personal_cate)
models.ArticleDetail.objects.create(content=content,article=article_obj) if personal_tag: # [2,3]
for i in personal_tag:
models.Article2Tag.objects.create(article_id=article_obj.nid,tag_id=i)#在第三张表中自动添加关系 else:
pass return HttpResponse("添加成功") article_form=ArticleForm()
cate_list=models.Category.objects.filter(blog__user=request.user)
tag_list=models.Tag.objects.filter(blog__user=request.user)
return render(request,"addArticle.html",{"article_form":article_form,"cate_list":cate_list,"tag_list":tag_list})
惰性查询
查询集 是惰性执行的 —— 创建查询集不会带来任何数据库的访问。你可以将过滤器保持一整天,直到查询集 需要求值时,Django 才会真正运行这个查询。
ret=models.Article.objects.all()
这个就不会进入数据库查询
print(ret) 就会对数据库进行查询
一般来说,只有在“请求”查询集 的结果时才会到数据库中去获取它们。当你确实需要结果时,查询集 通过访问数据库来求值。 缓存机制:
每个查询集都包含一个缓存来最小化对数据库的访问。理解它是如何工作的将让你编写最高效的代码。
在一个新创建的查询集中,缓存为空。首次对查询集进行求值 —— 同时发生数据库查询 ——Django 将保存查询的结果到查询集的缓存中并返回明确请求的结果(例如,如果正在迭代查询集,则返回下一个结果)。接下来对该查询集 的求值将重用缓存的结果。
请牢记这个缓存行为,因为对查询集使用不当的话,它会坑你的。例如,下面的语句创建两个查询集,对它们求值,然后扔掉它们:
print([a.title
for
a
in
models.Article.objects.
all
()])
print([a.create_time
for
a
in
models.Article.objects.
all
()])
queryResult=models.Article.objects.
all
()
print([a.title
for
a
in
queryResult])
print([a.create_time
for
a
in
queryResult])
查询集不会永远缓存它们的结果。当只对查询集的部分进行求值时会检查缓存, 如果这个部分不在缓存中,那么接下来查询返回的记录都将不会被缓存。所以,这意味着使用切片或索引来限制查询集将不会填充缓存。
例如,重复获取查询集对象中一个特定的索引将每次都查询数据库:
>>> queryset
=
Entry.objects.
all
()
>>>
print
queryset[
5
]
# Queries the database
>>>
print
queryset[
5
]
# Queries the database again
>>> queryset
=
Entry.objects.
all
()
>>> [entry
for
entry
in
queryset]
# Queries the database
>>>
print
queryset[
5
]
# Uses cache
>>>
print
queryset[
5
]
# Uses cache
>>> [entry
for
entry
in
queryset]
>>>
bool
(queryset)
>>> entry
in
queryset
>>>
list
(queryset)
queryResult
=
models.Article.objects.
all
()
print
(queryResult)
# hits database
print
(queryResult)
# hits database
exists:
简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些 数据!为了避免这个,可以用exists()方法来检查是否有数据:
if queryResult.exists():
#SELECT (1) AS "a" FROM "blog_article" LIMIT 1; args=()
print("exists...")
iterator:
当queryset非常巨大时,cache会成为问题。
处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统 进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法 来获取数据,处理完数据就将其丢弃。
objs = Book.objects.all().iterator()
# iterator()可以一次只从数据库获取少量数据,这样可以节省内存
for obj in objs:
print(obj.title)
#BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
for obj in objs:
print(obj.title)
当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使用#iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询
总结:
queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。 使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能 会造成额外的数据库查询。
查询优化
对于一对一字段(OneToOneField)和外键字段(ForeignKey),可以使用select_related 来对QuerySet进行优化。
select_related 返回一个QuerySet,当执行它的查询时它沿着外键关系查询关联的对象的数据。它会生成一个复杂的查询并引起性能的损耗,但是在以后使用外键关系时将不需要数据库查询。
简单说,在对QuerySet使用select_related()函数后,Django会获取相应外键对应的对象,从而在之后需要的时候不必再查询数据库了。
obj_list=models.Article.objects.select_related("user").select_related("category").all()
print(obj_list)
for i in obj_list:
print(i.category)
for i in obj_list:
print(i.title)
cbv视图:
通过类来对应url 通过类里面的方法来对应
views代码:
from django.views import View class Login(View): def get(self,request): return render(request,"login_cbv.html") def post(self,request):
return HttpResponse("post.........") def delete(self):
pass
中介模型,cbv视图,和查询优化的更多相关文章
- 中介模型以及优化查询以及CBV模式
一.中介模型:多对多添加的时候用到中介模型 自己创建的第三张表就属于是中介模型 class Article(models.Model): ''' 文章表 ''' title = models.Char ...
- django中介模型,CBV模型,及logging日志配制
1.中介模型 中介模型,这个是在我们创建表格时,多对多添加的时候应用到的,通过制定ManyToManyField字段中的through参数来定义,为两者的关系新建一个中介class 为什么会产生这个中 ...
- Django【第26篇】:中介模型以及优化查询以及CBV模式
中介模型以及优化查询以及CBV模式 一.中介模型:多对多添加的时候用到中介模型 自己创建的第三张表就属于是中介模型 class Article(models.Model): ''' 文章表 ''' t ...
- Django-model进阶(中介模型,查询优化,extra,整体插入)
QuerySet 可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句. ? 1 >>> Entry.objects.al ...
- model进阶(queryset,中介模型,查询优化,extra)
queryset 方法 ############# 可切片 def queryTest(request): ret = models.Atricle.objects.all() 数据库查询 print ...
- 第十四篇Django-model进阶(中介模型,查询优化,extra,整体插入)
Django-model进阶(中介模型,查询优化,extra,整体插入) 阅读目录(Content) 中介模型 查询优化 extra 整体插入 中介模型 处理类似搭配 pizza 和 topping ...
- Django QuerySet和中介模型
笔记如下 一.QuerySet QuerySet是什么? 类似列表里边存着对象 只和ORM有关系 from app01.models import Book def qDemo(request): b ...
- Django中的CBV视图
Web 开发是一项无聊而且单调的工作,特别是在视图功能编写方面更为显著.为了减少这种痛苦,Django植入了视图类这一功能,该功能封装了视图开发常用的代码,无须编写大量代码即可快速完成数据视图的开发, ...
- [.net 面向对象程序设计深入](6).NET MVC 6 —— 模型、视图、控制器、路由等的基本操作
[.net 面向对象程序设计深入](6).NET MVC 6 —— 模型.视图.控制器.路由等的基本操作 1. 使用Visual Studio 2015创建Web App (1)文件>新建> ...
随机推荐
- mysql真的不能做搜索引擎吗?
大家都对电商的商品查询并不陌生,比如我们想根据商品名称查询所有商品信息. 有些技术的童鞋第一念头是搜索引擎:有些技术的童鞋第一念头是模糊查询,如like?(如果商品信息存放到mysql里,我们一般使用 ...
- .Net Core缓存组件(MemoryCache)源码解析
一.介绍 由于CPU从内存中读取数据的速度比从磁盘读取快几个数量级,并且存在内存中,减小了数据库访问的压力,所以缓存几乎每个项目都会用到.一般常用的有MemoryCache.Redis.MemoryC ...
- Python和Java编程题(二)
题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 兔子的规律为数列1,1,2,3,5,8,13,21 ...
- C++多重继承的构造执行顺序
一个类,它可能有基类,也可能存在多个基类,这些类里面还可能是虚拟基类,并且在类的本身也可能存在对象成员.那么所涉及的这些类或对象成员会以什么样的顺序来调用它们各自的构造函数呢?今天我们就来举例分析下. ...
- 初始mvc4(一) 新建项目
mvc4和mvc4.5基本大同小异,vs2012中已经集成了mvc,不需要手动安装了,现在就来看看如何新建mvc项目 一.首先打开vs2012,新建项目,选中web中mvc4 二.选择项目模板 这里面 ...
- AngularJS初始化Select选择框
一.引入 之前一个离职的同事负责的项目大量的引入了AngularJS的JS框架,后来我接手相关他项目里的功能.由于对AngularJS不是太熟,在他的功能上进行二次开发就比较费劲了,印象比较深的一个就 ...
- [PHP]算法-归并排序的PHP实现
<?php //归并排序 function merge(&$A,$left,$mid,$right,$temp){ //7.左堆起始 $i=$left; //8.右堆起始 $j=$mid ...
- 【Java】HashMap源码分析——常用方法详解
上一篇介绍了HashMap的基本概念,这一篇着重介绍HasHMap中的一些常用方法:put()get()**resize()** 首先介绍resize()这个方法,在我看来这是HashMap中一个非常 ...
- 【Spring】26、利用Spring的AbstractRoutingDataSource解决多数据源,读写分离问题
多数据源问题很常见,例如读写分离数据库配置. 1.首先配置多个datasource <bean id="dataSource" class="org.apache. ...
- 设计模式之策略模式(Strategy)
策略模式将不同算法的逻辑抽象接口封装到一个类中,通过组合和多态结合的方式来进行不同算法具体的实现. 作用 策略模式是一种定义一系列算法的方法,Strategy类层次为Context定义了一系列的可重用 ...