今日概要:javascript
一、bootstrap使用php
二、柵格系統css
三、orm簡介html
四、路由系統前端
五、mvc和mtv模式java
六、django框架python
一、Bootstrap 專門構建了免費的 CDN 加速服務,訪問速度更快、加速效果更明顯、沒有速度和帶寬限制、永久免費 mysql
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- 可選的 Bootstrap 主題文件(通常不用引入) --> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> <script type="application/javascript" src="bootstrap-3.3.7-dist/jquery-3.1.1.js"></script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <title>Bootstrap-demo</title> </head> <body> <div class="container"> <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar" aria-expanded="true" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Bootstrap theme</a> </div> <div id="navbar" class="navbar-collapse collapse in" aria-expanded="true"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Home</a></li> <li><a href="#about">About</a></li> <li><a href="#contact">Contact</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li class="dropdown-header">Nav header</li> <li><a href="#">Separated link</a></li> <li><a href="#">One more separated link</a></li> </ul> </li> </ul> </div><!--/.nav-collapse --> </div> </nav> </div> </body> </html>
二、本地下載bootstrap,經過路徑引入(注意引入順序,bootstrap的js依賴jquery,要在引入js前,先引入jquery)jquery
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"> <script type="application/javascript" src="bootstrap-3.3.7-dist/jquery-3.1.1.js"></script> <script type="application/javascript" src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> <title>Bootstrap-demo</title> </head> <body> <div class="container"> <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar" aria-expanded="true" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Bootstrap theme</a> </div> <div id="navbar" class="navbar-collapse collapse in" aria-expanded="true"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Home</a></li> <li><a href="#about">About</a></li> <li><a href="#contact">Contact</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li class="dropdown-header">Nav header</li> <li><a href="#">Separated link</a></li> <li><a href="#">One more separated link</a></li> </ul> </li> </ul> </div><!--/.nav-collapse --> </div> </nav> </div> </body> </html>
一、bootstrap將每一行分爲12列,並且這一行會有居中和兩邊有間距git
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"> <title>Bootstrap-demo</title> <style> .row [class*="col-"]{ padding-top: 15px; padding-bottom: 15px; background-color: rebeccapurple; border: 2px solid yellowgreen; color:#fff; } /*媒體查詢*/ /*@media(max-width:800px){*/ /*.media{*/ /*color: red;*/ /*}*/ /*}*/ /*多條件*/ @media(max-width:800px) and (min-width: 500px){ .media{ color: red; } } </style> </head> <body> <!--bootstrap將寬分爲12個列--> <!------------------------------柵格系統的結構------------> <!--container是距離左右各15px--> <div class="container"> <div class="row"> <div class="col-md-2">md-2</div> <div class="col-md-4">md-4</div> <div class="col-md-6">md-6</div> </div> <div class="row"> <div class="col-md-6 col-sm-4">md6-sm4</div> <div class="col-md-6 col-sm-8">md6-sm8</div> </div> <div class="media">hello @media</div> <!------------------------------柵格系統的使用------------> <div class="row"> <div class="col-sm-2">md-2</div> <div class="col-sm-4">md-4</div> <div class="col-sm-6">md-6</div> </div> <!-- 2 列偏移offset --> <div class="row"> <div class="col-md-2">col-md-3</div> <div class="col-md-4 col-md-offset-4">col-md-offset-3</div> <!--<div class="col-md-1">col-md-1col-md-1col-md-1col-md-1col-md-1</div>--> </div> <!-- 3 列嵌套 --> <div class="row"> <div class="col-md-9"> <!--這個嵌套是將原9列,在分爲12列,去分割--> <div class="row"> <div class="col-md-8">col-md-8</div> <div class="col-md-4">col-md-4</div> </div> </div> <div class="col-md-3">col-md-3</div> </div> <!-- 4 列排序 --> <div class="row"> <div class="col-md-9 col-md-push-3">col-md-9</div> <div class="col-md-3 col-md-pull-9">col-md-3</div> </div> <!-- 5 清除浮動 --> <div class="row"> <div class="col-md-6 col-sm-1">col-md-1</div> <div class="clearfix visible-sm"></div> <div class="col-md-6 col-sm-1">col-md-3</div> </div> </div> </body> </html>
二、媒介查詢-響應式佈局(使用場景多種不一樣分辨率的設備進行自適應)
@media
/* 超小屏幕(手機,小於 768px) */ /* 沒有任何媒體查詢相關的代碼,由於這在 Bootstrap 中是默認的(還記得 Bootstrap 是移動設備優先的嗎?) */ /* 小屏幕(平板,大於等於 768px) */ @media (min-width: @screen-sm-min) { ... } /* 中等屏幕(桌面顯示器,大於等於 992px) */ @media (min-width: @screen-md-min) { ... } /* 大屏幕(大桌面顯示器,大於等於 1200px) */ @media (min-width: @screen-lg-min) { ... }
咱們偶爾也會在媒體查詢代碼中包含 max-width
從而將 CSS 的影響限制在更小範圍的屏幕大小以內。
@media (max-width: @screen-xs-max) { ... } @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) { ... } @media (min-width: @screen-md-min) and (max-width: @screen-md-max) { ... } @media (min-width: @screen-lg-min) { ... }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .header{ background-color: wheat; width: 100%; height: 100px; } .header div{ display: inline-block; border: 1px solid red; background-color: blue; padding: 10px 100px; } @media (max-width: 800px) { .header .c3{ background-color: yellow; display: none; } } </style> </head> <body> <div class="header"> <div>hello</div> <div>hello</div> <div class="c3">hello</div> </div> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"> <title>demo-排版</title> </head> <body> <div class="container"> <!------------------------------排版基礎------------> <div class="row"> <div class="col-md-2">hello md-2</div> <a class="col-md-4">md-4</a> <p class="col-md-6">md-6</p> </div> <!------------------------------排版標題------------> <h1>我是h1</h1> <h2>我是h2</h2> <h3>我是h3</h3> <h4>我是h4</h4> <h5>我是h5</h5> <h6>我是h6</h6> <!--若是向任何標題添加一個內聯子標題,只須要簡單地在元素兩旁添加 <small>,--> <!--或者添加 .small class便可--> <h1>h1...<small>h1子標題</small></h1> <h2>h2...<small>h2子標題</small></h2> <!------------------------------強調------------> <!--添加 class="lead"使段落文本更大更粗、行高更高--> <p class="lead">莫道君行早,更有早行人</p> <small>small</small><br> <strong>strong</strong><br> <em>em</em><br> <p class="text-left">文本左對齊</p> <p class="text-center">文本居中對齊</p> <p class="text-right">文本右對齊</p> <p class="text-primary">text-primary</p> <p class="text-success">text-success</p> <p class="text-info">text-info</p> <p class="text-warning">text-warning</p> <p class="text-danger">text-danger</p> <!------------------------------縮寫------------> <abbr title="HyperText Transfer Protocol">http</abbr><br> <abbr title="Domain Name System" class="initialism">dns</abbr> <!------------------------------地址(沒有太大樣式改變)------------> <address> <strong>oldboy</strong><br> XXX street<br> beijing<br> <abbr title="Phone">P:</abbr> (123) 456-7890 </address> <!------------------------------引用------------> <p class="lead">hello world hello world hello world hello world</p> <blockquote class="pull-left"> <small><em>發佈於 2017-02-19</em></small> </blockquote> <!------------------------------列表(有序列表、無序列表和定義列表)------------> <br> <hr> <h3>未定義樣式列表</h3> <ul class="list-unstyled"> <li>item</li> <li>item</li> <li>item</li> <li>item</li> </ul> <h3>內聯列表</h3> <ul class="list-inline"> <li>item</li> <li>item</li> <li>item</li> <li>item</li> </ul> <h3>水平的定義列表</h3> <dl class="dl-horizontal"> <dt>Desc</dt> <dd>item</dd> <dt>Desc</dt> <dd>item</dd> </dl> </div> </body> </html>
Bootstrap 容許您以兩種方式顯示代碼:
<div class="container"> <p><code><p>hello</p></code> 是一個p標籤</p> <p>若是須要把代碼顯示爲一個獨立的塊元素,請使用 <code><pre></code> <pre> <div> <h1>介紹</h1> </div> </pre> </div>
1.表格的樣式
<div class="container"> <table class="table table-striped"> <!--關於表格存儲內容的描述或總結。--> <caption>條紋表格佈局</caption> <thead> <tr> <th>姓名</th> <th>年齡</th> <th>salary</th> </tr> </thead> <tbody> <tr> <td>Bob</td> <td>23</td> <td>3000</td> </tr> <tr class="danger"> <td>steven</td> <td>34</td> <td>5000</td> </tr> <tr class="success"> <td>alvin</td> <td>33</td> <td>7000</td> </tr> <tr class="warning"> <td>alvin</td> <td>33</td> <td>7000</td> </tr> </tbody> </table> </div>
二、響應式表格
經過把任意的 .table 包在 .table-responsive class 內可讓表格水平滾動以適應小型設備(小於 768px)。當在大於 768px 寬的大型設備上查看時,看不到任何的差異。
Bootstrap 提供了下列類型的表單佈局:
一、垂直表單
建立基本表單的步驟:
<form role="form"> <div class="form-group"> <label for="username">用戶名</label> <input type="text" class="form-control" id="username" placeholder="請輸入用戶名"> </div> <div class="form-group"> <label for="password">密碼</label> <input type="password" class="form-control" id="password" placeholder="請輸入密碼"> </div> <div class="checkbox"> <label> <input type="checkbox">記住密碼 </label> </div> <button type="submit" class="btn">提交</button> </form>
二、內聯表單
若是須要建立一個表單,它的全部元素是內聯的,向左對齊的,標籤是並排的,請向 <form> 標籤添加 class .form-inline。
三、水平表單
水平表單與其餘表單不只標記的數量上不一樣,並且表單的呈現形式也不一樣。如需建立一個水平佈局的表單,請按下面的幾個步驟進行:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"> <title>demo-排版</title> </head> <body> <div class="container"> <form class="form-horizontal" role="form"> <div class="form-group"> <label for="username" class="col-sm-2 control-label">用戶名</label> <div class="col-sm-10"> <input type="text" class="form-control" id="username" placeholder="請輸入用戶名"> </div> </div> <div class="form-group"> <label for="pwd" class="col-sm-2 control-label">密碼</label> <div class="col-sm-10"> <input type="text" class="form-control" id="pwd" placeholder="請輸入用戶名"> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <div class="checkbox"> <label> <input type="checkbox">記住密碼 </label> </div> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn">登陸</button> </div> </div> </form> </div> </body> </html>
四、表單控件插件
輸入框焦點:當輸入框 input 接收到 :focus 時,輸入框的輪廓會被移除,同時應用 box-shadow。
禁用的輸入框 input:若是您想要禁用一個輸入框 input,只須要簡單地添加 disabled 屬性,這不只會禁用輸入框,還會改變輸入框的樣式以及當鼠標的指針懸停在元素上時鼠標指針的樣式。
禁用的字段集 fieldset:對<添加 disabled 屬性來禁用內的全部控件。
驗證狀態:Bootstrap 包含了錯誤、警告和成功消息的驗證樣式。只須要對父元素簡單地添加適當的 class(.has-warning、 .has-error 或 .has-success)便可使用驗證狀態
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"> <title>demo-排版</title> </head> <body> <div class="container"> <!------------------------------排版基礎------------> <div class="row"> <div class="col-md-2">hello md-2</div> <a class="col-md-4">md-4</a> <p class="col-md-6">md-6</p> </div> <!------------------------------排版標題------------> <h1>我是h1</h1> <h2>我是h2</h2> <h3>我是h3</h3> <h4>我是h4</h4> <h5>我是h5</h5> <h6>我是h6</h6> <!--若是向任何標題添加一個內聯子標題,只須要簡單地在元素兩旁添加 <small>,--> <!--或者添加 .small class便可--> <h1>h1...<small>h1子標題</small></h1> <h2>h2...<small>h2子標題</small></h2> <!------------------------------強調------------> <!--添加 class="lead"使段落文本更大更粗、行高更高--> <p class="lead">莫道君行早,更有早行人</p> <small>small</small><br> <strong>strong</strong><br> <em>em</em><br> <p class="text-left">文本左對齊</p> <p class="text-center">文本居中對齊</p> <p class="text-right">文本右對齊</p> <p class="text-primary">text-primary</p> <p class="text-success">text-success</p> <p class="text-info">text-info</p> <p class="text-warning">text-warning</p> <p class="text-danger">text-danger</p> <!------------------------------縮寫------------> <abbr title="HyperText Transfer Protocol">http</abbr><br> <abbr title="Domain Name System" class="initialism">dns</abbr> <!------------------------------地址(沒有太大樣式改變)------------> <address> <strong>oldboy</strong><br> XXX street<br> beijing<br> <abbr title="Phone">P:</abbr> (123) 456-7890 </address> <!------------------------------引用------------> <p class="lead">hello world hello world hello world hello world</p> <blockquote class="pull-left"> <small><em>發佈於 2017-02-19</em></small> </blockquote> <!------------------------------列表(有序列表、無序列表和定義列表)------------> <br> <hr> <h3>未定義樣式列表</h3> <ul class="list-unstyled"> <li>item</li> <li>item</li> <li>item</li> <li>item</li> </ul> <h3>內聯列表</h3> <ul class="list-inline"> <li>item</li> <li>item</li> <li>item</li> <li>item</li> </ul> <h3>水平的定義列表</h3> <dl class="dl-horizontal"> <dt>Desc</dt> <dd>item</dd> <dt>Desc</dt> <dd>item</dd> </dl> </div> </body> </html>
五、表單控件大小
您能夠分別使用 class .input-lg 和 .col-lg-* 來設置表單的高度和寬度
<div class="container"> <form role="form"> <div class="form-group"> <!--have a try: input-sm--> <input class="form-control input-lg" type="text" placeholder=".input-lg"> </div> <div class="form-group"> <!--have a try: input-sm--> <select class="form-control input-lg"> <option value="">默認選擇</option> </select> </div> <div class="row"> <div class="col-lg-6"> <input type="text" class="form-control"> </div> <div class="col-lg-6"> <input type="text" class="form-control"> </div> </div> </form> </div>
六、表單幫助文本
Bootstrap 表單控件能夠在輸入框 input 上有一個塊級幫助文本。爲了添加一個佔用整個寬度的內容塊,請在 <input> 後使用 .help-block。
<div class="container"> <form role="form"> <span>幫助文本實例</span> <input class="form-control" type="text" placeholder=""> <span class="help-block">幫助文本實例幫助文本實例幫助文本實例幫助文本實例幫助文本實例 幫助文本實例幫助文本實例幫助文本實例幫助文本實例幫助文本實例幫助文本實例幫助文本實例 幫助文本實例幫助文本實例幫助文本實例</span> </form> </div>
任何帶有 class .btn 的元素都會繼承圓角灰色按鈕的默認外觀。可是 Bootstrap 提供了一些選項來定義按鈕的樣式
<div class="container"> <!-- 標準的按鈕 --> <button type="button" class="btn btn-default">默認按鈕</button> <!-- 提供額外的視覺效果,標識一組按鈕中的原始動做 --> <button type="button" class="btn btn-primary">原始按鈕</button> <!-- 表示一個成功的或積極的動做 --> <button type="button" class="btn btn-success">成功按鈕</button> <!-- 信息警告消息的上下文按鈕 --> <button type="button" class="btn btn-info">信息按鈕</button> <!-- 表示應謹慎採起的動做 --> <button type="button" class="btn btn-warning">警告按鈕</button> <!-- 表示一個危險的或潛在的負面動做 --> <button type="button" class="btn btn-danger">危險按鈕</button> <!-- 並不強調是一個按鈕,看起來像一個連接,但同時保持按鈕的行爲 --> <button type="button" class="btn btn-link">連接按鈕</button> <hr> <button type="button" class="btn btn-primary btn-lg">大的原始按鈕</button> <button type="button" class="btn btn-default btn-sm">小的按鈕</button> <hr> <p> <button type="button" class="btn btn-default btn-lg ">默認按鈕</button> <button type="button" class="btn btn-default btn-lg active">激活按鈕</button> </p> <p> <button type="button" class="btn btn-primary btn-lg ">原始按鈕</button> <button type="button" class="btn btn-primary btn-lg active">激活的原始按鈕</button> </p> <hr> <p> <button type="button" class="btn btn-primary btn-lg ">原始按鈕</button> <button type="button" class="btn btn-primary btn-lg" disabled="disabled">禁用的原始按鈕</button> </p> </div>
Bootstrap 提供了三個可對圖片應用簡單樣式的 class:
<img src="mienv.png" class="img-rounded">
另外,經過在 <img> 標籤添加 .img-responsive 類來讓圖片支持響應式設計。.img-responsive 類將 max-width: 100%; 和 height: auto; 樣式應用在圖片上
<img src="meinv.jpg" class="img-responsive">
框架,即framework,特指爲解決一個開放性問題而設計的具備必定約束性的支撐結構,使用框架能夠幫你快速開發特定的系統,簡單地說,就是你用別人搭建好的舞臺來作表演。
對於全部的Web應用,本質上其實就是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端。
import socket def handle_request(client): buf = client.recv(1024) client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8")) client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8")) def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost',8001)) sock.listen(5) while True: connection, address = sock.accept() handle_request(connection) connection.close() if __name__ == '__main__': main()
最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。
若是要動態生成HTML,就須要把上述步驟本身來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,若是咱們本身來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規範。
正確的作法是底層代碼由專門的服務器軟件實現,咱們用Python專一於生成HTML文檔。由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口,讓咱們專心用Python編寫Web業務。
這個接口就是WSGI:Web Server Gateway Interface。
-----------------------------Do a web framework ourselves---------------------------
step1:建立服務端
from wsgiref.simple_server import make_server def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b'<h1>Hello, web!</h1>'] httpd = make_server('', 8080, application) print('Serving HTTP on port 8000...') # 開始監聽HTTP請求: httpd.serve_forever()
注意:
整個application()函數自己沒有涉及到任何解析HTTP的部分,也就是說,底層代碼不須要咱們本身編寫, 咱們只負責在更高層次上考慮如何響應請求就能夠了。 application()函數必須由WSGI服務器來調用。有不少符合WSGI規範的服務器,咱們能夠挑選一個來用。 Python內置了一個WSGI服務器,這個模塊叫wsgiref application()函數就是符合WSGI標準的一個HTTP處理函數,它接收兩個參數: //environ:一個包含全部HTTP請求信息的dict對象; //start_response:一個發送HTTP響應的函數。 在application()函數中,調用: start_response('200 OK', [('Content-Type', 'text/html')]) 就發送了HTTP響應的Header,注意Header只能發送一次,也就是隻能調用一次start_response()函數。 start_response()函數接收兩個參數,一個是HTTP響應碼,一個是一組list表示的HTTP Header,每 個Header用一個包含兩個str的tuple表示。 一般狀況下,都應該把Content-Type頭髮送給瀏覽器。其餘不少經常使用的HTTP Header也應該發送。 而後,函數的返回值b'<h1>Hello, web!</h1>'將做爲HTTP響應的Body發送給瀏覽器。 有了WSGI,咱們關心的就是如何從environ這個dict對象拿到HTTP請求信息,而後構造HTML, 經過start_response()發送Header,最後返回Body。
step2:設置路由系統
print(environ['PATH_INFO']) path=environ['PATH_INFO'] start_response('200 OK', [('Content-Type', 'text/html')]) f1=open("index1.html","rb") data1=f1.read() f2=open("index2.html","rb") data2=f2.read() if path=="/yuan": return [data1] elif path=="/alex": return [data2] else: return ["<h1>404</h1>".encode('utf8')]
step3:更改版
from wsgiref.simple_server import make_server def f1(): f1=open("index1.html","rb") data1=f1.read() return [data1] def f2(): f2=open("index2.html","rb") data2=f2.read() return [data2] def application(environ, start_response): print(environ['PATH_INFO']) path=environ['PATH_INFO'] start_response('200 OK', [('Content-Type', 'text/html')]) if path=="/yuan": return f1() elif path=="/alex": return f2() else: return ["<h1>404</h1>".encode("utf8")] httpd = make_server('', 8502, application) print('Serving HTTP on port 8084...') # 開始監聽HTTP請求: httpd.serve_forever()
step4:模擬數據庫
from wsgiref.simple_server import make_server def f1(req): print(req) print(req["QUERY_STRING"]) f1=open("index1.html","rb") data1=f1.read() return [data1] def f2(req): f2=open("index2.html","rb") data2=f2.read() return [data2] import time def f3(req): #模版以及數據庫 f3=open("index3.html","rb") data3=f3.read() times=time.strftime("%Y-%m-%d %X", time.localtime()) data3=str(data3,"utf8").replace("!time!",str(times)) return [data3.encode("utf8")] def routers(): urlpatterns = ( ('/yuan',f1), ('/alex',f2), ("/cur_time",f3) ) return urlpatterns def application(environ, start_response): print(environ['PATH_INFO']) path=environ['PATH_INFO'] start_response('200 OK', [('Content-Type', 'text/html')]) urlpatterns = routers() func = None for item in urlpatterns: if item[0] == path: func = item[1] break if func: return func(environ) else: return ["<h1>404</h1>".encode("utf8")] httpd = make_server('', 8518, application) print('Serving HTTP on port 8084...') # 開始監聽HTTP請求: httpd.serve_forever()
Django的MTV模式本質是各組件之間爲了保持鬆耦合關係,Django的MTV分別表明:
Model(模型):負責業務對象與數據庫的對象(ORM)
Template(模版):負責如何把頁面展現給用戶
View(視圖):負責業務邏輯,並在適當的時候調用Model和Template
此外,Django還有一個url分發器,它的做用是將一個個URL的頁面請求分發給不一樣的view處理,view再調用相應的Model和Template
安裝django pip3 install django
一、建立一個django project
django-admin.py startproject mysite
當前目錄下會生成mysite的工程,目錄結構以下
二、在mysite目錄下建立應用,好比blog:
python manage.py startapp blog
三、啓動django項目
python manage.py runserver 8080
四、同步更改數據庫表或字段
''' python manage.py syncdb 注意:Django 1.7.1 及以上的版本須要用如下命令 python manage.py makemigrations python manage.py migrate '''
這種方法能夠建立表,當你在models.py中新增了類時,運行它就能夠自動在數據庫中建立表了,不用手動建立。
五、清空數據庫
python manage.py flush
六、建立超級管理員
''' python manage.py createsuperuser # 按照提示輸入用戶名和對應的密碼就行了郵箱能夠留空,用戶名和密碼必填 # 修改 用戶密碼能夠用: python manage.py changepassword username '''
七、Django 項目環境終端
python manage.py shell
這個命令和 直接運行 python 進入 shell 的區別是:你能夠在這個 shell 裏面調用當前項目的 models.py 中的 API,對於操做數據的測試很是方便。
八、Django 項目環境終端
python manage.py dbshell
Django 會自動進入在settings.py中設置的數據庫,若是是 MySQL 或 postgreSQL,會要求輸入數據庫用戶密碼。
在這個終端能夠執行數據庫的SQL語句。若是您對SQL比較熟悉,可能喜歡這種方式。
九、static配置***
#三、STATIC文件還能夠配置STATICFILES_DIRS,指定額外的靜態文件存儲位置。 # STATIC_URL的含義與MEDIA_URL相似。 # ---------------------------------------------------------------------------- #注意1: #爲了後端的更改不會影響前端的引入,避免形成前端大量修改 STATIC_URL = '/static/' #引用名 STATICFILES_DIRS = ( os.path.join(BASE_DIR,"statics") #實際名 ,即實際文件夾的名字 ) #django對引用名和實際名進行映射,引用時,只能按照引用名來,不能按實際名去找 #<script src="/statics/jquery-3.1.1.js"></script> #------error-----不能直接用,必須用STATIC_URL = '/static/': #<script src="/static/jquery-3.1.1.js"></script> #注意2(statics文件夾寫在不一樣的app下,靜態文件的調用): STATIC_URL = '/static/' STATICFILES_DIRS=( ('hello',os.path.join(BASE_DIR,"app01","statics")) , ) #<script src="/static/hello/jquery-1.8.2.min.js"></script> #注意3: STATIC_URL = '/static/' {% load staticfiles %} # <script src={% static "jquery-1.8.2.min.js" %}></script>
URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL與要爲該URL調用的視圖函數之間的映射表;你就是以這種方式告訴Django,對於這個URL調用這段代碼,對於那個URL調用那段代碼。
urlpatterns = [
url(正則表達式, views視圖函數,參數,別名),
]
參數說明:
一個正則表達式字符串
一個可調用對象,一般爲一個視圖函數或一個指定視圖函數路徑的字符串
可選的要傳遞給視圖函數的默認參數(字典形式)
一個可選的name參數
簡單配置:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ]
規則:
''' NOTE: 一旦匹配成功則再也不繼續 若要從URL 中捕獲一個值,只須要在它周圍放置一對圓括號。 不須要添加一個前導的反斜槓,由於每一個URL 都有。例如,應該是^articles 而不是 ^/articles。 每一個正則表達式前面的'r' 是可選的可是建議加上。 一些請求的例子: /articles/2005/3/ 不匹配任何URL 模式,由於列表中的第三個模式要求月份應該是兩個數字。 /articles/2003/ 將匹配列表中的第一個模式不是第二個,由於模式按順序匹配,第一個會首先測試是否匹配。 /articles/2005/03/ 請求將匹配列表中的第三個模式。Django 將調用函數 views.month_archive(request, '2005', '03')。 '''
#設置項是否開啓URL訪問地址後面不爲/跳轉至帶有/的路徑 APPEND_SLASH=True
上面的示例使用簡單的、沒有命名的正則表達式組(經過圓括號)來捕獲URL 中的值並以位置 參數傳遞給視圖。在更高級的用法中,可使用命名的正則表達式組來捕獲URL 中的值並以關鍵字 參數傳遞給視圖。
在Python 正則表達式中,命名正則表達式組的語法是(?P<name>pattern)
,其中name
是組的名稱,pattern
是要匹配的模式。
下面是以上URLconf 使用命名組的重寫:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), --->無名分組 url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), --->有名分組 url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), ]
這個實現與前面的示例徹底相同,只有一個細微的差異:捕獲的值做爲關鍵字參數而不是位置參數傳遞給視圖函數。例如:
/articles/2005/03/ 請求將調用views.month_archive(request, year='2005', month='03')函數 /articles/2003/03/03/ 請求將調用函數views.article_detail(request, year='2003', month='03', day='03')。
無名分組和有名分組的區別:
無名分組是位置變量,後面必須一一對應才能正確傳參,有名分組是關鍵字變量,不須要一一對應。
在實際應用中,這意味你的URLconf 會更加明晰且不容易產生參數順序問題的錯誤 —— 你能夠在你的視圖函數定義中從新安排參數的順序。固然,這些好處是以簡潔爲代價;有些開發人員認爲命名組語法醜陋而繁瑣。
URLconf 在請求的URL 上查找,將它當作一個普通的Python 字符串。不包括GET和POST參數以及域名。
例如,http://www.example.com/myapp/ 請求中,URLconf 將查找myapp/
。
在http://www.example.com/myapp/?page=3 請求中,URLconf 仍將查找myapp/
。
URLconf 不檢查請求的方法。換句話講,全部的請求方法 —— 同一個URL的POST
、GET
、HEAD
等等 —— 都將路由到相同的函數。
每一個捕獲的參數都做爲一個普通的Python 字符串傳遞給視圖,不管正則表達式使用的是什麼匹配方式。例如,下面這行URLconf 中:
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
views.year_archive()
的year
參數將是一個字符串
# URLconf from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/$', views.page), url(r'^blog/page(?P<num>[0-9]+)/$', views.page), ] # View (in blog/views.py) def page(request, num="1"): ...
在上面的例子中,兩個URL模式指向同一個視圖views.page
—— 可是第一個模式不會從URL 中捕獲任何值。若是第一個模式匹配,page()
函數將使用num
參數的默認值"1"。若是第二個模式匹配,page()
將使用正則表達式捕獲的num
值。
第一個若是匹配上,表示num會走默認值,這個對分頁的做用很重要!
#At any point, your urlpatterns can 「include」 other URLconf modules. This #essentially 「roots」 a set of URLs below other ones. #For example, here’s an excerpt of the URLconf for the Django website itself. #It includes a number of other URLconfs: from django.conf.urls import include, url urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^blog/', include('blog.urls')), -->子項目的urls.py ]
URLconfs 具備一個鉤子,讓你傳遞一個Python 字典做爲額外的參數傳遞給視圖函數。
django.conf.urls.url()
函數能夠接收一個可選的第三個參數,它是一個字典,表示想要傳遞給視圖函數的額外關鍵字參數。
from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}), ]
在這個例子中,對於/blog/2005/
請求,Django 將調用views.year_archive(request, year='2005', foo='bar')
。
這個技術在Syndication 框架中使用,來傳遞元數據和選項給視圖。
''' urlpatterns = [ url(r'^index',views.index,name='INDEX'), ] ################### def index(req): if req.method=='POST': username=req.POST.get('username') password=req.POST.get('password') if username=='alex' and password=='123': return HttpResponse("登錄成功") return render(req,'index.html') ##################### <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {# <form action="/index/" method="post">#} <form action="{% url 'INDEX' %}" method="post"> 用戶名:<input type="text" name="username"> 密碼:<input type="password" name="password"> <input type="submit" value="submit"> </form> </body> </html> ####################### '''
一個視圖函數,或者簡短來講叫作視圖,是一個簡單的Python函數,它接受web請求,而且返回web響應。響應能夠是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片. . . 是任何東西均可以。不管視圖自己包含什麼邏輯,都要返回響應。代碼寫在哪裏也無所謂,只要它在你的Python目錄下面。除此以外沒有更多的要求了——能夠說「沒有什麼神奇的地方」。爲了可以把代碼放在某個地方,慣例是把視圖放在叫作views.py的文件中,而後把它放到你的項目或者應用目錄裏
一個簡單的視圖(返回當前時間):
from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
讓咱們逐行閱讀上面的代碼:
http請求-響應過程當中有兩個核心對象:
http請求對象:HttpRequest
http響應響應:HttpResponse
所在位置:django.http
一、render函數
---------------render(request, template_name[, context]) 結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的 HttpResponse 對象。 參數: request: 用於生成響應的請求對象。 template_name:要使用的模板的完整名稱,可選的參數 context:添加到模板上下文的一個字典。默認是一個空字典。若是字典中的某個值是可調用的,視圖將在渲染模板以前調用它。 content_type:生成的文檔要使用的MIME類型。默認爲DEFAULT_CONTENT_TYPE 設置的值。 status:響應的狀態碼。默認爲200。
二、redirect函數(跳轉函數)
-----------------------------------url.py url(r"login", views.login), url(r"yuan_back", views.yuan_back), -----------------------------------views.py def login(req): if req.method=="POST": if 1: # return redirect("/yuan_back/") name="yuanhao" return render(req,"my backend.html",locals()) return render(req,"login.html",locals()) def yuan_back(req): name="苑昊" return render(req,"my backend.html",locals()) -----------------------------------login.html <form action="/login/" method="post"> <p>姓名<input type="text" name="username"></p> <p>性別<input type="text" name="sex"></p> <p>郵箱<input type="text" name="email"></p> <p><input type="submit" value="submit"></p> </form> -----------------------------------my backend.html <h1>用戶{{ name }}你好</h1> #總結: render和redirect的區別: # 1 if render的頁面須要模板語言渲染,須要的將數據庫的數據加載到html,那麼全部的這一部分 # 除了寫在yuan_back的視圖函數中,必須還要寫在login中,代碼重複,沒有解耦. # 2 the most important: url沒有跳轉到/yuan_back/,而是還在/login/,因此當刷新後 # 又得從新登陸.
你可能已經注意到咱們在例子視圖中返回文本的方式有點特別。 也就是說,HTML被直接硬編碼在 Python代碼之中。
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
儘管這種技術便於解釋視圖是如何工做的,但直接將HTML硬編碼到你的視圖裏卻並非一個好主意。 讓咱們來看一下爲何:
對頁面設計進行的任何改變都必須對 Python 代碼進行相應的修改。 站點設計的修改每每比底層 Python 代碼的修改要頻繁得多,所以若是能夠在不進行 Python 代碼修改的狀況下變動設計,那將會方便得多。
Python 代碼編寫和 HTML 設計是兩項不一樣的工做,大多數專業的網站開發環境都將他們分配給不一樣的人員(甚至不一樣部門)來完成。 設計者和HTML/CSS的編碼人員不該該被要求去編輯Python的代碼來完成他們的工做。
程序員編寫 Python代碼和設計人員製做模板兩項工做同時進行的效率是最高的,遠勝於讓一我的等待另外一我的完成對某個既包含 Python又包含 HTML 的文件的編輯工做。
基於這些緣由,將頁面的設計和Python的代碼分離開會更乾淨簡潔更容易維護。 咱們可使用 Django的 模板系統 (Template System)來實現這種模式,這就是本章要具體討論的問題。
python的模板:HTML代碼+邏輯控制代碼
一、變量
語法格式:{{ val_name }}
----------------------------------Template和Context對象 >>> python manange.py shell (進入該django項目的環境) >>> from django.template import Context, Template >>> t = Template('My name is {{ name }}.') >>> c = Context({'name': 'Stephane'}) >>> t.render(c) 'My name is Stephane.' # 同一模板,多個上下文,一旦有了模板對象,你就能夠經過它渲染多個context,不管什麼時候咱們均可以 # 像這樣使用同一模板源渲染多個context,只進行 一次模板建立而後屢次調用render()方法渲染會 # 更爲高效: # Low for name in ('John', 'Julie', 'Pat'): t = Template('Hello, {{ name }}') print t.render(Context({'name': name})) # Good t = Template('Hello, {{ name }}') for name in ('John', 'Julie', 'Pat'): print t.render(Context({'name': name}))
Django 模板解析很是快捷。 大部分的解析工做都是在後臺經過對簡短正則表達式一次性調用來完成。 這和基於 XML 的模板引擎造成鮮明對比,那些引擎承擔了 XML 解析器的開銷,且每每比 Django 模板渲染引擎要慢上幾個數量級。
from django.shortcuts import render,HttpResponse from django.template.loader import get_template #記得導入 # Create your views here. import datetime from django.template import Template,Context # def current_time(req): #原始的視圖函數 # now=datetime.datetime.now() # html="<html><body>如今時刻:<h1>%s.</h1></body></html>" %now # return HttpResponse(html) # def current_time(req): #django模板修改的視圖函數 # now=datetime.datetime.now() # t=Template('<html><body>如今時刻是:<h1 style="color:red">{{current_date}}</h1></body></html>') #t=get_template('current_datetime.html') # c=Context({'current_date':now}) # html=t.render(c) # return HttpResponse(html) #另外一種寫法(推薦) def current_time(req): now=datetime.datetime.now() return render(req, 'current_datetime.html', {'current_date':now})
在到目前爲止的例子中,咱們經過 context 傳遞的簡單參數值主要是字符串,然而,模板系統可以很是簡潔地處理更加複雜的數據結構,例如list、dictionary和自定義的對象。在 Django 模板中遍歷複雜數據結構的關鍵是句點字符 (.)。
#最好是用幾個例子來講明一下。 # 首先,句點可用於訪問列表索引,例如: >>> from django.template import Template, Context >>> t = Template('Item 2 is {{ items.2 }}.') >>> c = Context({'items': ['apples', 'bananas', 'carrots']}) >>> t.render(c) 'Item 2 is carrots.' #假設你要向模板傳遞一個 Python 字典。 要經過字典鍵訪問該字典的值,可以使用一個句點: >>> from django.template import Template, Context >>> person = {'name': 'Sally', 'age': '43'} >>> t = Template('{{ person.name }} is {{ person.age }} years old.') >>> c = Context({'person': person}) >>> t.render(c) 'Sally is 43 years old.' #一樣,也能夠經過句點來訪問對象的屬性。 比方說, Python 的 datetime.date 對象有 #year 、 month 和 day 幾個屬性,你一樣能夠在模板中使用句點來訪問這些屬性: >>> from django.template import Template, Context >>> import datetime >>> d = datetime.date(1993, 5, 2) >>> d.year >>> d.month >>> d.day >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.') >>> c = Context({'date': d}) >>> t.render(c) 'The month is 5 and the year is 1993.' # 這個例子使用了一個自定義的類,演示了經過實例變量加一點(dots)來訪問它的屬性,這個方法適 # 用於任意的對象。 >>> from django.template import Template, Context >>> class Person(object): ... def __init__(self, first_name, last_name): ... self.first_name, self.last_name = first_name, last_name >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.') >>> c = Context({'person': Person('John', 'Smith')}) >>> t.render(c) 'Hello, John Smith.' # 點語法也能夠用來引用對象的方法。 例如,每一個 Python 字符串都有 upper() 和 isdigit() # 方法,你在模板中可使用一樣的句點語法來調用它們: >>> from django.template import Template, Context >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}') >>> t.render(Context({'var': 'hello'})) 'hello -- HELLO -- False' >>> t.render(Context({'var': '123'})) '123 -- 123 -- True' # 注意這裏調用方法時並* 沒有* 使用圓括號 並且也沒法給該方法傳遞參數;你只能調用不需參數的 # 方法。
語法格式:{{ obj | filter:param}}
# 1 add : 給變量加上相應的值 # # 2 addslashes : 給變量中的引號前加上斜線 # # 3 capfirst : 首字母大寫 # # 4 cut : 從字符串中移除指定的字符 # # 5 date : 格式化日期字符串 # # 6 default : 若是值是False,就替換成設置的默認值,不然就是用原本的值 # # 7 default_if_none: 若是值是None,就替換成設置的默認值,不然就使用原本的值 #實例: #value1="aBcDe" {{ value1|upper }}<br> #value2=5 {{ value2|add:3 }}<br> #value3='he llo wo r ld' {{ value3|cut:' ' }}<br> #import datetime #value4=datetime.datetime.now() {{ value4|date:'Y-m-d' }}<br> #value5=[] {{ value5|default:'空的' }}<br> #value6='<a href="#">跳轉</a>' {{ value6 }} {% autoescape off %} {{ value6 }} {% endautoescape %} {{ value6|safe }}<br> {{ value6|striptags }} #value7='1234' {{ value7|filesizeformat }}<br> {{ value7|first }}<br> {{ value7|length }}<br> {{ value7|slice:":-1" }}<br> #value8='http://www.baidu.com/?a=1&b=3' {{ value8|urlencode }}<br> value9='hello I am yuan'
語法格式:{% tag %}
{% if %}標籤計算一個變量值,若是是「true」,即它存在、不爲空而且不是false的boolean值,系統則會顯示{% if %}和{% endif %}間的全部內容
{% if num >= 100 and 8 %} {% if num > 200 %} <p>num大於200</p> {% else %} <p>num大於100小於200</p> {% endif %} {% elif num < 100%} <p>num小於100</p> {% else %} <p>num等於100</p> {% endif %} {% if %} 標籤接受and,or或者not來測試多個變量值或者否認一個給定的變量 {% if %} 標籤不容許同一標籤裏同時出現and和or,不然邏輯容易產生歧義,例以下面的標籤是不合法的: {% if obj1 and obj2 or obj3 %}
{% for %}標籤容許你按順序遍歷一個序列中的各個元素,每次循環模板系統都會渲染{% for %}和{% endfor %}之間的全部內容
<ul> {% for obj in list %} <li>{{ obj.name }}</li> {% endfor %} </ul> #在標籤裏添加reversed來反序循環列表: {% for obj in list reversed %} ... {% endfor %} #{% for %}標籤能夠嵌套: {% for country in countries %} <h1>{{ country.name }}</h1> <ul> {% for city in country.city_list %} <li>{{ city }}</li> {% endfor %} </ul> {% endfor %} #系統不支持中斷循環,系統也不支持continue語句,{% for %}標籤內置了一個forloop模板變量, #這個變量含有一些屬性能夠提供給你一些關於循環的信息 1,forloop.counter表示循環的次數,它從1開始計數,第一次循環設爲1: {% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %} 2,forloop.counter0 相似於forloop.counter,但它是從0開始計數,第一次循環設爲0 3,forloop.revcounter 4,forloop.revcounter0 5,forloop.first當第一次循環時值爲True,在特別狀況下頗有用: {% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} {{ object }} </li> {% endfor %} # 富有魔力的forloop變量只能在循環中獲得,當模板解析器到達{% endfor %}時forloop就消失了 # 若是你的模板context已經包含一個叫forloop的變量,Django會用{% for %}標籤替代它 # Django會在for標籤的塊中覆蓋你定義的forloop變量的值 # 在其餘非循環的地方,你的forloop變量仍然可用 #{% empty %} {{li }} {% for i in li %} <li>{{ forloop.counter0 }}----{{ i }}</li> {% empty %} <li>this is empty!</li> {% endfor %} # [11, 22, 33, 44, 55] # 0----11 # 1----22 # 2----33 # 3----44 # 4----55
<1> sqlite
django默認使用sqlite的數據庫,默認自帶sqlite的數據庫驅動 , 引擎名稱:django.db.backends.sqlite3
<2> mysql
引擎名稱:django.db.backends.mysql
修改爲mysql數據庫以下:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'books', #你的數據庫名稱 'USER': 'root', #你的數據庫用戶名 'PASSWORD': '', #你的數據庫密碼 'HOST': '', #你的數據庫主機,留空默認爲localhost 'PORT': '3306', #你的數據庫端口 } }
NAME即數據庫的名字,在mysql鏈接前該數據庫必須已經建立,而上面的sqlite數據庫下的db.sqlite3則是項目自動建立 USER和PASSWORD分別是數據庫的用戶名和密碼。 設置完後,再啓動咱們的Django項目前,咱們須要激活咱們的mysql。 而後,啓動項目,會報錯:no module named MySQLdb 這是由於django默認你導入的驅動是MySQLdb,但是MySQLdb對於py3有很大問題,因此咱們須要的驅動是PyMySQL 因此,咱們只須要找到項目名文件下的__init__,在裏面寫入: import pymysql pymysql.install_as_MySQLdb() 問題解決!
實例:咱們來假定下面這些概念,字段和關係
做者模型:一個做者有姓名。
做者詳細模型:把做者的詳情放到詳情表,包含性別,email地址和出生日期,做者詳情模型和做者模型之間是一對一的關係(one-to-one)(相似於每一個人和他的身份證之間的關係),在大多數狀況下咱們沒有必要將他們拆分紅兩張表,這裏只是引出一對一的概念。
出版商模型:出版商有名稱,地址,所在城市,省,國家和網站。
書籍模型:書籍有書名和出版日期,一本書可能會有多個做者,一個做者也能夠寫多本書,因此做者和書籍的關係就是多對多的關聯關係(many-to-many),一本書只應該由一個出版商出版,因此出版商和書籍是一對多關聯關係(one-to-many),也被稱做外鍵。
from django.db import models<br> class Publisher(models.Model): name = models.CharField(max_length=30, verbose_name="名稱") address = models.CharField("地址", max_length=50) city = models.CharField('城市',max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Meta: verbose_name = '出版商' verbose_name_plural = verbose_name def __str__(self): return self.name class Author(models.Model): name = models.CharField(max_length=30) def __str__(self): return self.name class AuthorDetail(models.Model): sex = models.BooleanField(max_length=1, choices=((0, '男'),(1, '女'),)) email = models.EmailField() address = models.CharField(max_length=50) birthday = models.DateField() author = models.OneToOneField(Author) class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() price=models.DecimalField(max_digits=5,decimal_places=2,default=10) def __str__(self): return self.title
分析代碼:
<1> 每一個數據模型都是django.db.models.Model的子類,它的父類Model包含了全部必要的和數據庫交互的方法。並提供了一個簡介漂亮的定義數據庫字段的語法。
<2> 每一個模型至關於單個數據庫表(多對多關係例外,會多生成一張關係表),每一個屬性也是這個表中的字段。屬性名就是字段名,它的類型(例如CharField)至關於數據庫的字段類型(例如varchar)。你們能夠留意下其它的類型都和數據庫裏的什麼字段對應。
<3> 模型之間的三種關係:一對一,一對多,多對多。
一對一:實質就是在主外鍵(author_id就是foreign key)的關係基礎上,給外鍵加了一個UNIQUE=True的屬性;
一對多:就是主外鍵關係;(foreign key)
多對多:(ManyToManyField) 自動建立第三張表(固然咱們也能夠本身建立第三張表:兩個foreign key)
from app01.models import * #一種是建立一個對象的形式,另外是對象傳參 #create方式一: Author.objects.create(name='Alvin') #create方式二: Author.objects.create(**{"name":"alex"}) #save方式一: author=Author(name="alvin") author.save() #save方式二: author=Author() author.name="alvin" author.save()
重點來了------->那麼如何建立存在一對多或多對多關係的一本書的信息呢?(如何處理外鍵關係的字段如一對多的publisher和
多對多的authors)
#一對多(ForeignKey): #方式一: 因爲綁定一對多的字段,好比publish,存到數據庫中的字段名叫publish_id,因此咱們能夠直接給這個 # 字段設定對應值: Book.objects.create(title='php', publisher_id=2, #這裏的2是指爲該book對象綁定了Publisher表中id=2的行對象 publication_date='2017-7-7', price=99) #方式二: # <1> 先獲取要綁定的Publisher對象: pub_obj=Publisher(name='河大出版社',address='保定',city='保定', state_province='河北',country='China',website='http://www.hbu.com') OR pub_obj=Publisher.objects.get(id=1) # <2>將 publisher_id=2 改成 publisher=pub_obj #多對多(ManyToManyField()): author1=Author.objects.get(id=1) author2=Author.objects.filter(name='alvin')[0] book=Book.objects.get(id=1) book.authors.add(author1,author2) #等同於: book.authors.add(*[author1,author2]) book.authors.remove(*[author1,author2]) #------------------- book=models.Book.objects.filter(id__gt=1) authors=models.Author.objects.filter(id=1)[0] authors.book_set.add(*book) authors.book_set.remove(*book) #------------------- book.authors.add(1) book.authors.remove(1) authors.book_set.add(1) authors.book_set.remove(1) #注意: 若是第三張表是經過models.ManyToManyField()自動建立的,那麼綁定關係只有上面一種方式 # 若是第三張表是本身建立的: class Book2Author(models.Model): author=models.ForeignKey("Author") Book= models.ForeignKey("Book") # 那麼就還有一種方式: author_obj=models.Author.objects.filter(id=2)[0] book_obj =models.Book.objects.filter(id=3)[0] s=models.Book2Author.objects.create(author_id=1,Book_id=2) s.save() s=models.Book2Author(author=author_obj,Book_id=1) s.save()
先filter出行數,在執行.delete()進行刪除
>>> Book.objects.filter(id=1).delete() (3, {'app01.Book_authors': 2, 'app01.Book': 1})
咱們表面上刪除了一條信息,實際卻刪除了三條,由於咱們刪除的這本書在Book_authors表中有兩條相關信息,這種刪除方式就是django默認的級聯刪除。
注意:
<1> 第二種方式修改不能用get的緣由是:update是QuerySet對象的方法,get返回的是一個model對象,它沒有update方法,而filter返回的是一個QuerySet對象(filter裏面的條件可能有多個條件符合,好比name='alvin',可能有兩個name='alvin'的行數據)。
<2>在「插入和更新數據」小節中,咱們有提到模型的save()方法,這個方法會更新一行裏的全部列。 而某些狀況下,咱們只須要更新行裏的某幾列。
下面是二者區別的解釋:
#---------------- update方法直接設定對應屬性---------------- models.Book.objects.filter(id=3).update(title="PHP") ##sql: ##UPDATE "app01_book" SET "title" = 'PHP' WHERE "app01_book"."id" = 3; args=('PHP', 3) #--------------- save方法會將全部屬性從新設定一遍,效率低----------- obj=models.Book.objects.filter(id=3)[0] obj.title="Python" obj.save() # SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", # "app01_book"."color", "app01_book"."page_num", # "app01_book"."publisher_id" FROM "app01_book" WHERE "app01_book"."id" = 3 LIMIT 1; # # UPDATE "app01_book" SET "title" = 'Python', "price" = 3333, "color" = 'red', "page_num" = 556, # "publisher_id" = 1 WHERE "app01_book"."id" = 3;
此外,update()方法對於任何結果集(QuerySet)均有效,這意味着你能夠同時更新多條記錄update()方法會返回一個整型數值,表示受影響的記錄條數。
注意,這裏由於update返回的是一個整形,因此無法用query屬性;對於每次建立一個對象,想顯示對應的raw sql,須要在settings加上日誌記錄部分:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
# 查詢相關API: # <1>filter(**kwargs): 它包含了與所給篩選條件相匹配的對象 # <2>all(): 查詢全部結果 # <3>get(**kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。 #-----------下面的方法都是對查詢的結果再進行處理:好比 objects.filter.values()-------- # <4>values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列 model的實例化對象,而是一個可迭代的字典序列 # <5>exclude(**kwargs): 它包含了與所給篩選條件不匹配的對象 # <6>order_by(*field): 對查詢結果排序 # <7>reverse(): 對查詢結果反向排序 # <8>distinct(): 從返回結果中剔除重複紀錄 # <9>values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列 # <10>count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。 # <11>first(): 返回第一條記錄 # <12>last(): 返回最後一條記錄 # <13>exists(): 若是QuerySet包含數據,就返回True,不然返回False
****request.get('user') 獲取一個值,request.getlist('authors') 獲取一個數組
未完待續!