微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Django 数据库与ORM

一、数据库的配置

1 django支持sqlite,MysqL,oracle,postgresql数据库

     <1> sqlite

            django认使用sqlite的数据库自带sqlite的数据库驱动 。

    引擎名称:django.db.backends.sqlite3

     <2> MysqL

            引擎名称:django.db.backends.MysqL

2 MysqL驱动程序

3 在django的项目中会认使用sqlite数据库,在settings里有如下设置:

  

如果我们想要更改数据库,需要修改如下:

   

display: none;" onclick="cnblogs_code_hide('3f37ba91-17b6-4dd8-b532-af1eedad095c',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
DATABASES =</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;default</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;: { </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;ENGINE</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.db.backends.<a href="/tag/MysqL/" target="_blank" class="keywords">MysqL</a></span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;NAME</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;books</span><span style="color: #800000;"&gt;'</span>,<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;你的<a href="/tag/shujuku/" target="_blank" class="keywords">数据库</a><a href="/tag/mingcheng/" target="_blank" class="keywords">名称</a></span> <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;USER</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;root</span><span style="color: #800000;"&gt;'</span>,<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;你的<a href="/tag/shujuku/" target="_blank" class="keywords">数据库</a><a href="/tag/yonghuming/" target="_blank" class="keywords">用户名</a></span> <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;PASSWORD</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;''</span>,<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;你的<a href="/tag/shujuku/" target="_blank" class="keywords">数据库</a><a href="/tag/mimap/" target="_blank" class="keywords">密码</a></span> <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;HOST</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;''</span>,<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;你的<a href="/tag/shujuku/" target="_blank" class="keywords">数据库</a>主机,留空<a href="/tag/mo/" target="_blank" class="keywords">默</a>认为localhost</span> <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;PORT</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;3306</span><span style="color: #800000;"&gt;'</span>,<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;你的<a href="/tag/shujuku/" target="_blank" class="keywords">数据库</a>端口</span>

<span style="color: #000000;">
}

}

注意:

数据库的名字,在MysqL连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建

USER和PASSWORD分别是数据库用户名密码

设置完后,再启动我们的Django项目前,我们需要激活我们的MysqL

然后,启动项目,会报错:no module named MysqLdb

这是因为django认你导入的驱动是MysqLdb,可是MysqLdb对于py3有很大问题,所以我们需要的驱动是PyMysqL

所以,我们只需要找到项目名文件下的init,在里面写入:

<span style="color: #0000ff;">import<span style="color: #000000;"> pyMysqL
pyMysqL.installasMysqLdb()

问题解决

二、ORM表模型

表(模型)的创建:

实例:我们来假定下面这些概念,字段和关系

作者模型:一个作者有姓名。

作者详细模型:把作者的详情放到详情表,包含性别,email地址和出生日期,作者详情模型和作者模型之间是一对一的关系(one-to-one)(类似于每个人和他的身份证之间的关系),在大多数情况下我们没有必要将他们拆分成两张表,这里只是引出一对一的概念。

出版商模型:出版商有名称,地址,所在城市,省,国家和网站。

书籍模型:书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many),一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many),也被称作外键。

display: none;" onclick="cnblogs_code_hide('10f60c93-a647-4761-a8c2-85b48b0e6737',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
django.db models
= models.CharField(max_length=30,verbose_name=名称= models.CharField(,max_length=50= models.CharField(,max_length=60= models.CharField(max_length=30= models.CharField(max_length=50=</span><span style="color: #0000ff;"&gt;class</span><span style="color: #000000;"&gt; <a href="/tag/Meta/" target="_blank" class="keywords">Meta</a>: verbose_name </span>= <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;出版商</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt; verbose_name_plural </span>=<span style="color: #000000;"&gt; verbose_name </span><span style="color: #0000ff;"&gt;def</span> <span style="color: #800080;"&gt;__str__</span><span style="color: #000000;"&gt;(self): </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; self.name

<span style="color: #0000ff;">class<span style="color: #000000;"> Author(models.Model):
name = models.CharField(max_length=30<span style="color: #000000;">)
<span style="color: #0000ff;">def <span style="color: #800080;">str<span style="color: #000000;">(self):
<span style="color: #0000ff;">return<span style="color: #000000;"> self.name

<span style="color: #0000ff;">class<span style="color: #000000;"> AuthorDetail(models.Model):
sex = models.BooleanField(max_length=1,choices=((0,<span style="color: #800000;">'<span style="color: #800000;">男<span style="color: #800000;">'),(1,<span style="color: #800000;">'<span style="color: #800000;">女<span style="color: #800000;">'<span style="color: #000000;">),))
email =<span style="color: #000000;"> models.EmailField()
address = models.CharField(max_length=50<span style="color: #000000;">)
birthday =<span style="color: #000000;"> models.DateField()
author =<span style="color: #000000;"> models.OnetoOneField(Author)

<span style="color: #0000ff;">class<span style="color: #000000;"> Book(models.Model):
title = models.CharField(max_length=100<span style="color: #000000;">)
authors =<span style="color: #000000;"> models.ManyToManyField(Author)
publisher =<span style="color: #000000;"> models.ForeignKey(Publisher)
publication_date =<span style="color: #000000;"> models.DateField()
price=models.DecimalField(max_digits=5,decimal_places=2,default=10<span style="color: #000000;">)
<span style="color: #0000ff;">def <span style="color: #800080;">str<span style="color: #000000;">(self):
<span style="color: #0000ff;">return self.title

分析代码

       <1>  每个数据模型都是django.db.models.Model的子类,它的父类Model包含了所有必要的和数据库交互的方法。并提供了一个简介漂亮的定义数据库字段的语法。

       <2>  每个模型相当于单个数据库表(多对多关系例外,会多生成一张关系表),每个属性也是这个表中的字段。属性名就是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)。大家可以留意下其它的类型都和数据库里的什么字段对应。

       <3>  模型之间的三种关系:一对一,一对多,多对多。

             一对一:实质就是在主外键(author_id就是foreign key)的关系基础上,给外键加了一个UNIQUE=True的属性

             一对多:就是主外键关系;(foreign key)

             多对多:(ManyToManyField) 自动创建第三张表(当然我们也可以自己创建第三张表:两个foreign key)

1、ORM之增(create,save)

app01.models *
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;create方式一:   Author.objects.create(name='Alvin')</span>

<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;create方式二:   Author.objects.create(**{"name":"alex"})</span>

<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;save方式一:     author=Author(name="alvin")</span>

<span style="color: #000000;"> author.save()

</span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;save方式二:     author=Author()</span>
                        author.name=<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;alvin</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
                        author.save()</span></pre>

重点来了------->那么如何创建存在一对多或多对多关系的一本书的信息呢?(如何处理外键关系的字段如一对多的和多对多的authors)

display: none;" onclick="cnblogs_code_hide('d19d0832-d0c1-4fec-b68b-b08b65dcfa64',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;方式一: 由于绑定一对多的字段,比如publish,存到<a href="/tag/shujuku/" target="_blank" class="keywords">数据库</a>中的字段名叫publish_id,所以我们可以直接给这个</span>
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;       字段设定对应值:</span>
       Book.objects.create(title=<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;<a href="/tag/PHP/" target="_blank" class="keywords">PHP</a></span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,publisher_id</span>=2,<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;这里的2是指为该book对象绑定了Publisher表中id=2的行对象</span>
                           publication_date=<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;2017-7-7</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,price</span>=99<span style="color: #000000;"&gt;)


</span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;方式二:</span>
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;       <1> 先<a href="/tag/huoqu/" target="_blank" class="keywords">获取</a>要绑定的Publisher对象:</span>
    pub_obj=Publisher(name=<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;河大出版社</span><span style="color: #800000;"&gt;'</span>,address=<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;保定</span><span style="color: #800000;"&gt;'</span>,city=<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;保定</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,state_province</span>=<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;河北</span><span style="color: #800000;"&gt;'</span>,country=<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;China</span><span style="color: #800000;"&gt;'</span>,website=<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;http://www.hbu.com</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;)
OR  pub_obj</span>=Publisher.objects.get(id=1<span style="color: #000000;"&gt;)

</span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;       <2>将 publisher_id=2 改为  publisher=pub_obj</span>

       Book.objects.create(title=<span style="color: #800000;">'<span style="color: #800000;">PHP<span style="color: #800000;">'<span style="color: #000000;">,publisher=pub_obj,<span style="color: #008000;">#<span style="color: #008000;">添加的为出版社对象时不使用**_id了。
publication_date=<span style="color: #800000;">'<span style="color: #800000;">2017-7-7<span style="color: #800000;">'<span style="color: #000000;">,price=99)

display: none;" onclick="cnblogs_code_hide('ee5371d3-02aa-4507-b0fc-22fa8f9912a7',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;方式一:</span>
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;取出要<a href="/tag/tianjia/" target="_blank" class="keywords">添加</a>的作者对象列表,通过一本书籍的<ManyToManyDescriptor object>  .add<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a><a href="/tag/tianjia/" target="_blank" class="keywords">添加</a>作者对象。</span>

<span style="color: #000000;">
author1=Author.objects.get(id=1<span style="color: #000000;">)
author2=Author.objects.filter(name=<span style="color: #800000;">'<span style="color: #800000;">alvin<span style="color: #800000;">'<span style="color: #000000;">)[0]
book=Book.objects.get(id=1<span style="color: #000000;">)
book.authors.add(author1,author2)
<span style="color: #008000;">#<span style="color: #008000;">等同于:
book.authors.add(<span style="color: #000000;">[author1,author2])
book.authors.remove(
<span style="color: #000000;">[author1,author2])
<span style="color: #008000;">#<span style="color: #008000;">-------------------
<span style="color: #008000;">#<span style="color: #008000;">方式二:
<span style="color: #008000;">#<span style="color: #008000;">取出要添加的书籍对象列表,通过一个作者对象的.book_set.add(book)添加书籍对象。
book=models.Book.objects.filter(id__gt=1<span style="color: #000000;">)
authors=models.Author.objects.filter(id=1<span style="color: #000000;">)[0]
authors.book_set.add(
<span style="color: #000000;">book)
authors.book_set.remove(*<span style="color: #000000;">book)
<span style="color: #008000;">#<span style="color: #008000;">-------------------
<span style="color: #008000;">#<span style="color: #008000;">方式三:取出书籍或者作者对象,直接添加对应的id.
<span style="color: #000000;">
book.authors.add(1) <span style="color: #008000;">#<span style="color: #008000;">book.authors.add(1,2) 可一次添加多个id,已存在的id不会重复添加
book.authors.remove(1<span style="color: #000000;">)
authors.book_set.add(1<span style="color: #000000;">)
authors.book_set.remove(1<span style="color: #000000;">)

<span style="color: #008000;">#<span style="color: #008000;">注意: 如果第三张表是通过models.ManyToManyField()自动创建的,那么绑定关系只有上面一种方式<span style="color: #008000;">

<span style="color: #008000;"> 如果第三张表是自己创建的:

 <span style="color: #0000ff;"&gt;class</span><span style="color: #000000;"&gt; Book2Author(models.Model):
        author</span>=models.ForeignKey(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Author</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;)
        Book</span>=  models.ForeignKey(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Book</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;)

<span style="color: #008000;">#<span style="color: #008000;"> 那么就还有一种方式:
author_obj=models.Author.objects.filter(id=2<span style="color: #000000;">)[0]
book_obj =models.Book.objects.filter(id=3<span style="color: #000000;">)[0]

        s</span>=models.Book2Author.objects.create(author_id=1,Book_id=2<span style="color: #000000;"&gt;)
        s.save()
        s</span>=models.Book2Author(author=author_obj,Book_id=1<span style="color: #000000;"&gt;)
        s.save()</span></pre>

2、ORM之删(delete)

>>> Book.objects.filter(id=1).delete() (3,{'app01.Book_authors': 2,'app01.Book': 1})

我们表面上删除了一条信息,实际却删除了三条,因为我们删除的这本书在Book_authors表中有两条相关信息,这种删除方式就是django认的级联删除

3、ROM之改(update和save)

实例:

    

注意:

<1> 第二种方式修改不能用get的原因是:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象(filter里面的条件可能有多个条件符合,比如name='alvin',可能有两个name='alvin'的行数据)。

<2>在“插入和更新数据”小节中,我们有提到模型的 save() 方法,这个方法会更新一行里的所有列。而某些情况下,我们只需要更新行里的某几列。teral">

display: none;" onclick="cnblogs_code_hide('bae1c857-dfe4-4be4-8302-f52b5b98b084',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
方法直接设定对应属性---------------- models.Book.objects.filter(id=3).update(title=PHPsql: PHP',3)

<span style="color: #008000;">#<span style="color: #008000;">--------------- save方法会将所有属性重新设定一遍,效率低-----------
obj=models.Book.objects.filter(id=3<span style="color: #000000;">)[0]
obj.title=<span style="color: #800000;">"<span style="color: #800000;">Python<span style="color: #800000;">"<span style="color: #000000;">
obj.save()
<span style="color: #008000;">#<span style="color: #008000;"> SELECT "app01_book"."id","app01_book"."title","app01_book"."price",<span style="color: #008000;">

<span style="color: #008000;"> "app01_book"."color","app01_book"."page_num",<span style="color: #008000;">

<span style="color: #008000;"> "app01_book"."publisher_id" FROM "app01_book" WHERE "app01_book"."id" = 3 LIMIT 1; <span style="color: #008000;">

<span style="color: #008000;">

<span style="color: #008000;"> UPDATE "app01_book" SET "title" = 'Python',"price" = 3333,"color" = 'red',"page_num" = 556,<span style="color: #008000;">

<span style="color: #008000;"> "publisher_id" = 1 WHERE "app01_book"."id" = 3;

此外,update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。

注意,这里因为update返回的是一个整形,所以没法用query属性;对于每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分:

display: none;" onclick="cnblogs_code_hide('3f74d289-14c8-4c39-8176-784967def38d',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
LOGGING =: 1disable_existing_loggers::: [:
sql代码

4、ORM之查(filter和value)

4.1 查询API

display: none;" onclick="cnblogs_code_hide('cf4bb976-b96a-4883-a181-43e1b8fc57a6',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
查询相关API:

<span style="color: #008000;">#<span style="color: #008000;"> <1>filter(**kwargs): 它包含了与所给筛选条件相匹配的对象

<span style="color: #008000;">#<span style="color: #008000;"> <2>all(): 查询所有结果

<span style="color: #008000;">#<span style="color: #008000;"> <3>get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误

<span style="color: #008000;">#<span style="color: #008000;">-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()--------

<span style="color: #008000;">#<span style="color: #008000;"> <4>values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列

<span style="color: #008000;">#<span style="color: #008000;"> <5>exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象

<span style="color: #008000;">#<span style="color: #008000;"> <6>order_by(*field): 对查询结果排序

<span style="color: #008000;">#<span style="color: #008000;"> <7>reverse(): 对查询结果反向排序

<span style="color: #008000;">#<span style="color: #008000;"> <8>distinct(): 从返回结果中剔除重复纪录

<span style="color: #008000;">#<span style="color: #008000;"> <9>values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

<span style="color: #008000;">#<span style="color: #008000;"> <10>count(): 返回数据库中匹配查询(QuerySet)的对象数量

<span style="color: #008000;">#<span style="color: #008000;"> <11>first(): 返回第一条记录

<span style="color: #008000;">#<span style="color: #008000;"> <12>last(): 返回最后一条记录

<span style="color: #008000;">#<span style="color: #008000;"> <13>exists(): 如果QuerySet包含数据,就返回True,否则返回False

display: none;" onclick="cnblogs_code_hide('92550c68-de18-44ac-823e-09a3f33cbe37',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
---------------了不起的双下划线(__)之单表条件查询----------------

<span style="color: #008000;">#<span style="color: #008000;"> models.Tb1.objects.filter(idlt=10,idgt=1) # 获取id大于1 且 小于10的值<span style="color: #008000;">

<span style="color: #008000;"> models.Tb1.objects.filter(id__in=[11,22,33]) # 获取id等于11、22、33的数据<span style="color: #008000;">

<span style="color: #008000;"> models.Tb1.objects.exclude(id__in=[11,33]) # not in<span style="color: #008000;">

<span style="color: #008000;"> models.Tb1.objects.filter(name__contains="ven")<span style="color: #008000;">

<span style="color: #008000;"> models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感<span style="color: #008000;">

<span style="color: #008000;"> models.Tb1.objects.filter(id__range=[1,2]) # 范围bettwen and<span style="color: #008000;">

<span style="color: #008000;"> startswith,istartswith,endswith,iendswith,

查询

4.2 QuerySet与惰性机制

所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。

QuerySet特点:

       <1>  可迭代的

       <2>  可切片

<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;QuerySet:   可迭代</span>

<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; for obj in objs:#每一obj就是<a href="/tag/yige/" target="_blank" class="keywords">一个</a>行对象</span>
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;     print("obj:",obj)</span>
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; QuerySet:  可切片</span>

<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; print(objs[1])</span>
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; print(objs[1:4])</span>
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; print(objs[::-1])</span></pre>

QuerySet的高效使用:

display: none;" onclick="cnblogs_code_hide('47556a64-ee6e-4561-942a-ec6d02b0d960',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
<1> Django的queryset对应于<a href="/tag/shujuku/" target="_blank" class="keywords">数据库</a>的若干记录(row),通过可选的<a href="/tag/chaxun/" target="_blank" class="keywords">查询</a>来过滤。例如,下面的<a href="/tag/daima/" target="_blank" class="keywords">代码</a>会得到<a href="/tag/shujuku/" target="_blank" class="keywords">数据库</a>中名字为‘Dave’的所有的人:person_set </span>= Person.objects.filter(f<a href="/tag/irs/" target="_blank" class="keywords">irs</a>t_name=<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Dave</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;) 上面的<a href="/tag/daima/" target="_blank" class="keywords">代码</a>并没有运行任何的<a href="/tag/shujuku/" target="_blank" class="keywords">数据库</a><a href="/tag/chaxun/" target="_blank" class="keywords">查询</a>。你可以使用person_set,给它<a href="/tag/jiashang/" target="_blank" class="keywords">加上</a>一些过滤条件,或者将它传给某个<a href="/tag/hanshu/" target="_blank" class="keywords">函数</a>,这些操作都不会发送给<a href="/tag/shujuku/" target="_blank" class="keywords">数据库</a>。这是对的,因为<a href="/tag/shujuku/" target="_blank" class="keywords">数据库</a><a href="/tag/chaxun/" target="_blank" class="keywords">查询</a>是显著影响web应用<a href="/tag/xingneng/" target="_blank" class="keywords">性能</a>的因素之一。

<2><span style="color: #000000;">要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.为了验证这些,需要在settings里加入 LOGGING(验证方式)
obj=models.Book.objects.filter(id=3<span style="color: #000000;">)
<span style="color: #008000;">#<span style="color: #008000;"> for i in obj:
<span style="color: #008000;">#<span style="color: #008000;"> print(i)

    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; if obj:</span>
    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;     print("ok")</span>
<3>数据库获取,然后转换成Django的model。这被称为执行(evaluation).这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset,你不需要重复运行通用的查询。 obj=models.Book.objects.filter(id=3 </span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; for i in obj:</span> <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; print(i)</span> <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;# models.Book.objects.filter(id=3).update(title="GO")</span> <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;# obj_new=models.Book.objects.filter(id=3)</span> <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; for i in obj:</span> <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; print(i) #LOGGING只会打印一次</span> <4>方法来检查是否有数据:
        obj </span>= Book.objects.filter(id=4<span style="color: #000000;"&gt;)
        </span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;  exists()的检查可以避免数据放入queryset的cache。</span>
        <span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; obj.exists():
            </span><span style="color: #0000ff;"&gt;print</span>(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;<a href="/tag/HelloWorld/" target="_blank" class="keywords">Hello World!</a></span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;)

<5><span style="color: #000000;">当queryset非常巨大时,cache会成为问题处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法获取数据,处理完数据就将其丢弃。
objs =<span style="color: #000000;"> Book.objects.all().iterator()
<span style="color: #008000;">#<span style="color: #008000;"> iterator()可以一次只从数据库获取少量数据,这样可以节省内存
<span style="color: #0000ff;">for obj <span style="color: #0000ff;">in<span style="color: #000000;"> objs:
<span style="color: #0000ff;">print<span style="color: #000000;">(obj.name)
<span style="color: #008000;">#<span style="color: #008000;">BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
<span style="color: #0000ff;">for obj <span style="color: #0000ff;">in<span style="color: #000000;"> objs:
<span style="color: #0000ff;">print<span style="color: #000000;">(obj.name)

 </span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;当然,使用i<a href="/tag/tera/" target="_blank" class="keywords">tera</a>tor()<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>来防止<a href="/tag/shengcheng/" target="_blank" class="keywords">生成</a>cache,意味着遍历同<a href="/tag/yige/" target="_blank" class="keywords">一个</a>queryset时会重复执行<a href="/tag/chaxun/" target="_blank" class="keywords">查询</a>。所以使用i<a href="/tag/tera/" target="_blank" class="keywords">tera</a>tor()的时候要当心,确保你的<a href="/tag/daima/" target="_blank" class="keywords">代码</a>在操作<a href="/tag/yige/" target="_blank" class="keywords">一个</a>大的queryset时没有重复执行<a href="/tag/chaxun/" target="_blank" class="keywords">查询</a>。</span>

<span style="color: #000000;">
总结:
queryset的cache是用于减少程序对数据库查询,在通常的使用下会保证只有在需要的时候才会查询数据库。使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能会造成额外的数据库查询

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐