Django模型层

<div id="cnblogs_post_body" class="blogpost-body"><a name="_labelTop"></a><div id="navCategory"><p style="font-size:25px;color:#EE1289;"><i>知识预览</i></p><ul id="sortChapter"><li><a href="#_label0" style="color: #003366;text-decoration:none;font-size:18px">多表操作</a></li></ul></div><div style="text-align: right"><a href="#_labelTop">回到顶部</a><a name="_label0"></a></div><h1>多表操作</h1>
<h2>创建模型</h2>
<p>实例:我们来假定下面这些概念,字段和关系</p>
<p>作者模型:一个作者有姓名和年龄。</p>
<p>作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一的关系(one-to-one)</p>
<p>出版商模型:出版商有名称,所在城市以及email。</p>
<p>书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。</p>
<p>模型建立如下:</p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="color: #0000ff;">from</span> django.db <span style="color: #0000ff;">import</span><span style="color: #000000;"> models

</span><span style="color: #008000;">#</span><span style="color: #008000;"> Create your models here.</span>


<span style="color: #0000ff;">class</span><span style="color: #000000;"> Author(models.Model):
nid </span>= models.AutoField(primary_key=<span style="color: #000000;">True)
name</span>=models.CharField( max_length=32<span style="color: #000000;">)
age</span>=<span style="color: #000000;">models.IntegerField()

</span><span style="color: #008000;">#</span><span style="color: #008000;"> 与AuthorDetail建立一对一的关系</span>
authorDetail=models.OneToOneField(to=<span style="color: #800000;">"</span><span style="color: #800000;">AuthorDetail</span><span style="color: #800000;">"</span>,on_delete=<span style="color: #000000;">models.CASCADE)<br>
</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> AuthorDetail(models.Model):

nid </span>= models.AutoField(primary_key=<span style="color: #000000;">True)
birthday</span>=<span style="color: #000000;">models.DateField()
telephone</span>=<span style="color: #000000;">models.BigIntegerField()
addr</span>=models.CharField( max_length=64<span style="color: #000000;">)

</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Publish(models.Model):
nid </span>= models.AutoField(primary_key=<span style="color: #000000;">True)
name</span>=models.CharField( max_length=32<span style="color: #000000;">)
city</span>=models.CharField( max_length=32<span style="color: #000000;">)
email</span>=<span style="color: #000000;">models.EmailField()


</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Book(models.Model):

nid </span>= models.AutoField(primary_key=<span style="color: #000000;">True)
title </span>= models.CharField( max_length=32<span style="color: #000000;">)
publishDate</span>=<span style="color: #000000;">models.DateField()
price</span>=models.DecimalField(max_digits=5,decimal_places=2<span style="color: #000000;">)

</span><span style="color: #008000;">#</span><span style="color: #008000;"> 与Publish建立一对多的关系,外键字段建立在多的一方</span>
publish=models.ForeignKey(to=<span style="color: #800000;">"</span><span style="color: #800000;">Publish</span><span style="color: #800000;">"</span>,to_field=<span style="color: #800000;">"</span><span style="color: #800000;">nid</span><span style="color: #800000;">"</span>,on_delete=<span style="color: #000000;">models.CASCADE)
</span><span style="color: #008000;">#</span><span style="color: #008000;"> 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表</span>
authors=models.ManyToManyField(to=<span style="color: #800000;">'</span><span style="color: #800000;">Author</span><span style="color: #800000;">'</span>,)</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div>
<p>&nbsp;生成表如下:</p>
<p><img src="https://images2018.cnblogs.com/blog/877318/201805/877318-20180501223306119-1804705285.png" alt="" width="415" height="105"></p>
<p><img src="https://images2018.cnblogs.com/blog/877318/201805/877318-20180501223412676-377958198.png" alt="" width="404" height="100"></p>
<p><img src="https://images2018.cnblogs.com/blog/877318/201805/877318-20180501223511240-492522724.png" alt="" width="476" height="100"></p>
<p><img src="https://images2018.cnblogs.com/blog/877318/201805/877318-20180501223620025-185160553.png" alt="" width="350" height="99"></p>
<p><img src="https://images2018.cnblogs.com/blog/877318/201805/877318-20180501223701796-763894415.png" alt="" width="377" height="100"></p>
<p>&nbsp;</p>
<p>注意事项:</p>
<ul>
<li>&nbsp;表的名称<code>myapp_modelName</code>,是根据 模型中的元数据自动生成的,也可以覆写为别的名称  </li>
<li><code><span style="font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, sans-serif;">&nbsp;</span>id</code>&nbsp;字段是自动添加的</li>
<li>&nbsp;对于外键字段,Django 会在字段名上添加<tt class="docutils literal">"_id"</tt>&nbsp;来创建数据库中的列名</li>
<li>&nbsp;这个例子中的<code>CREATE TABLE</code>&nbsp;SQL 语句使用PostgreSQL 语法格式,要注意的是Django 会根据settings&nbsp;中指定的数据库类型来使用相应的SQL 语句。</li>
<li>&nbsp;定义好模型之后,你需要告诉Django _使用_这些模型。你要做的就是修改配置文件中的INSTALL_APPSZ中设置,在其中添加<code>models.py</code>所在应用的名称。</li>
<li class="line" data-line="91">外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。</li>
</ul>
<h2 class="line" data-line="91">添加表纪录&nbsp;</h2>
<p>操作前先简单的录入一些数据:</p>
<p>publish表:</p>
<p><img src="https://images2018.cnblogs.com/blog/877318/201805/877318-20180501231939514-1159349232.png" alt="" width="341" height="65"></p>
<p>author表:</p>
<p><img src="https://images2018.cnblogs.com/blog/877318/201805/877318-20180501232010534-1683544746.png" alt="" width="281" height="63"></p>
<p>authordetail表:</p>
<p><img src="https://images2018.cnblogs.com/blog/877318/201805/877318-20180501232217201-492441826.png" alt="" width="311" height="65"></p>
<h3>一对多</h3>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_963825" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div><div class="line number5 index4 alt2">5</div><div class="line number6 index5 alt1">6</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">方式</code><code class="python value">1</code><code class="python plain">:</code></div><div class="line number2 index1 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;</code><code class="python plain">publish_obj</code><code class="python keyword">=</code><code class="python plain">Publish.objects.get(nid</code><code class="python keyword">=</code><code class="python value">1</code><code class="python plain">)</code></div><div class="line number3 index2 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;</code><code class="python plain">book_obj</code><code class="python keyword">=</code><code class="python plain">Book.objects.create(title</code><code class="python keyword">=</code><code class="python string">"金瓶眉"</code><code class="python plain">,publishDate</code><code class="python keyword">=</code><code class="python string">"2012-12-12"</code><code class="python plain">,price</code><code class="python keyword">=</code><code class="python value">100</code><code class="python plain">,publish</code><code class="python keyword">=</code><code class="python plain">publish_obj)</code></div><div class="line number4 index3 alt1"><code class="python spaces">&nbsp;</code>&nbsp;</div><div class="line number5 index4 alt2"><code class="python plain">方式</code><code class="python value">2</code><code class="python plain">:</code></div><div class="line number6 index5 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;</code><code class="python plain">book_obj</code><code class="python keyword">=</code><code class="python plain">Book.objects.create(title</code><code class="python keyword">=</code><code class="python string">"金瓶眉"</code><code class="python plain">,publishDate</code><code class="python keyword">=</code><code class="python string">"2012-12-12"</code><code class="python plain">,price</code><code class="python keyword">=</code><code class="python value">100</code><code class="python plain">,publish_id</code><code class="python keyword">=</code><code class="python value">1</code><code class="python plain">)  </code></div></div></td></tr></tbody></table></div></div>
</div>
<p class="line" data-line="91"><img src="https://images2018.cnblogs.com/blog/877318/201805/877318-20180501231012070-1410608284.png" alt="" width="353" height="48"></p>
<p class="line" data-line="91"><span style="color: #ff0000;">核心:book_obj.publish与book_obj.publish_id是什么?&nbsp;</span></p>
<h3>多对多</h3>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="color: #008000;"> #</span><span style="color: #008000;"> 当前生成的书籍对象</span>
book_obj=Book.objects.create(title=<span style="color: #800000;">"</span><span style="color: #800000;">追风筝的人</span><span style="color: #800000;">"</span>,price=200,publishDate=<span style="color: #800000;">"</span><span style="color: #800000;">2012-11-12</span><span style="color: #800000;">"</span>,publish_id=1<span style="color: #000000;">)
</span><span style="color: #008000;">#</span><span style="color: #008000;"> 为书籍绑定的做作者对象</span>
yuan=Author.objects.filter(name=<span style="color: #800000;">"</span><span style="color: #800000;">yuan</span><span style="color: #800000;">"</span>).first() <span style="color: #008000;">#</span><span style="color: #008000;"> 在Author表中主键为2的纪录</span>
egon=Author.objects.filter(name=<span style="color: #800000;">"</span><span style="color: #800000;">alex</span><span style="color: #800000;">"</span>).first() <span style="color: #008000;">#</span><span style="color: #008000;"> 在Author表中主键为1的纪录</span>

<span style="color: #008000;">#</span><span style="color: #008000;"> 绑定多对多关系,即向关系表book_authors中添加纪录</span>
book_obj.authors.add(yuan,egon) <span style="color: #008000;">#</span><span style="color: #008000;"> 将某些特定的 model 对象添加到被关联对象集合中。 ======= book_obj.authors.add(*[])</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div>
<p>数据库表纪录生成如下:</p>
<p>book表&nbsp;</p>
<p><img src="https://images2018.cnblogs.com/blog/877318/201805/877318-20180501233728425-1500453543.png" alt="" width="448" height="63"></p>
<p>book_authors表</p>
<p><img src="https://images2018.cnblogs.com/blog/877318/201805/877318-20180501233939850-1362764638.png" alt="" width="190" height="58"></p>
<p><span style="color: #ff0000;">核心:book_obj.authors.all()是什么?</span></p>
<p>多对多关系其它常用API:</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_675111" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">book_obj.authors.remove()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code><code class="python comments"># 将某个特定的对象从被关联对象集合中去除。&nbsp;&nbsp;&nbsp; ======&nbsp;&nbsp; book_obj.authors.remove(*[])</code></div><div class="line number2 index1 alt1"><code class="python plain">book_obj.authors.clear()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code><code class="python comments">#清空被关联对象集合</code></div><div class="line number3 index2 alt2"><code class="python plain">book_obj.authors.</code><code class="python functions">set</code><code class="python plain">()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code><code class="python comments">#先清空再设置  </code></div></div></td></tr></tbody></table></div></div>
</div>
<p><a href="http://www.cnblogs.com/yuanchenqi/articles/8978167.html" target="_blank">more</a></p>
<h2>基于对象的跨表查询</h2>
<h3>一对多查询(Publish 与 Book)</h3>
<p>正向查询(按字段:publish):</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_92641" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python comments"># 查询主键为1的书籍的出版社所在的城市</code></div><div class="line number2 index1 alt1"><code class="python plain">book_obj</code><code class="python keyword">=</code><code class="python plain">Book.objects.</code><code class="python functions">filter</code><code class="python plain">(pk</code><code class="python keyword">=</code><code class="python value">1</code><code class="python plain">).first()</code></div><div class="line number3 index2 alt2"><code class="python comments"># book_obj.publish 是主键为1的书籍对象关联的出版社对象 </code></div><div class="line number4 index3 alt1"><code class="python functions">print</code><code class="python plain">(book_obj.publish.city)  </code></div></div></td></tr></tbody></table></div></div>
</div>
<p>反向查询(按表名:book_set):</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_783829" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div><div class="line number5 index4 alt2">5</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">publish</code><code class="python keyword">=</code><code class="python plain">Publish.objects.get(name</code><code class="python keyword">=</code><code class="python string">"苹果出版社"</code><code class="python plain">) </code></div><div class="line number2 index1 alt1"><code class="python comments">#publish.book_set.all() : 与苹果出版社关联的所有书籍对象集合</code></div><div class="line number3 index2 alt2"><code class="python plain">book_list</code><code class="python keyword">=</code><code class="python plain">publish.book_set.</code><code class="python functions">all</code><code class="python plain">()&nbsp;&nbsp;&nbsp;&nbsp; </code></div><div class="line number4 index3 alt1"><code class="python keyword">for</code> <code class="python plain">book_obj </code><code class="python keyword">in</code> <code class="python plain">book_list:</code></div><div class="line number5 index4 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python functions">print</code><code class="python plain">(book_obj.title)</code></div></div></td></tr></tbody></table></div></div>
</div>
<h3>一对一查询(Author 与 AuthorDetail)</h3>
<p>正向查询(按字段:authorDetail):</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_179290" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">egon</code><code class="python keyword">=</code><code class="python plain">Author.objects.</code><code class="python functions">filter</code><code class="python plain">(name</code><code class="python keyword">=</code><code class="python string">"egon"</code><code class="python plain">).first()</code></div><div class="line number2 index1 alt1"><code class="python functions">print</code><code class="python plain">(egon.authorDetail.telephone)</code></div></div></td></tr></tbody></table></div></div>
</div>
<p>反向查询(按表名:author):</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_192511" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div><div class="line number5 index4 alt2">5</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python comments"># 查询所有住址在北京的作者的姓名</code></div><div class="line number2 index1 alt1">&nbsp;</div><div class="line number3 index2 alt2"><code class="python plain">authorDetail_list</code><code class="python keyword">=</code><code class="python plain">AuthorDetail.objects.</code><code class="python functions">filter</code><code class="python plain">(addr</code><code class="python keyword">=</code><code class="python string">"beijing"</code><code class="python plain">)</code></div><div class="line number4 index3 alt1"><code class="python keyword">for</code> <code class="python plain">obj </code><code class="python keyword">in</code> <code class="python plain">authorDetail_list:</code></div><div class="line number5 index4 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python functions">print</code><code class="python plain">(obj.author.name)</code></div></div></td></tr></tbody></table></div></div>
</div>
<h3>多对多查询 (Author 与 Book)</h3>
<p>正向查询(按字段:authors):</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_844554" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div><div class="line number5 index4 alt2">5</div><div class="line number6 index5 alt1">6</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python comments"># 金瓶眉所有作者的名字以及手机号</code></div><div class="line number2 index1 alt1">&nbsp;</div><div class="line number3 index2 alt2"><code class="python plain">book_obj</code><code class="python keyword">=</code><code class="python plain">Book.objects.</code><code class="python functions">filter</code><code class="python plain">(title</code><code class="python keyword">=</code><code class="python string">"金瓶眉"</code><code class="python plain">).first()</code></div><div class="line number4 index3 alt1"><code class="python plain">authors</code><code class="python keyword">=</code><code class="python plain">book_obj.authors.</code><code class="python functions">all</code><code class="python plain">()</code></div><div class="line number5 index4 alt2"><code class="python keyword">for</code> <code class="python plain">author_obj </code><code class="python keyword">in</code> <code class="python plain">authors:</code></div><div class="line number6 index5 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python functions">print</code><code class="python plain">(author_obj.name,author_obj.authorDetail.telephone)</code></div></div></td></tr></tbody></table></div></div>
</div>
<p>反向查询(按表名:book_set):</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_538558" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div><div class="line number5 index4 alt2">5</div><div class="line number6 index5 alt1">6</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python comments"># 查询egon出过的所有书籍的名字</code></div><div class="line number2 index1 alt1">&nbsp;</div><div class="line number3 index2 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">author_obj</code><code class="python keyword">=</code><code class="python plain">Author.objects.get(name</code><code class="python keyword">=</code><code class="python string">"egon"</code><code class="python plain">)</code></div><div class="line number4 index3 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">book_list</code><code class="python keyword">=</code><code class="python plain">author_obj.book_set.</code><code class="python functions">all</code><code class="python plain">()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code><code class="python comments">#与egon作者相关的所有书籍</code></div><div class="line number5 index4 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python keyword">for</code> <code class="python plain">book_obj </code><code class="python keyword">in</code> <code class="python plain">book_list:</code></div><div class="line number6 index5 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python functions">print</code><code class="python plain">(book_obj.title)</code></div></div></td></tr></tbody></table></div></div>
</div>
<p><strong>注意:</strong></p>
<p>你可以通过在 ForeignKey() 和ManyToManyField的定义中设置 related_name 的值来覆写 FOO_set 的名称。例如,如果 Article model 中做一下更改:</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_716851" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">publish </code><code class="python keyword">=</code> <code class="python plain">ForeignKey(Book, related_name</code><code class="python keyword">=</code><code class="python string">'bookList'</code><code class="python plain">)</code></div></div></td></tr></tbody></table></div></div>
</div>
<p>那么接下来就会如我们看到这般:</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_954129" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python comments"># 查询 人民出版社出版过的所有书籍</code></div><div class="line number2 index1 alt1">&nbsp;</div><div class="line number3 index2 alt2"><code class="python plain">publish</code><code class="python keyword">=</code><code class="python plain">Publish.objects.get(name</code><code class="python keyword">=</code><code class="python string">"人民出版社"</code><code class="python plain">)</code></div><div class="line number4 index3 alt1"><code class="python plain">book_list</code><code class="python keyword">=</code><code class="python plain">publish.bookList.</code><code class="python functions">all</code><code class="python plain">()&nbsp; </code><code class="python comments"># 与人民出版社关联的所有书籍对象集合</code></div></div></td></tr></tbody></table></div></div>
</div>
<h2>基于双下划线的跨表查询&nbsp;</h2>
<p>Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系。要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的 model 为止。</p>
<p><span style="color: #ff0000;">关键点:正向查询按字段,反向查询按表名。</span></p>
<h3>一对多查询</h3>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_576257" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div><div class="line number5 index4 alt2">5</div><div class="line number6 index5 alt1">6</div><div class="line number7 index6 alt2">7</div><div class="line number8 index7 alt1">8</div><div class="line number9 index8 alt2">9</div><div class="line number10 index9 alt1">10</div><div class="line number11 index10 alt2">11</div><div class="line number12 index11 alt1">12</div><div class="line number13 index12 alt2">13</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python comments"># 练习1:&nbsp; 查询苹果出版社出版过的所有书籍的名字与价格(一对多)</code></div><div class="line number2 index1 alt1">&nbsp;</div><div class="line number3 index2 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python comments"># 正向查询 按字段:publish</code></div><div class="line number4 index3 alt1">&nbsp;</div><div class="line number5 index4 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">queryResult</code><code class="python keyword">=</code><code class="python plain">Book.objects</code></div><div class="line number6 index5 alt1"><code class="python plain">            .</code><code class="python functions">filter</code><code class="python plain">(publish__name</code><code class="python keyword">=</code><code class="python string">"苹果出版社"</code><code class="python plain">)</code></div><div class="line number7 index6 alt2"><code class="python plain">            .values_list(</code><code class="python string">"title"</code><code class="python plain">,</code><code class="python string">"price"</code><code class="python plain">)</code></div><div class="line number8 index7 alt1">&nbsp;</div><div class="line number9 index8 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python comments"># 反向查询 按表名:book</code></div><div class="line number10 index9 alt1">&nbsp;</div><div class="line number11 index10 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">queryResult</code><code class="python keyword">=</code><code class="python plain">Publish.objects</code></div><div class="line number12 index11 alt1"><code class="python plain">              .</code><code class="python functions">filter</code><code class="python plain">(name</code><code class="python keyword">=</code><code class="python string">"苹果出版社"</code><code class="python plain">)</code></div><div class="line number13 index12 alt2"><code class="python plain">              .values_list(</code><code class="python string">"book__title"</code><code class="python plain">,</code><code class="python string">"book__price"</code><code class="python plain">)</code></div></div></td></tr></tbody></table></div></div>
</div>
<h3>多对多查询  </h3>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_420864" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div><div class="line number5 index4 alt2">5</div><div class="line number6 index5 alt1">6</div><div class="line number7 index6 alt2">7</div><div class="line number8 index7 alt1">8</div><div class="line number9 index8 alt2">9</div><div class="line number10 index9 alt1">10</div><div class="line number11 index10 alt2">11</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python comments"># 练习2: 查询alex出过的所有书籍的名字(多对多)</code></div><div class="line number2 index1 alt1">&nbsp;</div><div class="line number3 index2 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python comments"># 正向查询 按字段:authors:</code></div><div class="line number4 index3 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">queryResult</code><code class="python keyword">=</code><code class="python plain">Book.objects</code></div><div class="line number5 index4 alt2"><code class="python plain">            .</code><code class="python functions">filter</code><code class="python plain">(authors__name</code><code class="python keyword">=</code><code class="python string">"yuan"</code><code class="python plain">)</code></div><div class="line number6 index5 alt1"><code class="python plain">            .values_list(</code><code class="python string">"title"</code><code class="python plain">)</code></div><div class="line number7 index6 alt2">&nbsp;</div><div class="line number8 index7 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python comments"># 反向查询 按表名:book</code></div><div class="line number9 index8 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">queryResult</code><code class="python keyword">=</code><code class="python plain">Author.objects</code></div><div class="line number10 index9 alt1"><code class="python plain">              .</code><code class="python functions">filter</code><code class="python plain">(name</code><code class="python keyword">=</code><code class="python string">"yuan"</code><code class="python plain">)</code></div><div class="line number11 index10 alt2"><code class="python plain">              .values_list(</code><code class="python string">"book__title"</code><code class="python plain">,</code><code class="python string">"book__price"</code><code class="python plain">)</code></div></div></td></tr></tbody></table></div></div>
</div>
<h3>混合使用</h3>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_737416" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div><div class="line number5 index4 alt2">5</div><div class="line number6 index5 alt1">6</div><div class="line number7 index6 alt2">7</div><div class="line number8 index7 alt1">8</div><div class="line number9 index8 alt2">9</div><div class="line number10 index9 alt1">10</div><div class="line number11 index10 alt2">11</div><div class="line number12 index11 alt1">12</div><div class="line number13 index12 alt2">13</div><div class="line number14 index13 alt1">14</div><div class="line number15 index14 alt2">15</div><div class="line number16 index15 alt1">16</div><div class="line number17 index16 alt2">17</div><div class="line number18 index17 alt1">18</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python comments"># 练习3: 查询人民出版社出版过的所有书籍的名字以及作者的姓名</code></div><div class="line number2 index1 alt1">&nbsp;</div><div class="line number3 index2 alt2">&nbsp;</div><div class="line number4 index3 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python comments"># 正向查询</code></div><div class="line number5 index4 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">queryResult</code><code class="python keyword">=</code><code class="python plain">Book.objects</code></div><div class="line number6 index5 alt1"><code class="python plain">            .</code><code class="python functions">filter</code><code class="python plain">(publish__name</code><code class="python keyword">=</code><code class="python string">"人民出版社"</code><code class="python plain">)</code></div><div class="line number7 index6 alt2"><code class="python plain">            .values_list(</code><code class="python string">"title"</code><code class="python plain">,</code><code class="python string">"authors__name"</code><code class="python plain">)</code></div><div class="line number8 index7 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python comments"># 反向查询</code></div><div class="line number9 index8 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">queryResult</code><code class="python keyword">=</code><code class="python plain">Publish.objects</code></div><div class="line number10 index9 alt1"><code class="python plain">              .</code><code class="python functions">filter</code><code class="python plain">(name</code><code class="python keyword">=</code><code class="python string">"人民出版社"</code><code class="python plain">)</code></div><div class="line number11 index10 alt2"><code class="python plain">              .values_list(</code><code class="python string">"book__title"</code><code class="python plain">,</code><code class="python string">"book__authors__age"</code><code class="python plain">,</code><code class="python string">"book__authors__name"</code><code class="python plain">)</code></div><div class="line number12 index11 alt1">&nbsp;</div><div class="line number13 index12 alt2">&nbsp;</div><div class="line number14 index13 alt1"><code class="python comments"># 练习4: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称</code></div><div class="line number15 index14 alt2">&nbsp;</div><div class="line number16 index15 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">queryResult</code><code class="python keyword">=</code><code class="python plain">Book.objects</code></div><div class="line number17 index16 alt2"><code class="python plain">            .</code><code class="python functions">filter</code><code class="python plain">(authors__authorDetail__telephone__regex</code><code class="python keyword">=</code><code class="python string">"151"</code><code class="python plain">)</code></div><div class="line number18 index17 alt1"><code class="python plain">            .values_list(</code><code class="python string">"title"</code><code class="python plain">,</code><code class="python string">"publish__name"</code><code class="python plain">)</code></div></div></td></tr></tbody></table></div></div>
</div>
<p>注意:</p>
<p>反向查询时,如果定义了related_name ,则用related_name替换表名,例如:</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_300545" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">publish </code><code class="python keyword">=</code> <code class="python plain">ForeignKey(Blog, related_name</code><code class="python keyword">=</code><code class="python string">'bookList'</code><code class="python plain">)</code></div></div></td></tr></tbody></table></div></div>
</div>
<p class="brush:python;collapse:true;;gutter:true;">练习1: 查询人民出版社出版过的所有书籍的名字与价格(一对多)</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_672759" class="syntaxhighlighter collapsed python"><div class="toolbar"><span><a href="#" class="toolbar_item command_expandSource expandSource">+ View Code</a></span><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div><div class="line number5 index4 alt2">5</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python comments">#反向查询 不再按表名:book,而是related_name:bookList</code></div><div class="line number2 index1 alt1">&nbsp;</div><div class="line number3 index2 alt2"><code class="python plain">queryResult</code><code class="python keyword">=</code><code class="python plain">Publish.objects</code></div><div class="line number4 index3 alt1"><code class="python plain">          .</code><code class="python functions">filter</code><code class="python plain">(name</code><code class="python keyword">=</code><code class="python string">"人民出版社"</code><code class="python plain">)</code></div><div class="line number5 index4 alt2"><code class="python plain">          .values_list(</code><code class="python string">"bookList__title"</code><code class="python plain">,</code><code class="python string">"bookList__price"</code><code class="python plain">)&nbsp;</code></div></div></td></tr></tbody></table></div></div>
</div>
<h2>聚合查询与分组查询</h2>
<h3><tt class="descname">聚合</tt></h3>
<p><tt class="descname">aggregate</tt>(*args,&nbsp;**kwargs)</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_128817" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python comments"># 计算所有图书的平均价格</code></div><div class="line number2 index1 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">&gt;&gt;&gt; </code><code class="python keyword">from</code> <code class="python plain">django.db.models </code><code class="python keyword">import</code> <code class="python plain">Avg</code></div><div class="line number3 index2 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">&gt;&gt;&gt; Book.objects.</code><code class="python functions">all</code><code class="python plain">().aggregate(Avg(</code><code class="python string">'price'</code><code class="python plain">))</code></div><div class="line number4 index3 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">{</code><code class="python string">'price__avg'</code><code class="python plain">: </code><code class="python value">34.35</code><code class="python plain">}</code></div></div></td></tr></tbody></table></div></div>
</div>
<p><span id="yiyi-17" class="yiyi-st"><tt class="docutils literal"><span class="pre">aggregate()</span></tt>是<tt class="docutils literal"><span class="pre">QuerySet</span></tt>&nbsp;的一个终止子句,意思是说,它返回一个包含一些键值对的字典。<span id="yiyi-18" class="yiyi-st">键的名称是聚合值的标识符,<span id="yiyi-19" class="yiyi-st">值是计算出来的聚合值。<span id="yiyi-20" class="yiyi-st">键的名称是按照字段和聚合函数的名称自动生成出来的。<span id="yiyi-21" class="yiyi-st">如果你想要为聚合值指定一个名称,可以向聚合子句提供它。</span></span></span></span></span></p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_409123" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">&gt;&gt;&gt; Book.objects.aggregate(average_price</code><code class="python keyword">=</code><code class="python plain">Avg(</code><code class="python string">'price'</code><code class="python plain">))</code></div><div class="line number2 index1 alt1"><code class="python plain">{</code><code class="python string">'average_price'</code><code class="python plain">: </code><code class="python value">34.35</code><code class="python plain">}</code></div></div></td></tr></tbody></table></div></div>
</div>
<p><span id="yiyi-22" class="yiyi-st">如果你希望生成不止一个聚合,你可以向<tt class="docutils literal"><span class="pre">aggregate()</span></tt>子句中添加另一个参数。<span id="yiyi-23" class="yiyi-st">所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:</span></span></p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_763043" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">&gt;&gt;&gt; </code><code class="python keyword">from</code> <code class="python plain">django.db.models </code><code class="python keyword">import</code> <code class="python plain">Avg, </code><code class="python functions">Max</code><code class="python plain">, </code><code class="python functions">Min</code></div><div class="line number2 index1 alt1"><code class="python plain">&gt;&gt;&gt; Book.objects.aggregate(Avg(</code><code class="python string">'price'</code><code class="python plain">), </code><code class="python functions">Max</code><code class="python plain">(</code><code class="python string">'price'</code><code class="python plain">), </code><code class="python functions">Min</code><code class="python plain">(</code><code class="python string">'price'</code><code class="python plain">))</code></div><div class="line number3 index2 alt2"><code class="python plain">{</code><code class="python string">'price__avg'</code><code class="python plain">: </code><code class="python value">34.35</code><code class="python plain">, </code><code class="python string">'price__max'</code><code class="python plain">: Decimal(</code><code class="python string">'81.20'</code><code class="python plain">), </code><code class="python string">'price__min'</code><code class="python plain">: Decimal(</code><code class="python string">'12.99'</code><code class="python plain">)}</code></div></div></td></tr></tbody></table></div></div>
</div>
<h3>分组</h3>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="color: #008000;">#</span><span style="color: #008000;">##################################--单表分组查询--#######################################################</span>
<span style="color: #000000;">


查询每一个部门名称以及对应的员工数

emp:

id name age salary dep
</span>1 alex 12 2000<span style="color: #000000;"> 销售部
</span>2 egon 22 3000<span style="color: #000000;"> 人事部
</span>3 wen 22 5000<span style="color: #000000;"> 人事部


sql语句:
select dep,Count(</span>*) <span style="color: #0000ff;">from</span><span style="color: #000000;"> emp group by dep;

ORM:
emp.objects.all().values(</span><span style="color: #800000;">"</span><span style="color: #800000;">dep</span><span style="color: #800000;">"</span>).annotate(Count(<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span><span style="color: #000000;">)


</span><span style="color: #008000;">#</span><span style="color: #008000;">##################################--多表分组查询--#######################################################</span>
<span style="color: #000000;">


多表分组查询:

查询每一个部门名称以及对应的员工数


emp:

id name age salary dep_id
</span>1 alex 12 2000 1
2 egon 22 3000 2
3 wen 22 5000 2<span style="color: #000000;">


dep

id name
</span>1<span style="color: #000000;"> 销售部
</span>2<span style="color: #000000;"> 人事部

emp-dep:

id name age salary dep_id id name
</span>1 alex 12 2000 1 1<span style="color: #000000;"> 销售部
</span>2 egon 22 3000 2 2<span style="color: #000000;"> 人事部
</span>3 wen 22 5000 2 2<span style="color: #000000;"> 人事部


sql语句:

select dep.name,Count(</span>*) <span style="color: #0000ff;">from</span> emp left join dep on emp.dep_id=<span style="color: #000000;">dep.id group by emp.dep_id
select dep.name,Count(</span>*) <span style="color: #0000ff;">from</span> emp left join dep on emp.dep_id=<span style="color: #000000;">dep.id group by dep.id,dep.name

ORM:
dep.objetcs.all().annotate(c</span>=Count(<span style="color: #800000;">"</span><span style="color: #800000;">emp</span><span style="color: #800000;">"</span>)).values(<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">c</span><span style="color: #800000;">"</span>)</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div>
<p>annotate()为<span style="color: #ff0000;">调用的<tt class="docutils literal">QuerySet</tt></span>中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。 </p>
<p>(1) 练习:统计每一本书的作者个数</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_152250" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">bookList</code><code class="python keyword">=</code><code class="python plain">Book.objects.annotate(authorsNum</code><code class="python keyword">=</code><code class="python plain">Count(</code><code class="python string">'authors'</code><code class="python plain">))</code></div><div class="line number2 index1 alt1"><code class="python keyword">for</code> <code class="python plain">book_obj </code><code class="python keyword">in</code> <code class="python plain">bookList:</code></div><div class="line number3 index2 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python functions">print</code><code class="python plain">(book_obj.title,book_obj.authorsNum)</code></div></div></td></tr></tbody></table></div></div>
</div>
<div class="cnblogs_code" onclick="cnblogs_code_show('bbb30d65-6d99-45e6-8057-f2ad0c5699c6')"><img id="code_img_closed_bbb30d65-6d99-45e6-8057-f2ad0c5699c6" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_bbb30d65-6d99-45e6-8057-f2ad0c5699c6" class="code_img_opened" style="display: none;" onclick="cnblogs_code_hide('bbb30d65-6d99-45e6-8057-f2ad0c5699c6',event)" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_bbb30d65-6d99-45e6-8057-f2ad0c5699c6" class="cnblogs_code_hide">
<pre><span style="color: #000000;">SELECT
</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">nid</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">title</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">publishDate</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">price</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">pageNum</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">publish_id</span><span style="color: #800000;">"</span><span style="color: #000000;">,
COUNT(</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book_authors</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">author_id</span><span style="color: #800000;">"</span>) AS <span style="color: #800000;">"</span><span style="color: #800000;">authorsNum</span><span style="color: #800000;">"</span><span style="color: #000000;">
FROM </span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span> LEFT OUTER JOIN <span style="color: #800000;">"</span><span style="color: #800000;">app01_book_authors</span><span style="color: #800000;">"</span><span style="color: #000000;">
ON (</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">nid</span><span style="color: #800000;">"</span> = <span style="color: #800000;">"</span><span style="color: #800000;">app01_book_authors</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">book_id</span><span style="color: #800000;">"</span><span style="color: #000000;">)
GROUP BY
</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">nid</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">title</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">publishDate</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">price</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">pageNum</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #800000;">"</span><span style="color: #800000;">app01_book</span><span style="color: #800000;">"</span>.<span style="color: #800000;">"</span><span style="color: #800000;">publish_id</span><span style="color: #800000;">"</span></pre>
</div>
<span class="cnblogs_code_collapse">sql</span></div>
<p>(2) 如果想对所查询对象的关联对象进行聚合:</p>
<p class="brush:python;gutter:true;">练习:统计每一个出版社的最便宜的书</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_359415" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">publishList</code><code class="python keyword">=</code><code class="python plain">Publish.objects.annotate(MinPrice</code><code class="python keyword">=</code><code class="python functions">Min</code><code class="python plain">(</code><code class="python string">"book__price"</code><code class="python plain">))</code></div><div class="line number2 index1 alt1"><code class="python keyword">for</code> <code class="python plain">publish_obj </code><code class="python keyword">in</code> <code class="python plain">publishList:</code></div><div class="line number3 index2 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python functions">print</code><code class="python plain">(publish_obj.name,publish_obj.MinPrice)</code></div></div></td></tr></tbody></table></div></div>
</div>
<p>annotate的返回值是querySet,如果不想遍历对象,可以用上valuelist:</p>
<div class="cnblogs_code">
<pre>queryResult=<span style="color: #000000;"> Publish.objects
            .annotate(MinPrice</span>=Min(<span style="color: #800000;">"</span><span style="color: #800000;">book__price</span><span style="color: #800000;">"</span><span style="color: #000000;">))
            .values_list(</span><span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">MinPrice</span><span style="color: #800000;">"</span><span style="color: #000000;">)
</span><span style="color: #0000ff;">print</span>(queryResult)</pre>
</div>
<p>方式2: </p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_485969" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">queryResult</code><code class="python keyword">=</code><code class="python plain">Book.objects.values(</code><code class="python string">"publish__name"</code><code class="python plain">).annotate(MinPrice</code><code class="python keyword">=</code><code class="python functions">Min</code><code class="python plain">(</code><code class="python string">'price'</code><code class="python plain">)) # 思考: </code><code class="python keyword">if</code> <code class="python plain">有一个出版社没有出版过书会怎样?</code></div></div></td></tr></tbody></table></div></div>
</div>
<p>(3) 统计每一本以py开头的书籍的作者个数:</p>
<div class="cnblogs_code">
<pre> queryResult=<span style="color: #000000;">Book.objects
           .filter(title__startswith</span>=<span style="color: #800000;">"</span><span style="color: #800000;">Py</span><span style="color: #800000;">"</span><span style="color: #000000;">)
           .annotate(num_authors</span>=Count(<span style="color: #800000;">'</span><span style="color: #800000;">authors</span><span style="color: #800000;">'</span>))</pre>
</div>
<p>(4) 统计不止一个作者的图书:</p>
<div class="cnblogs_code">
<pre>queryResult=<span style="color: #000000;">Book.objects
          .annotate(num_authors</span>=Count(<span style="color: #800000;">'</span><span style="color: #800000;">authors</span><span style="color: #800000;">'</span><span style="color: #000000;">))
          .filter(num_authors__gt</span>=1)</pre>
</div>
<p>(5)&nbsp;根据一本图书作者数量的多少对查询集&nbsp;<tt class="docutils literal">QuerySet</tt>进行排序:</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_422323" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">Book.objects.annotate(num_authors</code><code class="python keyword">=</code><code class="python plain">Count(</code><code class="python string">'authors'</code><code class="python plain">)).order_by(</code><code class="python string">'num_authors'</code><code class="python plain">)</code></div></div></td></tr></tbody></table></div></div>
</div>
<p>(6) 查询各个作者出的书的总价格:</p>
<div class="cnblogs_code">
<pre><span style="color: #008000;">#</span><span style="color: #008000;"> 按author表的所有字段 group by</span>
queryResult=Author.objects<br>              .annotate(SumPrice=Sum(<span style="color: #800000;">"</span><span style="color: #800000;">book__price</span><span style="color: #800000;">"</span>))<br>              .values_list(<span style="color: #800000;">"</span><span style="color: #800000;">name</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">SumPrice</span><span style="color: #800000;">"</span><span style="color: #000000;">)
</span><span style="color: #0000ff;">print</span><span style="color: #000000;">(queryResult)</span><span style="color: #008000;"><br></span></pre>
</div>
<h2>F查询与Q查询</h2>
<h3>F查询</h3>
<p>在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?</p>
<p>Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_797668" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python comments"># 查询评论数大于收藏数的书籍</code></div><div class="line number2 index1 alt1">&nbsp;</div><div class="line number3 index2 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;</code><code class="python keyword">from</code> <code class="python plain">django.db.models </code><code class="python keyword">import</code> <code class="python plain">F</code></div><div class="line number4 index3 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;</code><code class="python plain">Book.objects.</code><code class="python functions">filter</code><code class="python plain">(commnetNum__lt</code><code class="python keyword">=</code><code class="python plain">F(</code><code class="python string">'keepNum'</code><code class="python plain">))</code></div></div></td></tr></tbody></table></div></div>
</div>
<p>Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_556225" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python comments"># 查询评论数大于收藏数2倍的书籍</code></div><div class="line number2 index1 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">Book.objects.</code><code class="python functions">filter</code><code class="python plain">(commnetNum__lt</code><code class="python keyword">=</code><code class="python plain">F(</code><code class="python string">'keepNum'</code><code class="python plain">)</code><code class="python keyword">*</code><code class="python value">2</code><code class="python plain">)</code></div></div></td></tr></tbody></table></div></div>
</div>
<p>修改操作也可以使用F函数,比如将每一本书的价格提高30元:</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_884502" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">Book.objects.</code><code class="python functions">all</code><code class="python plain">().update(price</code><code class="python keyword">=</code><code class="python plain">F(</code><code class="python string">"price"</code><code class="python plain">)</code><code class="python keyword">+</code><code class="python value">30</code><code class="python plain">) </code></div></div></td></tr></tbody></table></div></div>
</div>
<h3>Q查询</h3>
<p><span id="yiyi-212" class="yiyi-st"><tt class="xref py py-meth docutils literal"><span class="pre">filter()</span></tt>&nbsp;等方法中的关键字参数查询都是一起进行“AND” 的。&nbsp;<span id="yiyi-213" class="yiyi-st">如果你需要执行更复杂的查询(例如<tt class="docutils literal"><span class="pre">OR</span></tt>&nbsp;语句),你可以使用<tt class="xref py py-class docutils literal"><span class="pre">Q&nbsp;<span class="pre">对象</span></span></tt>。</span></span></p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_563977" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python keyword">from</code> <code class="python plain">django.db.models </code><code class="python keyword">import</code> <code class="python plain">Q</code></div><div class="line number2 index1 alt1"><code class="python plain">Q(title__startswith</code><code class="python keyword">=</code><code class="python string">'Py'</code><code class="python plain">)</code></div></div></td></tr></tbody></table></div></div>
</div>
<p><span id="yiyi-217" class="yiyi-st"><tt class="docutils literal"><span class="pre">Q</span></tt>&nbsp;对象可以使用<tt class="docutils literal"><span class="pre">&amp;</span></tt>&nbsp;和<tt class="docutils literal"><span class="pre">|</span></tt>&nbsp;操作符组合起来。<span id="yiyi-218" class="yiyi-st">当一个操作符在两个<tt class="docutils literal"><span class="pre">Q</span></tt>&nbsp;对象上使用时,它产生一个新的<tt class="docutils literal"><span class="pre">Q</span></tt>&nbsp;对象。</span></span></p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_88790" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">bookList</code><code class="python keyword">=</code><code class="python plain">Book.objects.</code><code class="python functions">filter</code><code class="python plain">(Q(authors__name</code><code class="python keyword">=</code><code class="python string">"yuan"</code><code class="python plain">)|Q(authors__name</code><code class="python keyword">=</code><code class="python string">"egon"</code><code class="python plain">))</code></div></div></td></tr></tbody></table></div></div>
</div>
<p>等同于下面的SQL&nbsp;<tt class="docutils literal"><span class="pre">WHERE</span></tt>&nbsp;子句:</p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_266698" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">WHERE name </code><code class="python keyword">=</code><code class="python string">"yuan"</code> <code class="python plain">OR name </code><code class="python keyword">=</code><code class="python string">"egon"</code></div></div></td></tr></tbody></table></div></div>
</div>
<p><span id="yiyi-221" class="yiyi-st">你可以组合<tt class="docutils literal"><span class="pre">&amp;</span></tt>&nbsp;和<tt class="docutils literal"><span class="pre">|</span></tt>&nbsp;&nbsp;操作符以及使用括号进行分组来编写任意复杂的<tt class="docutils literal"><span class="pre">Q</span></tt>&nbsp;对象。<span id="yiyi-222" class="yiyi-st">同时,<tt class="docutils literal"><span class="pre">Q</span></tt>&nbsp;对象可以使用<tt class="docutils literal"><span class="pre">~</span></tt>&nbsp;操作符取反,这允许组合正常的查询和取反(<tt class="docutils literal"><span class="pre">NOT</span></tt>) 查询:</span></span></p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_670966" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">bookList</code><code class="python keyword">=</code><code class="python plain">Book.objects.</code><code class="python functions">filter</code><code class="python plain">(Q(authors__name</code><code class="python keyword">=</code><code class="python string">"yuan"</code><code class="python plain">) &amp; ~Q(publishDate__year</code><code class="python keyword">=</code><code class="python value">2017</code><code class="python plain">)).values_list(</code><code class="python string">"title"</code><code class="python plain">)</code></div></div></td></tr></tbody></table></div></div>
</div>
<p><span id="yiyi-227" class="yiyi-st">查询函数可以混合使用<tt class="docutils literal"><span class="pre">Q 对象</span></tt>和关键字参数。<span id="yiyi-228" class="yiyi-st">所有提供给查询函数的参数(关键字参数或<tt class="docutils literal"><span class="pre">Q</span></tt>&nbsp;对象)都将"AND”在一起。<span id="yiyi-229" class="yiyi-st">但是,如果出现<tt class="docutils literal"><span class="pre">Q</span></tt>&nbsp;对象,它必须位于所有关键字参数的前面。<span id="yiyi-230" class="yiyi-st">例如:</span></span></span></span></p>
<div class="cnblogs_Highlighter sh-gutter">
<div><div id="highlighter_687391" class="syntaxhighlighter python"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">bookList</code><code class="python keyword">=</code><code class="python plain">Book.objects.</code><code class="python functions">filter</code><code class="python plain">(Q(publishDate__year</code><code class="python keyword">=</code><code class="python value">2016</code><code class="python plain">) | Q(publishDate__year</code><code class="python keyword">=</code><code class="python value">2017</code><code class="python plain">),</code></div><div class="line number2 index1 alt1"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">title__icontains</code><code class="python keyword">=</code><code class="python string">"python"</code></div><div class="line number3 index2 alt2"><code class="python spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="python plain">)</code></div></div></td></tr></tbody></table></div></div>
</div>
<p>  </p>
<p>&nbsp;</p></div>

猜你喜欢

转载自www.cnblogs.com/2018-01-30/p/9103243.html
今日推荐