Django 【第二十一篇】中介模型以及优化查询以及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模型中所需要的所有信息;而简单的addcreate 和赋值语句是做不到这一点的。所以它们不能在使用中介模型的多对多关系中使用。此时,唯一的办法就是创建中介模型的实例。

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");

  总结

  1. select_related主要针一对一和多对一关系进行优化。
  2. select_related使用SQL的JOIN语句进行优化,通过减少SQL查询的次数来进行优化、提高性能。
  3. 可以通过可变长参数指定需要select_related的字段名。也可以通过使用双下划线“__”连接字段名来实现指定的递归查询。
  4. 没有指定的字段不会缓存,没有指定的深度不会缓存,如果要访问的话Django会再次进行SQL查询。
  5. 也可以通过depth参数指定递归的深度,Django会自动缓存指定深度内所有的字段。如果要访问指定深度外的字段,Django会再次进行SQL查询。
  6. 也接受无参数的调用,Django会尽可能深的递归查询所有的字段。但注意有Django递归的限制和性能的浪费。
  7. 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具有多对多关联。

原文地址:https://www.cnblogs.com/xiaohema/p/8456602.html

时间: 2024-10-07 22:05:48

Django 【第二十一篇】中介模型以及优化查询以及CBV模式的相关文章

Python开发【第二十一篇】:Web框架之Django【基础】

Python开发[第二十一篇]:Web框架之Django[基础] 猛击这里:http://www.cnblogs.com/wupeiqi/articles/5237704.html Python之路[第十六篇]:Django[基础篇] Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. 基本配置 一.创建django程序 终端命令:django-a

第二十一篇 生命的全景

第二十一篇  生命的全景 生命对于我们来讲非常的熟悉,我们身边就有形形色色的生命,我们所生活的这个空间就是生命的空间.然而,就是我们习以为常的生命,却蕴含着极其广泛的意义和无穷的奥秘.就目前我们在宇宙中的能力而言,还无法做到站在生命空间之上的高度去总览全局,还无法对生命进行全面地概括与剖析. 如今,凭我们小宇宙家族现阶段的能力,还没有办法了解生命全部的奥秘,但是,随着我们对生命的不断探索,会有越来越多的生命奥秘被我们认知. 虽说我们对生命的了解还很有局限,但是我们目前的认知水平已经可以探知到:生

第二十一篇:基?于?W?D?M?模?型?的?A?V?S?t?r?e?a?m?驱?动?架?构?研?究

基?于?W?D?M?模?型?的?A?V?S?t?r?e?a?m?驱?动?架?构?研? 这篇论文2006年早就发表, 与当时开发这个驱动正好差不多的时间. 最近实际项目需要, 又回过头来将AVStream中的主要框架列举一下. 整个框架由: KSDevice KSFilter KSPin所构成 KSDevice负责了PNP相关的DISPATCH, 如START, STOP, ADD, REMOVE KSFilter构成软件AVSTREAM设备的DISPATCH, 这就是所谓的FILTER CENT

Python之路【第二十一篇】Django ORM详解

ORM回顾 关系对象映射(Object Relational Mapping,简称ORM). django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表. 对于ORM框架里: 我们写的类表示数据库的表 如果根据这个类创建的对象是数据库表里的一行数据 对象.id 对象.value 是每一行里的数据 http://www.cnblogs.com/luotianshuai/p/5301343.html 梳理 首先在理解ORM的时候,我们可以把一对多.多对多 分为正向和反

Django框架 之 ORM中介模型

中介模型 处理类似搭配 pizza 和 topping 这样简单的多对多关系时,使用标准的ManyToManyField  就可以了.但是,有时你可能需要关联数据到两个模型之间的关系上. 例如,有这样一个应用,它记录音乐家所属的音乐小组.我们可以用一个ManyToManyField 表示小组和成员之间的多对多关系.但是,有时你可能想知道更多成员关系的细节,比如成员是何时加入小组的. 对于这些情况,Django 允许你指定一个中介模型来定义多对多关系. 你可以将其他字段放在中介模型里面.源模型的M

Python之路【第二十一篇】:Django之Form组件

Django之Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1.创建Form类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from django.forms import Form from django.forms import widgets from django.forms imp

python全栈开发基础【第二十一篇】互斥锁以及进程之间的三种通信方式(IPC)以及生产者个消费者模型

一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行的修改,没错,速度是慢了,牺牲了速度而保证了数据安全. 1.上厕所的小例子:你上厕所的时候肯定得锁门吧,有人来了看见门锁着,就会在外面等着,等你吧门开开出来的时候,下一个人才去上厕所. from multiprocessing import Process,Lock import os import

第二十一篇 Java 数据类型的定义 ,以及基础类型的自动转换和强制转换

大家好,今天呢我吧我所学到的一些知识点共享给大家,希望大家看完之后,要是有什么不懂的,请随时联系我,要是觉得我写的不是很好的 ,还希望你们能够谅解一下,因为小弟我刚学会写博客也没多久,很多格式和方法都不是很完善,希望大家多多包涵,好了 废话就不多说了,来谈一下今天我所学到的一些知识点吧: 今天我主要是学到了一些Java中的数据类型,其中,Java中的数据类型分为俩类------基础数据类和逻辑数据类,下面我所介绍的都是基本数据类的一些分类,至于逻辑类,由于使用次数过少,所以今天就不再这里多做介绍

Django进阶Model篇002 - 模型类的定义

一.创建数据模型. 实例: 作者模型:一个作者有姓名. 作者详情模型:把作者的详情放到详情表,包含性别.email 地址和出生日期,作者详情模型与作者模型之间是一对一的关系(OneToOneField) 出版商模型:出版商有名称,地址,所在城市,省,国家,网址. 书籍模型:书籍有书名,出版日期,价格.一本书可能会有多个作者,一个作者也可以写多本书,所以作者与书籍的关系是多对多的关联关系(many-to-many),一本书只应该由一个出版商出版,所以出版商和书籍是一对多的关联关系(one-to-m