中介模型以及优化查询以及CBV模式
一、中介模型:多对多添加的时候用到中介模型
自己创建的第三张表就属于是中介模型
class Article(models.Model):
'''
文章表
'''
title = models.CharField(max_length=64,verbose_name="文章标题")
summary = models.CharField(max_length=244, verbose_name="文章概要")
create_time = models.DateTimeField(verbose_name="创建时间",auto_now_add=True)
update_time = models.DateTimeField(verbose_name="修改时间",auto_now=True)
up_count = models.IntegerField(verbose_name="点赞数",default=0)
down_count = models.IntegerField(verbose_name="点灭数",default=0)
comment_count = models.IntegerField(verbose_name="评论数",default=0)
read_count = models.IntegerField(verbose_name="阅读数",default=0) user = models.ForeignKey(to="UserInfo",verbose_name="所属作者",null=True,blank=True)
classify = models.ForeignKey(to="Classfication",verbose_name="所属类别",null=True,blank=True)
tags = models.ManyToManyField(to="Tag",through="Article2tag",through_fields=('article', 'tag'),verbose_name="所属标签")
site_article_category = models.ForeignKey(to="SiteArticleCategory",verbose_name="所属文章分类",null=True,blank=True)
class Meta:
verbose_name_plural = "文章表"
def __str__(self):
return self.title class Tag(models.Model):
'''标签表'''
name = models.CharField(max_length=32,verbose_name="标签名")
blog = models.ForeignKey(to="Blog",verbose_name="所属博客")
class Meta:
verbose_name_plural = "标签表" def __str__(self):
return self.name class Article2tag(models.Model):
article = models.ForeignKey(verbose_name="文章",to="Article")
tag = models.ForeignKey(verbose_name="标签",to="Tag")
class Meta:
verbose_name="文章和标签关系表"
'''联合唯一'''
unique_together = [
("article","tag")
]
def __str__(self):
return self.article.title + " "+self.tag.name 像是这样自己创建的第三张表就属于是中介模型。一般就Django会给我们自动创建第三张表,
人家自己创建的只是有关系字段,不能在增加其他的字段了,
如果根据需求添加其他字段,不需要ManytoMany自己创建第三张表就自己设置第三张表
这就需要我们自己去创建第三张表。
当然我现在设计的Article2tag这个第三张表就可以在里面添加其他你需要的字段。
如果用了中介模型了,就不能在用add,remove了
为什么不能这样做? 这是因为你不能只创建 article和 tag之间的关联关系,你还要指定 Membership模型中所需要的所有信息;而简单的add、create 和赋值语句是做不到这一点的。所以它们不能在使用中介模型的多对多关系中使用。此时,唯一的办法就是创建中介模型的实例。
remove()方法被禁用也是出于同样的原因。但是clear() 方法却是可用的。它可以清空某个实例所有的多对多关系:
cate = request.POST.get("cate")
tag = request.POST.getlist("tag")
article_obj = models.Article.objects.create(title=title,summary=content[0:30],create_time=datetime.datetime.now(),user=request.user,classify_id = cate)
models.Article_detail.objects.create(content=content,article=article_obj)
if tag:
for i in tag: #[2,4]
models.Article2tag.objects.create(tag_id=i,article_id=article_obj.id) #直接从关系表里面去查
remove()方法被禁用也是出于同样的原因。但是clear() 方法却是可用的。它可以清空某个实例所有的多对多关系:
二、优化查询
简单使用
对于一对一字段(OneToOneField)和外键字段(ForeignKey),可以使用select_related 来对QuerySet进行优化。
select_related 返回一个QuerySet,当执行它的查询时它沿着外键关系查询关联的对象的数据。它会生成一个复杂的查询并引起性能的损耗,但是在以后使用外键关系时将不需要数据库查询。
简单说,在对QuerySet使用select_related()函数后,Django会获取相应外键对应的对象,从而在之后需要的时候不必再查询数据库了。
下面的例子解释了普通查询和select_related() 查询的区别。
查询id=2的文章的分类名称,下面是一个标准的查询:
obj = models.Article.objects.get(id=2)
print(obj.classify.title) #走两次数据库,基于对象的属于子查询,基于双下划线的属于连表查询
sql是这样的
''' SELECT
"blog_article"."nid",
"blog_article"."title",
"blog_article"."desc",
"blog_article"."read_count",
"blog_article"."comment_count",
"blog_article"."up_count",
"blog_article"."down_count",
"blog_article"."category_id",
"blog_article"."create_time",
"blog_article"."blog_id",
"blog_article"."article_type_id"
FROM "blog_article"
WHERE "blog_article"."nid" = 2; args=(2,) SELECT
"blog_category"."nid",
"blog_category"."title",
"blog_category"."blog_id"
FROM "blog_category"
WHERE "blog_category"."nid" = 4; args=(4,) '''
如果我们使用select_related()函数:
articleList=models.Article.objects.select_related("category").all()
for article_obj in articleList:
# Doesn't hit the database, because article_obj.category
# has been prepopulated in the previous query.
print(article_obj.category.title)
#查询所有书的分类标题
obj_list=models.Article.objects.select_related("user").select_related("classify").all()
for obj in obj_list:
print(obj,"2222222",type(obj))
print(obj.classify.title) # obj_list = models.Article.objects.select_related("user","classify").all()
# for obj in obj_list:
# print(obj.classify.title)
# 要看需求查的数据多不多,如果一次的话就没有必要了
SELECT
"blog_article"."nid",
"blog_article"."title",
"blog_article"."desc",
"blog_article"."read_count",
"blog_article"."comment_count",
"blog_article"."up_count",
"blog_article"."down_count",
"blog_article"."category_id",
"blog_article"."create_time",
"blog_article"."blog_id",
"blog_article"."article_type_id", "blog_category"."nid",
"blog_category"."title",
"blog_category"."blog_id" FROM "blog_article"
LEFT OUTER JOIN "blog_category" ON ("blog_article"."category_id" = "blog_category"."nid");
总结
- select_related主要针一对一和多对一关系进行优化。
- select_related使用SQL的JOIN语句进行优化,通过减少SQL查询的次数来进行优化、提高性能。
- 可以通过可变长参数指定需要select_related的字段名。也可以通过使用双下划线“__”连接字段名来实现指定的递归查询。
- 没有指定的字段不会缓存,没有指定的深度不会缓存,如果要访问的话Django会再次进行SQL查询。
- 也可以通过depth参数指定递归的深度,Django会自动缓存指定深度内所有的字段。如果要访问指定深度外的字段,Django会再次进行SQL查询。
- 也接受无参数的调用,Django会尽可能深的递归查询所有的字段。但注意有Django递归的限制和性能的浪费。
- Django >= 1.7,链式调用的select_related相当于使用可变长参数。Django < 1.7,链式调用会导致前边的select_related失效,只保留最后一个。
三、CBV模式
就是把之前的函数视图用类实现了
简单测试一下:
urls.py
#CBV模式
url(r'^login_cbv/$', views.Login_cbv.as_view()),
注意:这里的Login_cbv是类名,它必须后面调用as_view()
views.py
from django.views import View
class Login_cbv(View):
def get(self,request): #如果是get请求需要执行的代码
return render(request,"login_cbv.html")
def post(self,request): #如果是post请求需要执行的代码
return HttpResponse(".....")
def delete(self,request):
pass
login_cbv.html
<form action="/login_cbv/" method="post">
{% csrf_token %}
姓名:<input type="text">
<input type="submit">
</form>
对于form表单只支持post和get请求,对于ajax请求支持8种,
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
四、整体插入
创建对象时,尽可能使用bulk_create()来减少SQL查询的数量。例如:
Entry.objects.bulk_create([
Entry(headline="Python 3.0 Released"),
Entry(headline="Python 3.1 Planned")
])
...更优于:
Entry.objects.create(headline="Python 3.0 Released")
Entry.objects.create(headline="Python 3.1 Planned")
注意该方法有很多注意事项,所以确保它适用于你的情况。
这也可以用在ManyToManyFields中,所以:
my_band.members.add(me, my_friend)
...更优于:
my_band.members.add(me)
my_band.members.add(my_friend)
...其中Bands和Artists具有多对多关联。
中介模型以及优化查询以及CBV模式的更多相关文章
- Django【第26篇】:中介模型以及优化查询以及CBV模式
中介模型以及优化查询以及CBV模式 一.中介模型:多对多添加的时候用到中介模型 自己创建的第三张表就属于是中介模型 class Article(models.Model): ''' 文章表 ''' t ...
- 中介模型,cbv视图,和查询优化
中介模型: 处理类似搭配 pizza 和 topping 这样简单的多对多关系时,使用标准的ManyToManyField 就可以了.但是,有时你可能需要关联数据到两个模型之间的关系上. 例如,有这 ...
- django中介模型,CBV模型,及logging日志配制
1.中介模型 中介模型,这个是在我们创建表格时,多对多添加的时候应用到的,通过制定ManyToManyField字段中的through参数来定义,为两者的关系新建一个中介class 为什么会产生这个中 ...
- 查询职责分离(CQRS)模式
查询职责分离(CQRS)模式 在常用的三层架构中,通常都是通过数据访问层来修改或者查询数据,一般修改和查询使用的是相同的实体.在一些业务逻辑简单的系统中可能没有什么问题,但是随着系统逻辑变得复杂,用户 ...
- Django进阶之QuerySet和中介模型
QuerySet QuerySet是查询集,就是传到服务器上的url里面的查询内容.其形态类似于Python的列表,列表中的元素是QuerySet对象.支持大部分列表的内置方法. 可切片 QueryS ...
- Django QuerySet和中介模型
笔记如下 一.QuerySet QuerySet是什么? 类似列表里边存着对象 只和ORM有关系 from app01.models import Book def qDemo(request): b ...
- 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 ...
- 危险!水很深,让叔来 —— 谈谈命令查询权责分离模式(CQRS)
多年以前,那时我正年轻,做技术如鱼得水,甚至一度希望自己能当一辈子的一线程序员. 但是我又有两个小愿望想要达成:一个是想多挣点钱:另一个就是对项目的技术栈和架构选型能多有点主动权. 多挣点钱是因为当时 ...
随机推荐
- 解决Nginx出现403 forbidden
在之前我修改了nginx.conf,所以/home/ftpuser/www文件夹下应该有index.html或index.htm文件 将index.html或index.htm文件复制到/home/f ...
- [转] Understanding Convolutional Neural Networks for NLP
http://www.wildml.com/2015/11/understanding-convolutional-neural-networks-for-nlp/ 讲CNN以及其在NLP的应用,非常 ...
- (转载)ECCV 2018:IBN-Net:打开域适应的新方式
(本文转自极视角) 本文由香港中文大学发表于ECCV2018,论文探索了IN和BN的优劣,据此提出的IBN-Net在语义分割的域适应任务上取得了十分显著的性能提升. 论文地址:https://arxi ...
- HDFS-put: unexpected URISyntaxException
目的:将某zip上传到HDFS某目录 [hdfs@mr1 jars]$ hadoop fs -put "20180720_155245 label.zip" /user/File/ ...
- 判断HDFS文件是否存在
hadoop判断文件是否存在 在shell中判断一个HDFS目录/文件是否存在 直接看shell代码: hadoop fs -test -e /hdfs_dirif [ $? -ne 0 ]; the ...
- 负载均衡集群中的session解决方案【转】
通常面临的问题 从用户端来解释,就是当一个用户第一次访问被负载均衡代理到后端服务器A并登录后,服务器A上保留了用户的登录信息:当用户再次发送请求时, 根据负载均衡策略可能被代理到后端不同的服务器,例如 ...
- python用类装饰函数的一个有趣实现
class RunningLog: def __init__(self,func): self._func=func self._func_name = func.__name__ def __cal ...
- 在Ubuntu 16.04下安装nodejs
源安装: 1.curl -sL https://deb.nodesource.com/setup_5.x | sudo -E bash - 2.sudo apt-get install -y node ...
- git与eclipse集成之更新特性分支代码到个人特性分支
1.1. 更新特性分支代码到个人特性分支 在基于特性分支开发的过程中,存在多人向特性分支提交代码的情况,开发者需要关注特性分支代码与个人分支代码保持同步,否则可能导致提交代码冲突. 具体代码同步步骤: ...
- Mysql支持哪几种索引
从数据结构角度 1.B+树索引(O(log(n))):关于B+树索引,可以参考 MySQL索引背后的数据结构及算法原理 2.hash索引:a 仅仅能满足"=","IN&q ...