<body> <a name="top"></a> <!--done--> <div id="home"> <div id="header"> <div id="blogTitle"> <a id="lnkBlogLogo" href="http://www.cnblogs.com/yuanchenqi/"><img id="blogLogo" alt="返回主页" src="/Skins/custom/images/logo.gif"></a> <!--done--> <h1><a class="headermaintitle" id="Header1_HeaderTitle" href="http://www.cnblogs.com/yuanchenqi/">Yuan 先生!</a></h1> <h2></h2> </div><!--end: blogTitle 博客的标题和副标题 --> <div id="navigator"> <ul id="navList"> <li><a class="menu" id="blog_nav_sitehome" href="http://www.cnblogs.com/">博客园</a></li> <li><a class="menu" id="blog_nav_myhome" href="http://www.cnblogs.com/yuanchenqi/">首页</a></li> <li><a class="menu" id="blog_nav_newpost" href="https://i.cnblogs.com/EditPosts.aspx?opt=1" rel="nofollow">新随笔</a></li> <li></li> <li><a class="menu" id="blog_nav_rss" href="http://www.cnblogs.com/yuanchenqi/rss">订阅</a> <!--<a id="blog_nav_rss_image" class="aHeaderXML" href="http://www.cnblogs.com/yuanchenqi/rss"><img src="//www.cnblogs.com/images/xml.gif" alt="订阅" /></a>--></li> <li><a class="menu" id="blog_nav_admin" href="https://i.cnblogs.com/" rel="nofollow">管理</a></li> </ul> <div class="blogStats"> <div id="blog_stats"> <span id="stats_post_count">随笔 - 1 </span> <span id="stats_article_count">文章 - 101 </span> <span id="stats-comment_count">评论 - 99</span> </div> </div><!--end: blogStats --> </div><!--end: navigator 博客导航栏 --> </div><!--end: header 头部 --> <div id="main"> <div id="mainContent"> <div class="forFlow"> <div id="post_detail"> <!--done--> <div id="topics"> <div class="post"> <h1 class="postTitle"> <a class="postTitle2" id="cb_post_title_url" href="http://www.cnblogs.com/yuanchenqi/articles/7614921.html">Django-form表单</a> </h1> <div class="clear"></div> <div class="postBody"> <div id="cnblogs_post_body"><a name="_labelTop"></a><div id="navCategory"><p style="font-size:25px;color:#EE1289;"><i>知识预览</i></p><ul id="sortChapter"><li><a style="color: #003366;text-decoration:none;font-size:18px" href="#_label0">构建一个表单</a></li><li><a style="color: #003366;text-decoration:none;font-size:18px" href="#_label1">在Django 中构建一个表单</a></li><li><a style="color: #003366;text-decoration:none;font-size:18px" href="#_label2">Django Form 类详解</a></li><li><a style="color: #003366;text-decoration:none;font-size:18px" href="#_label3">使用表单模板</a></li></ul></div><div style="text-align: right"><a href="#_labelTop">回到顶部</a><a name="_label0"></a></div><h1 class="line" data-line="97">构建一个表单</h1> <p>假设你想在你的网站上创建一个简单的表单,以获得用户的名字。你需要类似这样的模板:</p> <div class="cnblogs_Highlighter sh-gutter"> <div><div class="syntaxhighlighter sql" id="highlighter_289748"><div class="toolbar"><span><a class="toolbar_item command_help help" href="#">?</a></span></div><table border="0" cellspacing="0" cellpadding="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="sql plain"><form </code><code class="sql keyword">action</code><code class="sql plain">=</code><code class="sql string">"/your-name/"</code> <code class="sql plain">method=</code><code class="sql string">"post"</code><code class="sql plain">></code></div><div class="line number2 index1 alt1"><code class="sql spaces"> </code><code class="sql plain"><label </code><code class="sql keyword">for</code><code class="sql plain">=</code><code class="sql string">"your_name"</code><code class="sql plain">>Your </code><code class="sql keyword">name</code><code class="sql plain">: </label></code></div><div class="line number3 index2 alt2"><code class="sql spaces"> </code><code class="sql plain"><input id=</code><code class="sql string">"your_name"</code> <code class="sql plain">type=</code><code class="sql string">"text"</code> <code class="sql keyword">name</code><code class="sql plain">=</code><code class="sql string">"your_name"</code><code class="sql plain">></code></div><div class="line number4 index3 alt1"><code class="sql spaces"> </code><code class="sql plain"><input type=</code><code class="sql string">"submit"</code> <code class="sql plain">value=</code><code class="sql string">"OK"</code><code class="sql plain">></code></div><div class="line number5 index4 alt2"><code class="sql plain"></form></code></div></div></td></tr></tbody></table></div></div> </div> <p>这是一个非常简单的表单。实际应用中,一个表单可能包含几十上百个字段,其中大部分需要预填充,而且我们预料到用户将来回编辑-提交几次才能完成操作。</p> <p>我们可能需要在表单提交之前,在浏览器端作一些验证。我们可能想使用非常复杂的字段,以允许用户做类似从日历中挑选日期这样的事情,等等。</p> <p>这个时候,让Django 来为我们完成大部分工作是很容易的。</p> <p>so,两个突出优点:</p> <p> 1 form表单提交时,数据出现错误,返回的页面中仍可以保留之前输入的数据。</p> <p> 2 方便地限制字段条件</p> <div style="text-align: right"><a href="#_labelTop">回到顶部</a><a name="_label1"></a></div><h1 class="line" data-line="125">在Django 中构建一个表单</h1> <h2 class="line" data-line="127">Form 类</h2> <p>我们已经计划好了我们的 HTML 表单应该呈现的样子。在Django 中,我们的起始点是这里:</p> <div class="cnblogs_Highlighter sh-gutter"> <div><div class="syntaxhighlighter sql" id="highlighter_41420"><div class="toolbar"><span><a class="toolbar_item command_help help" href="#">?</a></span></div><table border="0" cellspacing="0" cellpadding="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="sql plain">#forms.py</code></div><div class="line number2 index1 alt1"> </div><div class="line number3 index2 alt2"><code class="sql keyword">from</code> <code class="sql plain">django import forms</code></div><div class="line number4 index3 alt1"> </div><div class="line number5 index4 alt2"><code class="sql plain">class NameForm(forms.Form):</code></div><div class="line number6 index5 alt1"><code class="sql spaces"> </code><code class="sql plain">your_name = forms.CharField(label=</code><code class="sql string">'Your name'</code><code class="sql plain">, max_length=100)</code></div></div></td></tr></tbody></table></div></div> </div> <p> 它定义一个<code>Form</code> 类,只带有一个字段(<code>your_name</code>)。</p> <p>字段允许的最大长度通过<code>max_length</code> 定义。它完成两件事情。首先,它在HTML 的<code><input></code> 上放置一个<code>maxlength="100"</code>(这样浏览器将在第一时间阻止用户输入多于这个数目的字符)。它还意味着当Django 收到浏览器发送过来的表单时,它将验证数据的长度。</p> <p><code>Form</code> 的<span style="color: #ff0000;">实例</span>具有一个<code>is_valid()</code> 方法,它为所有的字段运行验证的程序。当调用这个方法时,如果所有的字段都包含合法的数据,它将:</p> <ul> <li>返回<code>True</code></li> <li>将表单的数据放到<code>cleaned_data</code>属性中。</li> </ul> <p>完整的表单,第一次<span style="color: #ff0000;">渲染</span>时,看上去将像:</p> <div class="cnblogs_Highlighter sh-gutter"> <div><div class="syntaxhighlighter sql" id="highlighter_669757"><div class="toolbar"><span><a class="toolbar_item command_help help" href="#">?</a></span></div><table border="0" cellspacing="0" cellpadding="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="sql plain"><label </code><code class="sql keyword">for</code><code class="sql plain">=</code><code class="sql string">"your_name"</code><code class="sql plain">>Your </code><code class="sql keyword">name</code><code class="sql plain">: </label></code></div><div class="line number2 index1 alt1"><code class="sql plain"><input id=</code><code class="sql string">"your_name"</code> <code class="sql plain">type=</code><code class="sql string">"text"</code> <code class="sql keyword">name</code><code class="sql plain">=</code><code class="sql string">"your_name"</code> <code class="sql plain">maxlength=</code><code class="sql string">"100"</code><code class="sql plain">></code></div></div></td></tr></tbody></table></div></div> </div> <p> 注意它不包含 <code><form></code> 标签和提交按钮。我们必须自己在模板中提供它们。</p> <h2 class="line" data-line="158">视图</h2> <p>发送给Django 网站的表单数据通过一个视图处理,一般和发布这个表单的是同一个视图。这允许我们重用一些相同的逻辑。</p> <p>当处理表单时,我们需要在视图中实例化它:</p> <div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="//common.cnblogs.com/images/copycode.gif"></a></span></div> <pre><span style="color: #008000;">#</span><span style="color: #008000;">views.py</span> <span style="color: #0000ff;">from</span> django.shortcuts <span style="color: #0000ff;">import</span><span style="color: #000000;"> render </span><span style="color: #0000ff;">from</span> django.http <span style="color: #0000ff;">import</span><span style="color: #000000;"> HttpResponseRedirect </span><span style="color: #0000ff;">from</span> .forms <span style="color: #0000ff;">import</span><span style="color: #000000;"> NameForm </span><span style="color: #0000ff;">def</span><span style="color: #000000;"> get_name(request): </span><span style="color: #008000;">#</span><span style="color: #008000;"> if this is a POST request we need to process the form data</span> <span style="color: #0000ff;">if</span> request.method == <span style="color: #800000;">'</span><span style="color: #800000;">POST</span><span style="color: #800000;">'</span><span style="color: #000000;">: </span><span style="color: #008000;">#</span><span style="color: #008000;"> create a form instance and populate it with data from the request:</span> form =<span style="color: #000000;"> NameForm(request.POST) </span><span style="color: #008000;">#</span><span style="color: #008000;"> check whether it's valid:</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> form.is_valid(): </span><span style="color: #008000;">#</span><span style="color: #008000;"> process the data in form.cleaned_data as required</span> <span style="color: #008000;">#</span><span style="color: #008000;"> ...</span> <span style="color: #008000;">#</span><span style="color: #008000;"> redirect to a new URL:</span> <span style="color: #0000ff;">return</span> HttpResponseRedirect(<span style="color: #800000;">'</span><span style="color: #800000;">/thanks/</span><span style="color: #800000;">'</span><span style="color: #000000;">) </span><span style="color: #008000;">#</span><span style="color: #008000;"> if a GET (or any other method) we'll create a blank form</span> <span style="color: #0000ff;">else</span><span style="color: #000000;">: form </span>=<span style="color: #000000;"> NameForm() </span><span style="color: #0000ff;">return</span> render(request, <span style="color: #800000;">'</span><span style="color: #800000;">name.html</span><span style="color: #800000;">'</span>, {<span style="color: #800000;">'</span><span style="color: #800000;">form</span><span style="color: #800000;">'</span>: form})</pre> <div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="//common.cnblogs.com/images/copycode.gif"></a></span></div></div> <p>如果访问视图的是一个<code>GET</code> 请求,它将创建一个空的表单实例并将它放置到要渲染的模板的上下文中。这是我们在第一个访问该URL 时预期发生的情况。</p> <p>如果表单的提交使用<code>POST</code> 请求,那么视图将再次创建一个表单实例并使用请求中的数据填充它:<code>form = NameForm(request.POST)</code>。这叫做”绑定数据至表单“(它现在是一个绑定的表单)。</p> <p>我们调用表单的<code>is_valid()</code>方法;如果它不为<code>True</code>,我们将带着这个表单返回到模板。这时表单不再为空(未绑定),所以HTML 表单将用之前提交的数据填充,然后可以根据要求编辑并改正它。</p> <p>如果<code>is_valid()</code>为<code>True</code>,我们将能够在<code>cleaned_data</code> 属性中找到所有合法的表单数据。在发送HTTP 重定向给浏览器告诉它下一步的去向之前,我们可以用这个数据来更新数据库或者做其它处理。</p> <h2 class="line" data-line="199">模板</h2> <p>我们不需要在name.html 模板中做很多工作。最简单的例子是:</p> <div class="cnblogs_Highlighter sh-gutter"> <div><div class="syntaxhighlighter sql" id="highlighter_703535"><div class="toolbar"><span><a class="toolbar_item command_help help" href="#">?</a></span></div><table border="0" cellspacing="0" cellpadding="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="sql plain"><form </code><code class="sql keyword">action</code><code class="sql plain">=</code><code class="sql string">"/your-name/"</code> <code class="sql plain">method=</code><code class="sql string">"post"</code><code class="sql plain">></code></div><div class="line number2 index1 alt1"><code class="sql spaces"> </code><code class="sql plain">{% csrf_token %}</code></div><div class="line number3 index2 alt2"><code class="sql spaces"> </code><code class="sql plain">{{ form }}</code></div><div class="line number4 index3 alt1"><code class="sql spaces"> </code><code class="sql plain"><input type=</code><code class="sql string">"submit"</code> <code class="sql plain">value=</code><code class="sql string">"Submit"</code> <code class="sql plain">/></code></div><div class="line number5 index4 alt2"><code class="sql plain"></form></code></div></div></td></tr></tbody></table></div></div> </div> <p> 根据<code>{{ form }}</code>,所有的表单字段和它们的属性将通过Django 的模板语言拆分成HTML 标记 。</p> <p>注:Django 原生支持一个简单易用的<a href="http://python.usyiyi.cn/django/ref/csrf.html">跨站请求伪造的防护</a>。当提交一个启用CSRF 防护的<code>POST</code> 表单时,你必须使用上面例子中的<code>csrf_token</code> 模板标签。</p> <p>现在我们有了一个可以工作的网页表单,它通过Django Form 描述、通过视图处理并渲染成一个HTML <code><form></code>。</p> <div style="text-align: right"><a href="#_labelTop">回到顶部</a><a name="_label2"></a></div><h1>Django Form 类详解</h1> <h2>绑定的和未绑定的表单实例</h2> <p>绑定的和未绑定的表单 之间的区别非常重要:</p> <ul> <li>未绑定的表单没有关联的数据。当渲染给用户时,它将为空或包含默认的值。</li> <li>绑定的表单具有提交的数据,因此可以用来检验数据是否合法。如果渲染一个不合法的绑定的表单,它将包含内联的错误信息,告诉用户如何纠正数据。</li> </ul> <h2 class="line" data-line="242">字段详解</h2> <p>考虑一个比上面的迷你示例更有用的一个表单,我们完成一个更加有用的注册表单:</p> <div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="//common.cnblogs.com/images/copycode.gif"></a></span></div> <pre><span style="color: #008000;">#</span><span style="color: #008000;">forms.py</span> <span style="color: #0000ff;">from</span> django <span style="color: #0000ff;">import</span><span style="color: #000000;"> forms </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> RegisterForm(forms.Form): username </span>= forms.CharField(max_length=100<span style="color: #000000;">, error_messages</span>={<span style="color: #800000;">"</span><span style="color: #800000;">min_length</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">最短为5个字符</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">required</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">该字段不能为空</span><span style="color: #800000;">"</span><span style="color: #000000;">}, ) password </span>= forms.CharField(max_length=100<span style="color: #000000;">, widget</span>=widgets.PasswordInput(attrs={<span style="color: #800000;">"</span><span style="color: #800000;">placeholder</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">password</span><span style="color: #800000;">"</span><span style="color: #000000;">}) ) telephone</span>=<span style="color: #000000;">forms.IntegerField( error_messages</span>=<span style="color: #000000;">{ </span><span style="color: #800000;">"</span><span style="color: #800000;">invalid</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">格式错误</span><span style="color: #800000;">"</span><span style="color: #000000;"> } ) gender</span>=<span style="color: #000000;">forms.CharField( initial</span>=2<span style="color: #000000;">, widget</span>=widgets.Select(choices=((1,<span style="color: #800000;">'</span><span style="color: #800000;">上海</span><span style="color: #800000;">'</span>),(2,<span style="color: #800000;">'</span><span style="color: #800000;">北京</span><span style="color: #800000;">'</span><span style="color: #000000;">),)) ) email </span>=<span style="color: #000000;"> forms.EmailField() is_married </span>= forms.BooleanField(required=False)</pre> <div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="//common.cnblogs.com/images/copycode.gif"></a></span></div></div> <h3 class="line" data-line="260">Widgets</h3> <p>每个表单字段都有一个对应的<code>Widget</code> 类,它对应一个HTML 表单<code>Widget</code>,例如<code><input type="text"></code>。</p> <p>在大部分情况下,字段都具有一个合理的默认Widget。例如,默认情况下,<code>CharField</code> 具有一个<code>TextInput Widget</code>,它在HTML 中生成一个<code><input type="text"></code>。</p> <h3 class="line" data-line="266">字段的数据</h3> <p>不管表单提交的是什么数据,一旦通过调用<code>is_valid()</code> 成功验证(<code>is_valid()</code> 返回<code>True</code>),验证后的表单数据将位于<code>form.cleaned_data</code> 字典中。这些数据已经为你转换好为Python 的类型。</p> <p>注:此时,你依然可以从<code>request.POST</code> 中直接访问到未验证的数据,但是访问验证后的数据更好一些。</p> <p>在上面的联系表单示例中,<span style="color: #000000;">is_married</span>将是一个布尔值。类似地,<code>IntegerField</code> 和<code>FloatField</code> 字段分别将值转换为Python 的<code>int</code> 和<code>float</code>。</p> <div style="text-align: right"><a href="#_labelTop">回到顶部</a><a name="_label3"></a></div><h1 class="line" data-line="303">使用表单模板</h1> <p>你需要做的就是将表单实例放进模板的上下文。如果你的表单在<code>Contex</code>t 中叫做<code>form</code>,那么<code>{{ form }}</code>将正确地渲染它的<code><label></code> 和 <code><input></code>元素。</p> <h2 class="line" data-line="307">表单渲染的选项</h2> <p>对于<code><label>/<input></code> 对,还有几个输出选项:</p> <ul> <li><code>{{ form.as_table }}</code> 以表格的形式将它们渲染在<code><tr></code> 标签中</li> <li><code>{{ form.as_p }}</code> 将它们渲染在<code><p></code> 标签中</li> <li><code>{{ form.as_ul }}</code> 将它们渲染在<code><li></code> 标签中</li> </ul> <p>注意,你必须自己提供<code><table></code> 或<code><ul></code> 元素。</p> <p><code>{{ form.as_p }}</code>会渲染如下:</p> <div class="cnblogs_Highlighter sh-gutter"> <div><div class="syntaxhighlighter collapsed html" id="highlighter_927350"><div class="toolbar"><span><a class="toolbar_item command_expandSource expandSource" href="#">+ View Code</a></span><span><a class="toolbar_item command_help help" href="#">?</a></span></div><table border="0" cellspacing="0" cellpadding="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><div class="line number19 index18 alt2">19</div><div class="line number20 index19 alt1">20</div><div class="line number21 index20 alt2">21</div><div class="line number22 index21 alt1">22</div><div class="line number23 index22 alt2">23</div><div class="line number24 index23 alt1">24</div><div class="line number25 index24 alt2">25</div><div class="line number26 index25 alt1">26</div><div class="line number27 index26 alt2">27</div><div class="line number28 index27 alt1">28</div><div class="line number29 index28 alt2">29</div><div class="line number30 index29 alt1">30</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="html plain"><</code><code class="html keyword">form</code> <code class="html plain">action=""></code></div><div class="line number2 index1 alt1"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">p</code><code class="html plain">></code></div><div class="line number3 index2 alt2"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">label</code> <code class="html plain">for="id_username">Username:</</code><code class="html keyword">label</code><code class="html plain">> </code></div><div class="line number4 index3 alt1"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">input</code> <code class="html plain">id="id_username" maxlength="100" name="username" type="text" required=""></code></div><div class="line number5 index4 alt2"><code class="html spaces"> </code><code class="html plain"></</code><code class="html keyword">p</code><code class="html plain">></code></div><div class="line number6 index5 alt1"> </div><div class="line number7 index6 alt2"> </div><div class="line number8 index7 alt1"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">p</code><code class="html plain">></code></div><div class="line number9 index8 alt2"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">label</code> <code class="html plain">for="id_password">Password:</</code><code class="html keyword">label</code><code class="html plain">> </code></div><div class="line number10 index9 alt1"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">input</code> <code class="html plain">id="id_password" maxlength="100" name="password" placeholder="password" type="password" required=""></code></div><div class="line number11 index10 alt2"><code class="html spaces"> </code><code class="html plain"></</code><code class="html keyword">p</code><code class="html plain">></code></div><div class="line number12 index11 alt1"> </div><div class="line number13 index12 alt2"> </div><div class="line number14 index13 alt1"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">p</code><code class="html plain">></code></div><div class="line number15 index14 alt2"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">label</code> <code class="html plain">for="id_telephone">Telephone:</</code><code class="html keyword">label</code><code class="html plain">> <</code><code class="html keyword">input</code> <code class="html plain">id="id_telephone" name="telephone" type="number" required=""></code></div><div class="line number16 index15 alt1"><code class="html spaces"> </code><code class="html plain"></</code><code class="html keyword">p</code><code class="html plain">></code></div><div class="line number17 index16 alt2"> </div><div class="line number18 index17 alt1"> </div><div class="line number19 index18 alt2"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">p</code><code class="html plain">></code></div><div class="line number20 index19 alt1"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">label</code> <code class="html plain">for="id_email">Email:</</code><code class="html keyword">label</code><code class="html plain">> <</code><code class="html keyword">input</code> <code class="html plain">id="id_email" name="email" type="email" required=""></code></div><div class="line number21 index20 alt2"><code class="html spaces"> </code><code class="html plain"></</code><code class="html keyword">p</code><code class="html plain">></code></div><div class="line number22 index21 alt1"> </div><div class="line number23 index22 alt2"> </div><div class="line number24 index23 alt1"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">p</code><code class="html plain">></code></div><div class="line number25 index24 alt2"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">label</code> <code class="html plain">for="id_is_married">Is married:</</code><code class="html keyword">label</code><code class="html plain">> <</code><code class="html keyword">input</code> <code class="html plain">id="id_is_married" name="is_married" type="checkbox"></code></div><div class="line number26 index25 alt1"><code class="html spaces"> </code><code class="html plain"></</code><code class="html keyword">p</code><code class="html plain">></code></div><div class="line number27 index26 alt2"> </div><div class="line number28 index27 alt1"> </div><div class="line number29 index28 alt2"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">input</code> <code class="html plain">type="submit" value="注册"></code></div><div class="line number30 index29 alt1"><code class="html plain"></</code><code class="html keyword">form</code><code class="html plain">></code></div></div></td></tr></tbody></table></div></div> </div> <h2 class="line" data-line="338">手工渲染字段</h2> <p>我们没有必要非要让Django 来分拆表单的字段;如果我们喜欢,我们可以手工来做(例如,这样允许重新对字段排序)。每个字段都是表单的一个属性,可以使用<code>{{ form.name_of_field }}</code> 访问,并将在Django 模板中正确地渲染。例如:</p> <div class="cnblogs_Highlighter sh-gutter"> <div><div class="syntaxhighlighter html" id="highlighter_231606"><div class="toolbar"><span><a class="toolbar_item command_help help" href="#">?</a></span></div><table border="0" cellspacing="0" cellpadding="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="html plain"><</code><code class="html keyword">div</code> <code class="html plain">class="fieldWrapper"></code></div><div class="line number2 index1 alt1"><code class="html spaces"> </code><code class="html plain">{{ form.Username.errors }}</code></div><div class="line number3 index2 alt2"><code class="html spaces"> </code><code class="html plain">{{ form.Username.label_tag }}</code></div><div class="line number4 index3 alt1"><code class="html spaces"> </code><code class="html plain">{{ form.Username }}</code></div><div class="line number5 index4 alt2"><code class="html plain"></</code><code class="html keyword">div</code><code class="html plain">></code></div></div></td></tr></tbody></table></div></div> </div> <h2 class="line" data-line="376">渲染表单的错误信息</h2> <p>1、</p> <div class="cnblogs_Highlighter sh-gutter"> <div><div class="syntaxhighlighter html" id="highlighter_535022"><div class="toolbar"><span><a class="toolbar_item command_help help" href="#">?</a></span></div><table border="0" cellspacing="0" cellpadding="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="html plain">registerForm=RegisterForm(request.POST)</code></div><div class="line number2 index1 alt1"><code class="html plain">print(type(registerForm.errors)) #<</code><code class="html keyword">class</code> <code class="html plain">'django.forms.utils.ErrorDict'></code></div><div class="line number3 index2 alt2"><code class="html plain">print(type(registerForm.errors["username"])) #<</code><code class="html keyword">class</code> <code class="html plain">'django.forms.utils.ErrorList'> </code></div></div></td></tr></tbody></table></div></div> </div> <p>2、</p> <p>使用<code>{{ form.name_of_field.errors }}</code> 显示表单错误的一个清单,并渲染成一个<code>ul</code>。看上去可能像:</p> <div class="cnblogs_Highlighter sh-gutter"> <div><div class="syntaxhighlighter html" id="highlighter_687222"><div class="toolbar"><span><a class="toolbar_item command_help help" href="#">?</a></span></div><table border="0" cellspacing="0" cellpadding="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="html plain"><</code><code class="html keyword">ul</code> <code class="html plain">class="errorlist"></code></div><div class="line number2 index1 alt1"><code class="html spaces"> </code><code class="html plain"><</code><code class="html keyword">li</code><code class="html plain">>Sender is required.</</code><code class="html keyword">li</code><code class="html plain">></code></div><div class="line number3 index2 alt2"><code class="html plain"></</code><code class="html keyword">ul</code><code class="html plain">></code></div></div></td></tr></tbody></table></div></div> </div> <h2> form组件的钩子</h2> <div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="//common.cnblogs.com/images/copycode.gif"></a></span></div> <pre><span style="color: #0000ff;">def</span><span style="color: #000000;"> foo(request): </span><span style="color: #0000ff;">if</span> request.method==<span style="color: #800000;">"</span><span style="color: #800000;">POST</span><span style="color: #800000;">"</span><span style="color: #000000;">: regForm</span>=<span style="color: #000000;">RegForm(request.POST) </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> regForm.is_valid(): </span><span style="color: #0000ff;">pass</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 可用数据: regForm.cleaned_data,</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 将数据插入数据库表中</span> <span style="color: #0000ff;">else</span><span style="color: #000000;">: </span><span style="color: #0000ff;">pass</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 可用数据: regForm.errors</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 可以利用模板渲染讲errors嵌套到页面中返回</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 也可以打包到一个字典中,用于ajax返回</span> <span style="color: #0000ff;">else</span><span style="color: #000000;">: regForm</span>=<span style="color: #000000;">RegForm() </span><span style="color: #0000ff;">return</span> render(request,<span style="color: #800000;">"</span><span style="color: #800000;">register.html</span><span style="color: #800000;">"</span>,{<span style="color: #800000;">"</span><span style="color: #800000;">regForm</span><span style="color: #800000;">"</span><span style="color: #000000;">:regForm}) </span><span style="color: #800000;">'''</span><span style="color: #800000;"> 实例化时: self.fields={ "username":"字段规则对象", "password":"字段规则对象", } is_valid时: self._errors = {} self.cleaned_data = {} #局部钩子: for name, field in self.fields.items(): try: value = field.clean(value) self.cleaned_data[name] = value if hasattr(self, 'clean_%s' % name): value = getattr(self, 'clean_%s' % name)() self.cleaned_data[name] = value except ValidationError as e: self.add_error(name, e) # 全局钩子: self.clean() # def self.clean():return self.cleaned_data return not self.errors # True或者False </span><span style="color: #800000;">'''</span></pre> <div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="//common.cnblogs.com/images/copycode.gif"></a></span></div></div> <h2>form组件补充</h2> <p>1、Django内置字段如下:</p> <div class="cnblogs_code" onclick="cnblogs_code_show('03f6260b-58a8-4a1f-be56-ddff2bb0543a')"><img class="code_img_closed" id="code_img_closed_03f6260b-58a8-4a1f-be56-ddff2bb0543a" alt="" src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img class="code_img_opened" id="code_img_opened_03f6260b-58a8-4a1f-be56-ddff2bb0543a" style="display: none;" onclick="cnblogs_code_hide('03f6260b-58a8-4a1f-be56-ddff2bb0543a',event)" alt="" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"> <div class="cnblogs_code_hide" id="cnblogs_code_open_03f6260b-58a8-4a1f-be56-ddff2bb0543a"> <pre><span style="color: #000000;">Field required</span>=<span style="color: #000000;">True, 是否允许为空 widget</span>=<span style="color: #000000;">None, HTML插件 label</span>=<span style="color: #000000;">None, 用于生成Label标签或显示内容 initial</span>=<span style="color: #000000;">None, 初始值 help_text</span>=<span style="color: #800000;">''</span><span style="color: #000000;">, 帮助信息(在标签旁边显示) error_messages</span>=None, 错误信息 {<span style="color: #800000;">'</span><span style="color: #800000;">required</span><span style="color: #800000;">'</span>: <span style="color: #800000;">'</span><span style="color: #800000;">不能为空</span><span style="color: #800000;">'</span>, <span style="color: #800000;">'</span><span style="color: #800000;">invalid</span><span style="color: #800000;">'</span>: <span style="color: #800000;">'</span><span style="color: #800000;">格式错误</span><span style="color: #800000;">'</span><span style="color: #000000;">} show_hidden_initial</span>=<span style="color: #000000;">False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直) validators</span>=<span style="color: #000000;">[], 自定义验证规则 localize</span>=<span style="color: #000000;">False, 是否支持本地化 disabled</span>=<span style="color: #000000;">False, 是否可以编辑 label_suffix</span>=<span style="color: #000000;">None Label内容后缀 CharField(Field) max_length</span>=<span style="color: #000000;">None, 最大长度 min_length</span>=<span style="color: #000000;">None, 最小长度 strip</span>=<span style="color: #000000;">True 是否移除用户输入空白 IntegerField(Field) max_value</span>=<span style="color: #000000;">None, 最大值 min_value</span>=<span style="color: #000000;">None, 最小值 FloatField(IntegerField) ... DecimalField(IntegerField) max_value</span>=<span style="color: #000000;">None, 最大值 min_value</span>=<span style="color: #000000;">None, 最小值 max_digits</span>=<span style="color: #000000;">None, 总长度 decimal_places</span>=<span style="color: #000000;">None, 小数位长度 BaseTemporalField(Field) input_formats</span>=<span style="color: #000000;">None 时间格式化 DateField(BaseTemporalField) 格式:</span>2015-09-01<span style="color: #000000;"> TimeField(BaseTemporalField) 格式:</span>11:12<span style="color: #000000;"> DateTimeField(BaseTemporalField)格式:</span>2015-09-01 11:12<span style="color: #000000;"> DurationField(Field) 时间间隔:</span>%d %H:%M:%S.%<span style="color: #000000;">f ... RegexField(CharField) regex, 自定制正则表达式 max_length</span>=<span style="color: #000000;">None, 最大长度 min_length</span>=<span style="color: #000000;">None, 最小长度 error_message</span>=None, 忽略,错误信息使用 error_messages={<span style="color: #800000;">'</span><span style="color: #800000;">invalid</span><span style="color: #800000;">'</span>: <span style="color: #800000;">'</span><span style="color: #800000;">...</span><span style="color: #800000;">'</span><span style="color: #000000;">} EmailField(CharField) ... FileField(Field) allow_empty_file</span>=<span style="color: #000000;">False 是否允许空文件 ImageField(FileField) ... 注:需要PIL模块,pip3 install Pillow 以上两个字典使用时,需要注意两点: </span>- form表单中 enctype=<span style="color: #800000;">"</span><span style="color: #800000;">multipart/form-data</span><span style="color: #800000;">"</span> - view函数中 obj =<span style="color: #000000;"> MyForm(request.POST, request.FILES) URLField(Field) ... BooleanField(Field) ... NullBooleanField(BooleanField) ... ChoiceField(Field) ... choices</span>=(), 选项,如:choices = ((0,<span style="color: #800000;">'</span><span style="color: #800000;">上海</span><span style="color: #800000;">'</span>),(1,<span style="color: #800000;">'</span><span style="color: #800000;">北京</span><span style="color: #800000;">'</span><span style="color: #000000;">),) required</span>=<span style="color: #000000;">True, 是否必填 widget</span>=<span style="color: #000000;">None, 插件,默认select插件 label</span>=<span style="color: #000000;">None, Label内容 initial</span>=<span style="color: #000000;">None, 初始值 help_text</span>=<span style="color: #800000;">''</span><span style="color: #000000;">, 帮助提示 ModelChoiceField(ChoiceField) ... django.forms.models.ModelChoiceField queryset, </span><span style="color: #008000;">#</span><span style="color: #008000;"> 查询数据库中的数据</span> empty_label=<span style="color: #800000;">"</span><span style="color: #800000;">---------</span><span style="color: #800000;">"</span>, <span style="color: #008000;">#</span><span style="color: #008000;"> 默认空显示内容</span> to_field_name=None, <span style="color: #008000;">#</span><span style="color: #008000;"> HTML中value的值对应的字段</span> limit_choices_to=None <span style="color: #008000;">#</span><span style="color: #008000;"> ModelForm中对queryset二次筛选</span> <span style="color: #000000;"> ModelMultipleChoiceField(ModelChoiceField) ... django.forms.models.ModelMultipleChoiceField TypedChoiceField(ChoiceField) coerce </span>= <span style="color: #0000ff;">lambda</span><span style="color: #000000;"> val: val 对选中的值进行一次转换 empty_value</span>= <span style="color: #800000;">''</span><span style="color: #000000;"> 空值的默认值 MultipleChoiceField(ChoiceField) ... TypedMultipleChoiceField(MultipleChoiceField) coerce </span>= <span style="color: #0000ff;">lambda</span><span style="color: #000000;"> val: val 对选中的每一个值进行一次转换 empty_value</span>= <span style="color: #800000;">''</span><span style="color: #000000;"> 空值的默认值 ComboField(Field) fields</span>=<span style="color: #000000;">() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式 fields.ComboField(fields</span>=[fields.CharField(max_length=20<span style="color: #000000;">), fields.EmailField(),]) MultiValueField(Field) PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用 SplitDateTimeField(MultiValueField) input_date_formats</span>=None, 格式列表:[<span style="color: #800000;">'</span><span style="color: #800000;">%Y--%m--%d</span><span style="color: #800000;">'</span>, <span style="color: #800000;">'</span><span style="color: #800000;">%m%d/%Y</span><span style="color: #800000;">'</span>, <span style="color: #800000;">'</span><span style="color: #800000;">%m/%d/%y</span><span style="color: #800000;">'</span><span style="color: #000000;">] input_time_formats</span>=None 格式列表:[<span style="color: #800000;">'</span><span style="color: #800000;">%H:%M:%S</span><span style="color: #800000;">'</span>, <span style="color: #800000;">'</span><span style="color: #800000;">%H:%M:%S.%f</span><span style="color: #800000;">'</span>, <span style="color: #800000;">'</span><span style="color: #800000;">%H:%M</span><span style="color: #800000;">'</span><span style="color: #000000;">] FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中 path, 文件夹路径 match</span>=<span style="color: #000000;">None, 正则匹配 recursive</span>=<span style="color: #000000;">False, 递归下面的文件夹 allow_files</span>=<span style="color: #000000;">True, 允许文件 allow_folders</span>=<span style="color: #000000;">False, 允许文件夹 required</span>=<span style="color: #000000;">True, widget</span>=<span style="color: #000000;">None, label</span>=<span style="color: #000000;">None, initial</span>=<span style="color: #000000;">None, help_text</span>=<span style="color: #800000;">''</span><span style="color: #000000;"> GenericIPAddressField protocol</span>=<span style="color: #800000;">'</span><span style="color: #800000;">both</span><span style="color: #800000;">'</span><span style="color: #000000;">, both,ipv4,ipv6支持的IP格式 unpack_ipv4</span>=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1<span style="color: #000000;">, PS:protocol必须为both才能启用 SlugField(CharField) 数字,字母,下划线,减号(连字符) ... UUIDField(CharField) uuid类型 ...</span></pre> </div> <span class="cnblogs_code_collapse">View Code</span></div> <p>2、Django内置插件:</p> <div class="cnblogs_code" onclick="cnblogs_code_show('fe202540-9e3b-4ffa-9335-fcf89fa760c2')"><img class="code_img_closed" id="code_img_closed_fe202540-9e3b-4ffa-9335-fcf89fa760c2" alt="" src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img class="code_img_opened" id="code_img_opened_fe202540-9e3b-4ffa-9335-fcf89fa760c2" style="display: none;" onclick="cnblogs_code_hide('fe202540-9e3b-4ffa-9335-fcf89fa760c2',event)" alt="" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"> <div class="cnblogs_code_hide" id="cnblogs_code_open_fe202540-9e3b-4ffa-9335-fcf89fa760c2"> <pre><span style="color: #000000;">TextInput(Input) NumberInput(TextInput) EmailInput(TextInput) URLInput(TextInput) PasswordInput(TextInput) HiddenInput(TextInput) Textarea(Widget) DateInput(DateTimeBaseInput) DateTimeInput(DateTimeBaseInput) TimeInput(DateTimeBaseInput) CheckboxInput Select NullBooleanSelect SelectMultiple RadioSelect CheckboxSelectMultiple FileInput ClearableFileInput MultipleHiddenInput SplitDateTimeWidget SplitHiddenDateTimeWidget SelectDateWidget</span></pre> </div> <span class="cnblogs_code_collapse">View Code</span></div> <p>3、常用选择插件:</p> <div class="cnblogs_code" onclick="cnblogs_code_show('ddb30a2f-9f6c-4e6e-ad55-e19ea2b5baa8')"><img class="code_img_closed" id="code_img_closed_ddb30a2f-9f6c-4e6e-ad55-e19ea2b5baa8" alt="" src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img class="code_img_opened" id="code_img_opened_ddb30a2f-9f6c-4e6e-ad55-e19ea2b5baa8" style="display: none;" onclick="cnblogs_code_hide('ddb30a2f-9f6c-4e6e-ad55-e19ea2b5baa8',event)" alt="" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"> <div class="cnblogs_code_hide" id="cnblogs_code_open_ddb30a2f-9f6c-4e6e-ad55-e19ea2b5baa8"> <pre><span style="color: #008000;">#</span><span style="color: #008000;"> 单radio,值为字符串</span><span style="color: #008000;"> #</span><span style="color: #008000;"> user = fields.CharField(</span><span style="color: #008000;"> #</span><span style="color: #008000;"> initial=2,</span><span style="color: #008000;"> #</span><span style="color: #008000;"> widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))</span><span style="color: #008000;"> #</span><span style="color: #008000;"> )</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 单radio,值为字符串</span><span style="color: #008000;"> #</span><span style="color: #008000;"> user = fields.ChoiceField(</span><span style="color: #008000;"> #</span><span style="color: #008000;"> choices=((1, '上海'), (2, '北京'),),</span><span style="color: #008000;"> #</span><span style="color: #008000;"> initial=2,</span><span style="color: #008000;"> #</span><span style="color: #008000;"> widget=widgets.RadioSelect</span><span style="color: #008000;"> #</span><span style="color: #008000;"> )</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 单select,值为字符串</span><span style="color: #008000;"> #</span><span style="color: #008000;"> user = fields.CharField(</span><span style="color: #008000;"> #</span><span style="color: #008000;"> initial=2,</span><span style="color: #008000;"> #</span><span style="color: #008000;"> widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))</span><span style="color: #008000;"> #</span><span style="color: #008000;"> )</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 单select,值为字符串</span><span style="color: #008000;"> #</span><span style="color: #008000;"> user = fields.ChoiceField(</span><span style="color: #008000;"> #</span><span style="color: #008000;"> choices=((1, '上海'), (2, '北京'),),</span><span style="color: #008000;"> #</span><span style="color: #008000;"> initial=2,</span><span style="color: #008000;"> #</span><span style="color: #008000;"> widget=widgets.Select</span><span style="color: #008000;"> #</span><span style="color: #008000;"> )</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 多选select,值为列表</span><span style="color: #008000;"> #</span><span style="color: #008000;"> user = fields.MultipleChoiceField(</span><span style="color: #008000;"> #</span><span style="color: #008000;"> choices=((1,'上海'),(2,'北京'),),</span><span style="color: #008000;"> #</span><span style="color: #008000;"> initial=[1,],</span><span style="color: #008000;"> #</span><span style="color: #008000;"> widget=widgets.SelectMultiple</span><span style="color: #008000;"> #</span><span style="color: #008000;"> )</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 单checkbox</span><span style="color: #008000;"> #</span><span style="color: #008000;"> user = fields.CharField(</span><span style="color: #008000;"> #</span><span style="color: #008000;"> widget=widgets.CheckboxInput()</span><span style="color: #008000;"> #</span><span style="color: #008000;"> )</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 多选checkbox,值为列表</span><span style="color: #008000;"> #</span><span style="color: #008000;"> user = fields.MultipleChoiceField(</span><span style="color: #008000;"> #</span><span style="color: #008000;"> initial=[2, ],</span><span style="color: #008000;"> #</span><span style="color: #008000;"> choices=((1, '上海'), (2, '北京'),),</span><span style="color: #008000;"> #</span><span style="color: #008000;"> widget=widgets.CheckboxSelectMultiple</span><span style="color: #008000;"> #</span><span style="color: #008000;"> )</span></pre> </div> <span class="cnblogs_code_collapse">View Code</span></div> <p><a href="https://www.cnblogs.com/wupeiqi/articles/6144178.html" target="_blank">引入</a></p></div><div id="MySignature"></div> <div class="clear"></div> <div id="blog_post_info_block"> <div id="BlogPostCategory">分类: <a href="http://www.cnblogs.com/yuanchenqi/category/1050267.html" target="_blank">Django系列学习</a></div> <div id="EntryTag"></div> <div id="blog_post_info"><div id="green_channel"> <a id="green_channel_digg" onclick="DiggIt(7614921,cb_blogId,1);green_channel_success(this,'谢谢推荐!');" href="javascript:void(0);">好文要顶</a> <a id="green_channel_follow" onclick="follow('6d0ad0ce-3cb7-e511-9fc1-ac853d9f53cc');" href="javascript:void(0);">关注我</a> <a id="green_channel_favorite" onclick="AddToWz(cb_entryId);return false;" href="javascript:void(0);">收藏该文</a> <a title="分享至新浪微博" id="green_channel_weibo" onclick="ShareToTsina()" href="javascript:void(0);"><img alt="" src="//common.cnblogs.com/images/icon_weibo_24.png"></a> <a title="分享至微信" id="green_channel_wechat" onclick="shareOnWechat()" href="javascript:void(0);"><img alt="" src="//common.cnblogs.com/images/wechat.png"></a> </div> <div id="author_profile"> <div class="author_profile_info" id="author_profile_info"> <a href="http://home.cnblogs.com/u/yuanchenqi/" target="_blank"><img class="author_avatar" alt="" src="//pic.cnblogs.com/face/877318/20160110101629.png"></a> <div class="author_profile_info" id="author_profile_detail"> <a href="http://home.cnblogs.com/u/yuanchenqi/">Yuan先生</a><br> <a href="http://home.cnblogs.com/u/yuanchenqi/followees">关注 - 0</a><br> <a href="http://home.cnblogs.com/u/yuanchenqi/followers">粉丝 - 563</a> </div> </div> <div class="clear"></div> <div id="author_profile_honor"></div> <div id="author_profile_follow"> <a onclick="follow('6d0ad0ce-3cb7-e511-9fc1-ac853d9f53cc');return false;" href="javascript:void(0);">+加关注</a> </div> </div> <div id="div_digg"> <div class="diggit" onclick="votePost(7614921,'Digg')"> <span class="diggnum" id="digg_count">0</span> </div> <div class="buryit" onclick="votePost(7614921,'Bury')"> <span class="burynum" id="bury_count">0</span> </div> <div class="clear"></div> <div class="diggword" id="digg_tips"> </div> </div> </div> <div class="clear"></div> <div id="post_next_prev"><a class="p_n_p_prefix" href="http://www.cnblogs.com/yuanchenqi/articles/7609586.html">« </a> 上一篇:<a title="发布于2017-09-29 09:39" href="http://www.cnblogs.com/yuanchenqi/articles/7609586.html">Django-认证系统</a><br><a class="p_n_p_prefix" href="http://www.cnblogs.com/yuanchenqi/articles/7617280.html">» </a> 下一篇:<a title="发布于2017-10-01 15:45" href="http://www.cnblogs.com/yuanchenqi/articles/7617280.html">爬虫基础库</a><br></div> </div> </div> <div class="postDesc">posted @ <span id="post-date">2017-09-30 14:38</span> <a href="http://www.cnblogs.com/yuanchenqi/">Yuan先生</a> 阅读(<span id="post_view_count">268</span>) 评论(<span id="post_comment_count">0</span>) <a href="https://i.cnblogs.com/EditArticles.aspx?postid=7614921" rel="nofollow">编辑</a> <a onclick="AddToWz(7614921);return false;" href="#">收藏</a></div> </div> <script type="text/javascript">var allowComments=true,cb_blogId=262677,cb_entryId=7614921,cb_blogApp=currentBlogApp,cb_blogUserGuid='6d0ad0ce-3cb7-e511-9fc1-ac853d9f53cc',cb_entryCreatedDate='2017/9/30 14:38:00';loadViewCount(cb_entryId);var cb_postType=2;</script> </div><!--end: topics 文章、评论容器--> </div><a name="!comments"></a><div id="blog-comments-placeholder"></div><script type="text/javascript">var commentManager = new blogCommentManager();commentManager.renderComments(0);</script> <div class="commentform" id="comment_form"> <a name="commentform"></a> <div id="divCommentShow"></div> <div id="comment_nav"><span id="span_refresh_tips"></span><a id="lnk_RefreshComments" onclick="return RefreshCommentList();" href="javascript:void(0);" clientidmode="Static" runat="server">刷新评论</a><a onclick="return RefreshPage();" href="#">刷新页面</a><a href="#top">返回顶部</a></div> <div id="comment_form_container"> <div id="commentform_title">发表评论</div> <span id="tip_comment" style="color:Red"></span> <p> 昵称:<input disabled="disabled" class="author" id="tbCommentAuthor" type="text" size="50" value="jing_1"> </p> <div class="commentbox_main"> <div class="commentbox_title"> <div class="commentbox_title_left">评论内容:</div> <div class="commentbox_title_right"> <img title="添加引用" class="comment_icon" id="ubb_quote" onclick="insertUBB('tbCommentBody','quote')" alt="引用" src="http://static.cnblogs.com/images/ubb/quote.gif"> <img title="添加粗体" class="comment_icon" id="ubb_bold" onclick="insertUBB('tbCommentBody','b')" alt="粗体" src="http://static.cnblogs.com/images/ubb/b.png"> <img title="添加链接" class="comment_icon" id="ubb_url" onclick="insertUbbUrl('tbCommentBody')" alt="链接" src="http://static.cnblogs.com/images/ubb/lk.png"> <img title="添加首行缩进" class="comment_icon" id="ubb_indent" onclick="insertIndent('tbCommentBody')" alt="缩进" src="http://static.cnblogs.com/images/ubb/indent.png"> <img title="添加代码" class="comment_icon" id="ubb_code" onclick="insertUbbCode()" alt="代码" src="http://static.cnblogs.com/images/ubb/InsertCode.gif"> <img title="上传图片" class="comment_icon" id="ubb_img" onclick="OpenImageUploadWindow();" alt="图片" src="http://static.cnblogs.com/images/ubb/img.gif"> </div> </div> <div class="clear"></div> <textarea class="comment_textarea" id="tbCommentBody"></textarea> </div> <p id="commentbox_opt"> <input class="comment_btn" id="btn_comment_submit" type="button" value="提交评论"> <span id="span_comment_canceledit" style="display:none"><a onclick="return CancelCommentEdit()" href="javascript:void(0);">不改了</a></span> <a onclick="return logout();" href="javascript:void(0);">退出</a> <a title="订阅后有新评论时会邮件通知您" id="commentbox_opt_sub" onclick="commentManager.Subscribe()" href="javascript:void(0);">订阅评论</a> </p> <div id="tip_comment2" style="color:Red"></div> <p> [Ctrl+Enter快捷键提交] </p> <div style="display:none"> <span id="comment_edit_id"></span><span id="span_parentcomment_id"></span> <span id="span_parent_id"></span> <span id="span_comment_replyto"></span> <span id="span_comment_posted"></span> </div> </div> <div class="ad_text_commentbox" id="ad_text_under_commentbox"></div> <div id="ad_t2"><a href="http://www.ucancode.com/index.htm" target="_blank">【推荐】50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库</a><br><a href="https://cloud.tencent.com/developer/labs?fromSource=gwzcw.632116.632116.632116" target="_blank">【推荐】腾讯云免费实验室,1小时搭建人工智能应用</a><br><a href="https://news.cnblogs.com/n/582971/" target="_blank">【新闻】H3 BPM体验平台全面上线</a><br></div> <div id="opt_under_post"></div> <div class="c_ad_block" id="cnblogs_c1"><a href="http://www.gcpowertools.com.cn/products/activereports_overview.htm?utm_source=cnblogs&utm_medium=blogpage&utm_term=bottom&utm_content=AR&utm_campaign=community" target="_blank"><img width="300" height="250" alt="AR_1206" src="https://images2017.cnblogs.com/news/24442/201712/24442-20171206093739878-889349568.png"></a></div> <div id="under_post_news"><div class="itnews c_ad_block"><b>最新IT新闻</b>:<br> · <a href="https://news.cnblogs.com/n/584313/" target="_blank">伯克利最新发明机器人:他叫Vestri,他能“看见”未来</a><br> · <a href="https://news.cnblogs.com/n/584321/" target="_blank">因价格多变、交易费奇高:Steam叫停比特币支付</a><br> · <a href="https://news.cnblogs.com/n/584326/" target="_blank">吃胖算我输 华人学者今日带来减肥新思路</a><br> · <a href="https://news.cnblogs.com/n/584324/" target="_blank">大众高管因排放门而被判处七年监禁和40万美元罚款</a><br> · <a href="https://news.cnblogs.com/n/584325/" target="_blank">中国电信升级阿里鱼卡:四款APP加入免流 1元1GB全国流量</a><br>» <a title="IT新闻" href="http://news.cnblogs.com/" target="_blank">更多新闻...</a></div></div> <div class="c_ad_block" id="cnblogs_c2"><a href="http://click.aliyun.com/m/34771/" target="_blank"><img width="468" height="60" alt="阿里云1113" src="https://images2017.cnblogs.com/news/24442/201711/24442-20171113120112796-634832761.jpg"></a></div> <div id="under_post_kb"><div class="itnews c_ad_block" id="kb_block"><b>最新知识库文章</b>:<br><div id="kb_recent"> · <a href="http://kb.cnblogs.com/page/531409/" target="_blank">以操作系统的角度述说线程与进程</a><br> · <a href="http://kb.cnblogs.com/page/141729/" target="_blank">软件测试转型之路</a><br> · <a href="http://kb.cnblogs.com/page/177402/" target="_blank">门内门外看招聘</a><br> · <a href="http://kb.cnblogs.com/page/112506/" target="_blank">大道至简,职场上做人做事做管理</a><br> · <a href="http://kb.cnblogs.com/page/563790/" target="_blank">关于编程,你的练习是不是有效的?</a><br></div>» <a href="http://kb.cnblogs.com/" target="_blank">更多知识库文章...</a></div></div> <div class="c_ad_block" id="HistoryToday"></div> <script type="text/javascript"> fixPostBody(); setTimeout(function () { incrementViewCount(cb_entryId); }, 50); deliverAdT2(); deliverAdC1(); deliverAdC2(); loadNewsAndKb(); loadBlogSignature(); LoadPostInfoBlock(cb_blogId, cb_entryId, cb_blogApp, cb_blogUserGuid); GetPrevNextPost(cb_entryId, cb_blogId, cb_entryCreatedDate, cb_postType); loadOptUnderPost(); GetHistoryToday(cb_blogId, cb_blogApp, cb_entryCreatedDate); </script> </div> </div><!--end: forFlow --> </div><!--end: mainContent 主体内容容器--> <div id="sideBar"> <div id="sideBarMain"> <!--done--> <div class="newsItem"> <h3 class="catListTitle">公告</h3> <div id="blog-news"><div id="profile_block">昵称:<a href="http://home.cnblogs.com/u/yuanchenqi/">Yuan先生</a><br>园龄:<a title="入园时间:2016-01-10" href="http://home.cnblogs.com/u/yuanchenqi/">1年10个月</a><br>粉丝:<a href="http://home.cnblogs.com/u/yuanchenqi/followers/">563</a><br>关注:<a href="http://home.cnblogs.com/u/yuanchenqi/followees/">0</a><div id="p_b_follow"><a onclick="follow('6d0ad0ce-3cb7-e511-9fc1-ac853d9f53cc')" href="javascript:void(0);">+加关注</a></div></div></div><script type="text/javascript">loadBlogNews();</script> </div> <div id="blog-calendar"><table title="Calendar" class="Cal" id="blogCalendar" cellspacing="0" cellpadding="0"> <tbody><tr><td colspan="7"><table class="CalTitle" cellspacing="0"> <tbody><tr><td class="CalNextPrev"><a onclick="loadBlogCalendar('2017/11/01');return false;" href="javascript:void(0);"><</a></td><td align="center">2017年12月</td><td align="right" class="CalNextPrev"><a onclick="loadBlogCalendar('2018/01/01');return false;" href="javascript:void(0);">></a></td></tr> </tbody></table></td></tr><tr><th align="center" class="CalDayHeader" abbr="日" scope="col">日</th><th align="center" class="CalDayHeader" abbr="一" scope="col">一</th><th align="center" class="CalDayHeader" abbr="二" scope="col">二</th><th align="center" class="CalDayHeader" abbr="三" scope="col">三</th><th align="center" class="CalDayHeader" abbr="四" scope="col">四</th><th align="center" class="CalDayHeader" abbr="五" scope="col">五</th><th align="center" class="CalDayHeader" abbr="六" scope="col">六</th></tr><tr><td align="center" class="CalOtherMonthDay">26</td><td align="center" class="CalOtherMonthDay">27</td><td align="center" class="CalOtherMonthDay">28</td><td align="center" class="CalOtherMonthDay">29</td><td align="center" class="CalOtherMonthDay">30</td><td align="center">1</td><td align="center" class="CalWeekendDay">2</td></tr><tr><td align="center" class="CalWeekendDay">3</td><td align="center">4</td><td align="center">5</td><td align="center">6</td><td align="center" class="CalTodayDay">7</td><td align="center">8</td><td align="center" class="CalWeekendDay">9</td></tr><tr><td align="center" class="CalWeekendDay">10</td><td align="center">11</td><td align="center">12</td><td align="center">13</td><td align="center">14</td><td align="center">15</td><td align="center" class="CalWeekendDay">16</td></tr><tr><td align="center" class="CalWeekendDay">17</td><td align="center">18</td><td align="center">19</td><td align="center">20</td><td align="center">21</td><td align="center">22</td><td align="center" class="CalWeekendDay">23</td></tr><tr><td align="center" class="CalWeekendDay">24</td><td align="center">25</td><td align="center">26</td><td align="center">27</td><td align="center">28</td><td align="center">29</td><td align="center" class="CalWeekendDay">30</td></tr><tr><td align="center" class="CalWeekendDay">31</td><td align="center" class="CalOtherMonthDay">1</td><td align="center" class="CalOtherMonthDay">2</td><td align="center" class="CalOtherMonthDay">3</td><td align="center" class="CalOtherMonthDay">4</td><td align="center" class="CalOtherMonthDay">5</td><td align="center" class="CalOtherMonthDay">6</td></tr> </tbody></table></div><script type="text/javascript">loadBlogDefaultCalendar();</script> <div id="leftcontentcontainer"> <div id="blog-sidecolumn"><div class="sidebar-block" id="sidebar_search"></div><div class="sidebar-block" id="sidebar_toptags"></div><div id="sidebar_categories"> <div class="catListPostArchive sidebar-block" id="sidebar_postarchive"> <h3 class="catListTitle">随笔档案</h3> <ul> <li><a id="CatList_LinkList_0_Link_0" href="http://www.cnblogs.com/yuanchenqi/archive/2017/01.html">2017年1月 (1)</a> </li> </ul> </div> </div><div class="sidebar-block" id="sidebar_recentcomments"><div id="recent_comments_wrap"> <div class="catListComment"> <h3 class="catListTitle">最新评论</h3> <div id="RecentCommentsBlock"><ul> <li class="recent_comment_title"><a href="http://www.cnblogs.com/yuanchenqi/articles/7638956.html#3858991">1. Re:Django-Ajax</a></li> <li class="recent_comment_body">mark</li> <li class="recent_comment_author">--0bug</li> <li class="recent_comment_title"><a href="http://www.cnblogs.com/yuanchenqi/articles/7652353.html#3856516">2. Re:Django-进阶</a></li> <li class="recent_comment_body">中间件讲的条理很清晰,看着很顺</li> <li class="recent_comment_author">--竹先森</li> <li class="recent_comment_title"><a href="http://www.cnblogs.com/yuanchenqi/articles/6835654.html#3856063">3. Re:前端基础之html</a></li> <li class="recent_comment_body">签到学习</li> <li class="recent_comment_author">--武陵郡龙氏</li> <li class="recent_comment_title"><a href="http://www.cnblogs.com/yuanchenqi/articles/5733873.html#3851678">4. Re:Py西游攻关之多线程(threading模块)</a></li> <li class="recent_comment_body">五 条件变量同步(Condition) 我把consumer线程放在了列表第一个 就能显示ok了 在wait前面再加上一句print('xxx') 测试 会发现无论如何都会第一个显示 xxx 这是........</li> <li class="recent_comment_author">--西木野挖掘姬</li> <li class="recent_comment_title"><a href="http://www.cnblogs.com/yuanchenqi/articles/7690561.html#3851670">5. Re:web框架</a></li> <li class="recent_comment_body">测试一</li> <li class="recent_comment_author">--Aqq_1314</li> </ul> </div> </div> </div></div><div class="sidebar-block" id="sidebar_topviewedposts"><div id="topview_posts_wrap"> <div class="catListView"> <h3 class="catListTitle">阅读排行榜</h3> <div id="TopViewPostsBlock"><ul><li><a href="http://www.cnblogs.com/yuanchenqi/p/6337663.html">1. 操作系统核心简介(1857)</a></li></ul></div> </div> </div></div><div class="sidebar-block" id="sidebar_topcommentedposts"><div id="topfeedback_posts_wrap"> <div class="catListFeedback"> <h3 class="catListTitle">评论排行榜</h3> <div id="TopFeedbackPostsBlock"><ul><li><a href="http://www.cnblogs.com/yuanchenqi/p/6337663.html">1. 操作系统核心简介(3)</a></li></ul></div> </div> </div></div><div class="sidebar-block" id="sidebar_topdiggedposts"><div id="topdigg_posts_wrap" style="display: none;"> <div class="catListView"> <h3 class="catListTitle">推荐排行榜</h3> <div id="TopDiggPostsBlock"></div> </div></div></div></div><script type="text/javascript">loadBlogSideColumn();</script> </div> </div><!--end: sideBarMain --> </div><!--end: sideBar 侧边栏容器 --> <div class="clear"></div> </div><!--end: main --> <div class="clear"></div> <div id="footer"> <!--done--> Copyright ©2017 Yuan先生 </div><!--end: footer --> </div><!--end: home 自定义的最大容器 --> <!--PageEndHtml Block Begin--> <script language="javascript" type="text/javascript"> //生成目录索引列表 function GenerateContentList() { var jquery_h1_list = $('#cnblogs_post_body h1').not('.catListTitle').not('#blogTitle h1');//如果你的章节标题不是h4,只需要将这里的h4换掉即可 if(jquery_h1_list.length>0) { var content = '<a name="_labelTop"></a>'; content += '<div id="navCategory">'; content += '<p style="font-size:25px;color:#EE1289;"><i>知识预览</i></p>'; content += '<ul id="sortChapter">'; for(var i =0;i<jquery_h1_list.length;i++) { var go_to_top = '<div style="text-align: right"><a href="#_labelTop">回到顶部</a><a name="_label' + i + '"></a></div>'; $(jquery_h1_list[i]).before(go_to_top); var li_content = '<li><a href="#_label' + i + '"style="color: #003366;text-decoration:none;font-size:18px">' + $(jquery_h1_list[i]).text() + '</a></li>'; content += li_content; } content += '</ul>'; content += '</div>'; if($('#cnblogs_post_body').length != 0 ) { $($('#cnblogs_post_body')[0]).prepend(content); } } } GenerateContentList(); </script> <!--PageEndHtml Block End--> </body>