MVC:將web應用分爲模型(M),控制器(C),視圖(V)三層;他們之間以一種插件似的,鬆耦合的方式鏈接在一塊兒。html
模型負責業務對象與數據庫的對象(ORM),視圖負責與用戶的交互(頁面),控制器(C)接受用戶的輸入調用模型和視圖完成用戶的請求。python
Django的MTV模型本質上與MVC沒有什麼差異,也是各組件之間爲了保持鬆耦合關係,只不過定義上有些不一樣,Django的MTV分別是:mysql
• Model(模型):負責業務對象與數據庫的對象(ORM)linux
• Template(模板):負責如何把頁面展現給用戶git
• View(視圖):負責業務邏輯,並在適當的時候調用Model和Template程序員
1 django 2 #安裝: pip3 install django 3 4 添加環境變量 5 6 #1 建立project 7 django-admin startproject mysite 8 9 ---mysite 10 11 ---settings.py 12 ---url.py 13 ---wsgi.py 14 15 ---- manage.py(啓動文件) 16 17 #2 建立APP 18 python mannage.py startapp app01 19 20 #3 settings配置 21 22 TEMPLATES 23 24 STATICFILES_DIRS=( 25 os.path.join(BASE_DIR,"statics"), 26 ) 27 28 STATIC_URL = '/static/' 29 # 咱們只能用 STATIC_URL,但STATIC_URL會按着你的STATICFILES_DIRS去找#4 根據需求設計代碼 30 url.py 31 view.py 32 33 #5 使用模版 34 render(req,"index.html") 35 36 #6 啓動項目 37 python manage.py runserver 127.0.0.1:8090 38 39 #7 鏈接數據庫,操做數據 40 model.py
文件介紹:web
• manage.py --- Django項目裏面的工具,經過它能夠調用django shell和數據庫等正則表達式
• settings.py --- 包含了項目的默認設置,包括數據庫信息,調試標誌以及其餘一些工做的變量。sql
• urls.py --- 負責把url模式映射到應用程序shell
- 生成同步數據庫的腳本:python manage.py makemigrations
同步數據庫:python manage.py migrate
注:開發過程當中,數據庫同步誤操做以後,不免會遇到後面不能同步成功的狀況,解決這個問題的一個粗暴方法是將migrations目錄下的腳本(除了__init__.py以外)所有刪掉,再把數據庫刪掉以後建立一個新的數據庫,數據庫同步操做再從新作一遍。
-- 訪問http://127.0.0.1:8000/admin/login/?next=/admin/時,須要爲進入這個項目後臺建立超級管理員:python manage.py createsuperuser,設置好帳戶密碼就能夠登錄
-- 清空數據庫:python manage.py flush
-- 查詢某個命令的詳細信息:django-admin.py help startapp
-- 啓動交互界面:python manage.py shell(和直接運行python進入shell的區別是:你能夠在這個shell裏面調用當前項目的models.py中的API,對於操做數據,還有一些小測試很是方便)
-- 終端上輸入python manage.py 能夠看到詳細的列表,在忘記子名稱的時候特別有用
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <h1>建立我的信息</h1> 9 10 <form action="/userInfor/" method="post"> 11 12 <p>姓名<input type="text" name="username"></p> 13 <p>性別<input type="text" name="sex"></p> 14 <p>郵箱<input type="text" name="email"></p> 15 <p><input type="submit" value="submit"></p> 16 17 </form> 18 19 <hr> 20 21 <h1>信息展現</h1> 22 23 <table border="1"> 24 25 <tr> 26 <td>姓名</td> 27 <td>性別</td> 28 <td>郵箱</td> 29 </tr> 30 {% for i in info_list %} 31 32 <tr> 33 <td>{{ i.username }}</td> 34 <td>{{ i.sex }}</td> 35 <td>{{ i.email }}</td> 36 </tr> 37 38 {% endfor %} 39 40 </table> 41 42 </body> 43 </html> 44 45 46 -----------------------url.py--------------------------------------- 47 url(r'^userInfor/', views.userInfor) 48 49 -----------------------views.py-------------------------------------- 50 51 info_list=[] 52 53 def userInfor(req): 54 55 if req.method=="POST": 56 username=req.POST.get("username",None) 57 sex=req.POST.get("sex",None) 58 email=req.POST.get("email",None) 59 60 info={"username":username,"sex":sex,"email":email} 61 info_list.append(info) 62 63 return render(req,"userInfor.html",{"info_list":info_list})
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <h1>建立我的信息</h1> 9 10 <form action="/userInfor/" method="post"> 11 12 <p>姓名<input type="text" name="username"></p> 13 <p>性別<input type="text" name="sex"></p> 14 <p>郵箱<input type="text" name="email"></p> 15 <p><input type="submit" value="submit"></p> 16 17 </form> 18 19 <hr> 20 21 <h1>信息展現</h1> 22 23 <table border="1"> 24 25 <tr> 26 <td>姓名</td> 27 <td>性別</td> 28 <td>郵箱</td> 29 </tr> 30 {% for i in info_list %} 31 32 <tr> 33 <td>{{ i.username }}</td> 34 <td>{{ i.sex }}</td> 35 <td>{{ i.email }}</td> 36 </tr> 37 38 {% endfor %} 39 40 </table> 41 42 </body> 43 </html> 44 45 46 ----------------------------------------------models.py 47 from django.db import models 48 49 # Create your models here. 50 51 52 class UserInfor(models.Model): 53 54 username=models.CharField(max_length=64) 55 sex=models.CharField(max_length=64) 56 email=models.CharField(max_length=64) 57 58 ----------------------------------------------views.py 59 60 from django.shortcuts import render 61 62 from app01 import models 63 # Create your views here. 64 65 66 def userInfor(req): 67 68 if req.method=="POST": 69 u=req.POST.get("username",None) 70 s=req.POST.get("sex",None) 71 e=req.POST.get("email",None) 72 73 74 #---------表中插入數據方式一 75 # info={"username":u,"sex":e,"email":e} 76 # models.UserInfor.objects.create(**info) 77 78 #---------表中插入數據方式二 79 models.UserInfor.objects.create( 80 username=u, 81 sex=s, 82 email=e 83 ) 84 85 info_list=models.UserInfor.objects.all() 86 87 return render(req,"userInfor.html",{"info_list":info_list}) 88 89 return render(req,"userInfor.html")
URL配置(URLconf)就像Django所支持網站的目錄。它的本質是URL模式以及要爲該URL模式調用的視圖函數之間的映射表;就是以這種方式告訴Django,對於這個URL調用這段代碼,對於那個URL調用那段代碼。
1 urlpatterns = [ 2 url(正則表達式,views視圖函數,參數,別名), 3 ]
1 from django.conf.urls import url 2 from django.contrib import admin 3 4 from app01 import views 5 6 urlpatterns = [ 7 8 url(r'^articles/2003/$', views.special_case_2003), 9 10 #url(r'^articles/[0-9]{4}/$', views.year_archive), 11 12 url(r'^articles/([0-9]{4})/$', views.year_archive), #no_named group 13 14 url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), 15 16 url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), 17 18 ]
Http請求中產生兩個核心對象:
http請求:HttpRequest對象
http響應:HttpResponse對象
1 # path: 請求頁面的全路徑,不包括域名 2 # 3 # method: 請求中使用的HTTP方法的字符串表示。全大寫表示。例如 4 # 5 # if req.method=="GET": 6 # 7 # do_something() 8 # 9 # elseif req.method=="POST": 10 # 11 # do_something_else() 12 # 13 # GET: 包含全部HTTP GET參數的類字典對象 14 # 15 # POST: 包含全部HTTP POST參數的類字典對象 16 # 17 # 服務器收到空的POST請求的狀況也是可能發生的,也就是說,表單form經過 18 # HTTP POST方法提交請求,可是表單中可能沒有數據,所以不能使用 19 # if req.POST來判斷是否使用了HTTP POST 方法;應該使用 if req.method=="POST" 20 # 21 # 22 # 23 # COOKIES: 包含全部cookies的標準Python字典對象;keys和values都是字符串。 24 # 25 # FILES: 包含全部上傳文件的類字典對象;FILES中的每個Key都是<input type="file" name="" />標籤中 name屬性的值,FILES中的每個value同時也是一個標準的python字典對象,包含下面三個Keys: 26 # 27 # filename: 上傳文件名,用字符串表示 28 # content_type: 上傳文件的Content Type 29 # content: 上傳文件的原始內容 30 # 31 # 32 # user: 是一個django.contrib.auth.models.User對象,表明當前登錄的用戶。若是訪問用戶當前 33 # 沒有登錄,user將被初始化爲django.contrib.auth.models.AnonymousUser的實例。你 34 # 能夠經過user的is_authenticated()方法來辨別用戶是否登錄: 35 # if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware 36 # 時該屬性纔可用 37 # 38 # session: 惟一可讀寫的屬性,表明當前會話的字典對象;本身有激活Django中的session支持時該屬性纔可用。 39 40 #方法 41 get_full_path(), 好比:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()獲得的結果就是/index33/?name=123 42 req.path:/index33
注:經常使用request.POST.getlist('')
對於HttpReques對象來講,是由django自動建立的。可是,HttpResponse對象就必須咱們本身建立。每一個view請求處理方法必須返回一個HttpResponse對象。
HttpResponse類在django.http.HttpResponse
1 HttpResponse對象上擴展的經常使用方法: 2 3 頁面渲染: render() render_to_response() 4 頁面跳轉: redirect("路徑") 5 locals():能夠直接將函數中全部的變量傳給模板
模板語法
• 模板的組成
1 HTML代碼+邏輯控制代碼
• 邏輯控制代碼的組成
一、變量(使用雙大括號來引用變量)
1 格式: {{ var_name }}
---------Template和Context對象
Django模板解析很是便捷。大部分的解析工做都是在後臺經過對簡短正則表達式一次性調用來完成。相比於XML的模板引擎造成鮮明對比,那些引擎承擔了XML解析器的開銷,且每每比Django模板渲染引擎要慢的多。
1 from django.shortcuts import render,HttpResponse 2 from django.template.loader import get_template #記得導入 3 # Create your views here. 4 5 6 import datetime 7 from django.template import Template,Context 8 9 # def current_time(req): 10 #原始的視圖函數 11 # now=datetime.datetime.now() 12 # html="<html><body>如今時刻:<h1>%s.</h1></body></html>" %now 13 # return HttpResponse(html) 14 15 16 17 # def current_time(req): 18 19 #django模板修改的視圖函數 20 # now=datetime.datetime.now() 21 # t=Template('<html><body>如今時刻是:<h1 style="color:red">{{current_date}}</h1></body></html>') 22 #t=get_template('current_datetime.html') 23 # c=Context({'current_date':now}) 24 # html=t.render(c) 25 # return HttpResponse(html) 26 27 #另外一種寫法(推薦) 28 29 def current_time(req): 30 31 now=datetime.datetime.now() 32 33 return render(req, 'current_datetime.html', {'current_date':now}) 34 35 推薦方式
---------深度變量的查找(萬能的句點號)
以上的例子中,經過context傳遞的簡單參數值主要是字符串,然而,模板系統可以很是簡潔地處理更加複雜的數據結構,如:list、dictionary和自定義的對象。
Django模板中遍歷複雜數據結構的關鍵是句點字符(.)。
1 #最好是用幾個例子來講明一下。 2 # 首先,句點可用於訪問列表索引,例如: 3 4 >>> from django.template import Template, Context 5 >>> t = Template('Item 2 is {{ items.2 }}.') 6 >>> c = Context({'items': ['apples', 'bananas', 'carrots']}) 7 >>> t.render(c) 8 'Item 2 is carrots.' 9 10 #假設你要向模板傳遞一個 Python 字典。 要經過字典鍵訪問該字典的值,可以使用一個句點: 11 >>> from django.template import Template, Context 12 >>> person = {'name': 'Sally', 'age': '43'} 13 >>> t = Template('{{ person.name }} is {{ person.age }} years old.') 14 >>> c = Context({'person': person}) 15 >>> t.render(c) 16 'Sally is 43 years old.' 17 18 #一樣,也能夠經過句點來訪問對象的屬性。 比方說, Python 的 datetime.date 對象有 19 #year 、 month 和 day 幾個屬性,你一樣能夠在模板中使用句點來訪問這些屬性: 20 21 >>> from django.template import Template, Context 22 >>> import datetime 23 >>> d = datetime.date(1993, 5, 2) 24 >>> d.year 25 >>> d.month 26 >>> d.day 27 >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.') 28 >>> c = Context({'date': d}) 29 >>> t.render(c) 30 'The month is 5 and the year is 1993.' 31 32 # 這個例子使用了一個自定義的類,演示了經過實例變量加一點(dots)來訪問它的屬性,這個方法適 33 # 用於任意的對象。 34 >>> from django.template import Template, Context 35 >>> class Person(object): 36 ... def __init__(self, first_name, last_name): 37 ... self.first_name, self.last_name = first_name, last_name 38 >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.') 39 >>> c = Context({'person': Person('John', 'Smith')}) 40 >>> t.render(c) 41 'Hello, John Smith.' 42 43 # 點語法也能夠用來引用對象的方法。 例如,每一個 Python 字符串都有 upper() 和 isdigit() 44 # 方法,你在模板中可使用一樣的句點語法來調用它們: 45 >>> from django.template import Template, Context 46 >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}') 47 >>> t.render(Context({'var': 'hello'})) 48 'hello -- HELLO -- False' 49 >>> t.render(Context({'var': '123'})) 50 '123 -- 123 -- True' 51 52 # 注意這裏調用方法時並* 沒有* 使用圓括號 並且也沒法給該方法傳遞參數;你只能調用不需參數的 53 # 方法。
---------變量的過濾器(filter)的使用
1 格式: {{obj|filter:param}}
1 # 1 add : 給變量加上相應的值 2 # 3 # 2 addslashes : 給變量中的引號前加上斜線 4 # 5 # 3 capfirst : 首字母大寫 6 # 7 # 4 cut : 從字符串中移除指定的字符 8 # 9 # 5 date : 格式化日期字符串 10 # 11 # 6 default : 若是值是False,就替換成設置的默認值,不然就是用原本的值 12 # 13 # 7 default_if_none: 若是值是None,就替換成設置的默認值,不然就使用原本的值 14 15 16 #實例: 17 18 #value1="aBcDe" 19 {{ value1|upper }}<br> 20 21 #value2=5 22 {{ value2|add:3 }}<br> 23 24 #value3='he llo wo r ld' 25 {{ value3|cut:' ' }}<br> 26 27 #import datetime 28 #value4=datetime.datetime.now() 29 {{ value4|date:'Y-m-d' }}<br> 30 31 #value5=[] 32 {{ value5|default:'空的' }}<br> 33 34 #value6='<a href="#">跳轉</a>' 35 36 {{ value6 }} 37 38 {% autoescape off %} 39 {{ value6 }} 40 {% endautoescape %} 41 42 {{ value6|safe }}<br> 43 44 {{ value6|striptags }} 45 46 #value7='1234' 47 {{ value7|filesizeformat }}<br> 48 {{ value7|first }}<br> 49 {{ value7|length }}<br> 50 {{ value7|slice:":-1" }}<br> 51 52 #value8='http://www.baidu.com/?a=1&b=3' 53 {{ value8|urlencode }}<br> 54 value9='hello I am yuan'
二、標籤(tag)的使用(使用大括號和百分比的組合來表示使用tag)
1 {%tags%}
---------{% if %} 的使用
{% if %}標籤計算一個變量值,若是是"true",即它不存在、不爲空而且不是false的boolean值,系統則會顯示{% if %}和{% endif %}間的全部內容
1 {% if num >= 100 and 8 %} 2 3 {% if num > 200 %} 4 <p>num大於200</p> 5 {% else %} 6 <p>num大於100小於200</p> 7 {% endif %} 8 9 {% elif num < 100%} 10 <p>num小於100</p> 11 12 {% else %} 13 <p>num等於100</p> 14 15 {% endif %} 16 17 18 19 {% if %} 標籤接受and,or或者not來測試多個變量值或者否認一個給定的變量 20 {% if %} 標籤不容許同一標籤裏同時出現and和or,不然邏輯容易產生歧義,例以下面的標籤是不合法的: 21 22 {% if obj1 and obj2 or obj3 %}
---------{% for %} 的使用
{% for %}標籤容許你按順序遍歷一個序列中的各個元素,每次循環模板系統都會渲染{% for %}和{% endfor %}之間的全部哦內容
1 <ul> 2 {% for obj in list %} 3 <li>{{ obj.name }}</li> 4 {% endfor %} 5 </ul> 6 7 8 #在標籤裏添加reversed來反序循環列表: 9 10 {% for obj in list reversed %} 11 ... 12 {% endfor %} 13 14 #{% for %}標籤能夠嵌套: 15 16 {% for country in countries %} 17 <h1>{{ country.name }}</h1> 18 <ul> 19 {% for city in country.city_list %} 20 <li>{{ city }}</li> 21 {% endfor %} 22 </ul> 23 {% endfor %} 24 25 26 #系統不支持中斷循環,系統也不支持continue語句,{% for %}標籤內置了一個forloop模板變量, 27 #這個變量含有一些屬性能夠提供給你一些關於循環的信息 28 29 1,forloop.counter表示循環的次數,它從1開始計數,第一次循環設爲1: 30 31 {% for item in todo_list %} 32 <p>{{ forloop.counter }}: {{ item }}</p> 33 {% endfor %} 34 2,forloop.counter0 相似於forloop.counter,但它是從0開始計數,第一次循環設爲0 35 3,forloop.revcounter 36 4,forloop.revcounter0 37 5,forloop.first當第一次循環時值爲True,在特別狀況下頗有用: 38 39 40 {% for object in objects %} 41 {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} 42 {{ object }} 43 </li> 44 {% endfor %} 45 46 # 富有魔力的forloop變量只能在循環中獲得,當模板解析器到達{% endfor %}時forloop就消失了 47 # 若是你的模板context已經包含一個叫forloop的變量,Django會用{% for %}標籤替代它 48 # Django會在for標籤的塊中覆蓋你定義的forloop變量的值 49 # 在其餘非循環的地方,你的forloop變量仍然可用 50 51 52 #{% empty %} 53 54 {{li }} 55 {% for i in li %} 56 <li>{{ forloop.counter0 }}----{{ i }}</li> 57 {% empty %} 58 <li>this is empty!</li> 59 {% endfor %} 60 61 # [11, 22, 33, 44, 55] 62 # 0----11 63 # 1----22 64 # 2----33 65 # 3----44 66 # 4----55
---------{% csrf_token%}:csrf_token標籤
用於生成csrf_token的標籤,用於防治跨站攻擊驗證。注:若在view的index裏用的是render_to_response方法,不會生效
這裏生成一個input標籤,和其餘表單標籤一塊兒提交給 後臺
---------{% url %}:引用路由配置的地址
1 <form action="{% url "bieming"%}" > 2 <input type="text"> 3 <input type="submit"value="提交"> 4 {%csrf_token%} 5 </form>
---------{% with %}:用更簡單的變量名替代複雜的變量名
1 {% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}
---------{% verbatim%}:禁止render
1 {% verbatim %} 2 {{ hello }} 3 {% endverbatim %}
---------{% load%}:加載標籤庫
三、自定義filter和simple_tag
a.在app中建立templatetags模塊(必須的)
b.建立任意.py文件,如:my_tags.py
1 from django import template 2 from django.utils.safestring import mark_safe 3 4 register = template.Library() #register的名字是固定的,不可改變 5 6 7 @register.filter 8 def filter_multi(v1,v2): 9 return v1 * v2 10 11 12 @register.simple_tag 13 def simple_tag_multi(v1,v2): 14 return v1 * v2 15 16 17 @register.simple_tag 18 def my_input(id,arg): 19 result = "<input type='text' id='%s' class='%s' />" %(id,arg,) 20 return mark_safe(result)
c.在使用自定義simple_tag和filter的html文件中導入之間建立的 my_tags.py:{% load my_tags.py %}
d.使用simple_tag和filter
1 -------------------------------.html 2 {% load xxx %} #首行 3 4 5 6 7 # num=12 8 {{ num|filter_multi:2 }} #24 9 10 {{ num|filter_multi:"[22,333,4444]" }} 11 12 13 {% simple_tag_multi 2 5 %} 參數不限,但不能放在if for語句中 14 {% simple_tag_multi num 5 %}
e.在settings中的INSTALLED_APPS配置當前app,否則django沒法找到自定義的simple_tag
1 {% if num|filter_multi:30 > 100 %} 2 {{ num|filter_multi:30 }} 3 {% endif %}
注:filter能夠用在if等語句後,simple_tag不能夠
四、extend模板繼承
---------include 模板標籤
{% include %}:該標籤容許在(模塊中)包含其它的模板的內容。標籤的參數是所要包含的模板名稱,能夠是一個變量,也能夠是用單/雙引號硬編碼的字符串。每當在多個模板中出現相同的代碼時,就應該考慮是否要使用{% include %}來減小重複。
---------extend(繼承)模板標籤
在實際應用中,將用Django模板系統來建立整個HTML頁面。這就帶來一個常見Web開發問題:在整個網站中,如何減小共用頁面區域(如站點導航)所引發的重複和冗餘代碼?
解決該問題的傳統作法是使用 服務器端的includes,能夠在HTML頁面中使用該制定將一個網頁嵌入到另外一箇中。事實上,Django經過上面的{% include %}支持這種方式。可是用Django解決此類問題的首選方法是使用更加優雅的策略----模板繼承。
本質上來講,模板繼承就是先構造一個基礎框架模板,然後在其子模版中對它所包含站點公用部分和定義塊進行重載。
第一步:定義基礎模板,該框架將由子模板所繼承
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> 2 <html lang="en"> 3 <head> 4 <title>{% block title %}{% endblock %}</title> 5 </head> 6 <body> 7 <h1>My helpful timestamp site</h1> 8 {% block content %}{% endblock %} 9 {% block footer %} 10 <hr> 11 <p>Thanks for visiting my site.</p> 12 {% endblock %} 13 </body> 14 </html>
以上定義了一個簡單的HTML框架文檔,將在本站點的全部頁面中使用。子模板的做用就是重載、添加或保留那些塊的內容。
全部的{% block %}標籤告訴模板引擎,子模板能夠重載這些部分。每一個{% block %}標籤所要作的是告訴模板引擎,該模板下的這一塊內容將有可能被子模板覆蓋。
1 {% extends "base.html" %} 2 3 {% block title %}The current time{% endblock %} 4 5 {% block content %} 6 <p>It is now {{ current_date }}.</p> 7 {% endblock %}
1 {% extends "base.html" %} 2 3 {% block title %}Future time{% endblock %} 4 5 {% block content %} 6 <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p> 7 {% endblock %}
這樣一來,每一個模板只包含對本身而言獨一無二的代碼。無需多餘的部分。若是想進行站點級的設計修改,僅需修改基礎模板便可,全部其餘模板都會被修改。
數據庫配置
一、django默認支持sqlite,mysql,oracle,postgresql數據庫。
a.sqlite
django默認使用sqlite的數據庫,默認自帶sqlite的數據庫驅動,引擎名稱:django.db.backends.sqlite3
b.mysql
引擎名稱:django.db.backends.mysql
二、mysql驅動程序
a.MySQLdb(mysql python)
b.mysqlclient
c.MySQL
d.PyMySQL(純python的mysql驅動程序)
三、在django的項目中會默認使用sqlite數據庫,在settings有以下配置:
1 DATABASES = { 2 3 'default': { 4 5 'ENGINE': 'django.db.backends.mysql', 6 7 'NAME': 'books', #你的數據庫名稱 8 9 'USER': 'root', #你的數據庫用戶名 10 11 'PASSWORD': '', #你的數據庫密碼 12 13 'HOST': '', #你的數據庫主機,留空默認爲localhost 14 15 'PORT': '3306', #你的數據庫端口 16 17 } 18 19 }
1 NAME即數據庫的名字,在mysql鏈接前該數據庫必須已經建立,而上面的sqlite數據庫下的db.sqlite3則是項目自動建立 2 3 USER和PASSWORD分別是數據庫的用戶名和密碼。 4 5 設置完後,再啓動咱們的Django項目前,咱們須要激活咱們的mysql。 6 7 而後,啓動項目,會報錯:no module named MySQLdb 8 9 這是由於django默認你導入的驅動是MySQLdb,但是MySQLdb對於py3有很大問題,因此咱們須要的驅動是PyMySQL 10 11 因此,咱們只須要找到項目名文件下的__init__,在裏面寫入: 12 13 import pymysql 14 pymysql.install_as_MySQLdb() 15 16 問題解決!
用於實現面向對象編程語言裏不一樣類型系統的數據之間的轉換,換言之,就是用面向對象的方式去操做數據庫的建立表以及增刪改查等操做。
優勢:
一、ORM使得咱們的通用數據庫交互變得簡單易行,並且徹底不用考慮該死的SQL語句。快速開發,由此而來的。
二、能夠避免一些新手程序員寫SQL語句帶來的性能問題。
缺點:
一、性能有所犧牲,不過如今的各類ORM框架都在嘗試各類方法,好比緩存,延遲加載等來減輕這個問題。
二、對於個別複雜查詢,ORM仍然力不從心,爲了解決這個問題,ORM通常也支持寫raw sql。
三、經過QuerySet的query屬性查詢對應操做的sql語句。
1 author_obj=models.Author.objects.filter(id=2) 2 print(author_obj.query)
1 <1> CharField 2 #字符串字段, 用於較短的字符串. 3 #CharField 要求必須有一個參數 maxlength, 用於從數據庫層和Django校驗層限制該字段所容許的最大字符數. 4 5 <2> IntegerField 6 #用於保存一個整數. 7 8 <3> FloatField 9 # 一個浮點數. 必須 提供兩個參數: 10 # 11 # 參數 描述 12 # max_digits 總位數(不包括小數點和符號) 13 # decimal_places 小數位數 14 # 舉例來講, 要保存最大值爲 999 (小數點後保存2位),你要這樣定義字段: 15 # 16 # models.FloatField(..., max_digits=5, decimal_places=2) 17 # 要保存最大值一百萬(小數點後保存10位)的話,你要這樣定義: 18 # 19 # models.FloatField(..., max_digits=19, decimal_places=10) 20 # admin 用一個文本框(<input type="text">)表示該字段保存的數據. 21 22 <4> AutoField 23 # 一個 IntegerField, 添加記錄時它會自動增加. 你一般不須要直接使用這個字段; 24 # 自定義一個主鍵:my_id=models.AutoField(primary_key=True) 25 # 若是你不指定主鍵的話,系統會自動添加一個主鍵字段到你的 model. 26 27 <5> BooleanField 28 # A true/false field. admin 用 checkbox 來表示此類字段. 29 30 <6> TextField 31 # 一個容量很大的文本字段. 32 # admin 用一個 <textarea> (文本區域)表示該字段數據.(一個多行編輯框). 33 34 <7> EmailField 35 # 一個帶有檢查Email合法性的 CharField,不接受 maxlength 參數. 36 37 <8> DateField 38 # 一個日期字段. 共有下列額外的可選參數: 39 # Argument 描述 40 # auto_now 當對象被保存時,自動將該字段的值設置爲當前時間.一般用於表示 "last-modified" 時間戳. 41 # auto_now_add 當對象首次被建立時,自動將該字段的值設置爲當前時間.一般用於表示對象建立時間. 42 #(僅僅在admin中有意義...) 43 44 <9> DateTimeField 45 # 一個日期時間字段. 相似 DateField 支持一樣的附加選項. 46 47 <10> ImageField 48 # 相似 FileField, 不過要校驗上傳對象是不是一個合法圖片.#它有兩個可選參數:height_field和width_field, 49 # 若是提供這兩個參數,則圖片將按提供的高度和寬度規格保存. 50 <11> FileField 51 # 一個文件上傳字段. 52 #要求一個必須有的參數: upload_to, 一個用於保存上載文件的本地文件系統路徑. 這個路徑必須包含 strftime #formatting, 53 #該格式將被上載文件的 date/time 54 #替換(so that uploaded files don't fill up the given directory). 55 # admin 用一個<input type="file">部件表示該字段保存的數據(一個文件上傳部件) . 56 57 #注意:在一個 model 中使用 FileField 或 ImageField 須要如下步驟: 58 #(1)在你的 settings 文件中, 定義一個完整路徑給 MEDIA_ROOT 以便讓 Django在此處保存上傳文件. 59 # (出於性能考慮,這些文件並不保存到數據庫.) 定義MEDIA_URL 做爲該目錄的公共 URL. 要確保該目錄對 60 # WEB服務器用戶賬號是可寫的. 61 #(2) 在你的 model 中添加 FileField 或 ImageField, 並確保定義了 upload_to 選項,以告訴 Django 62 # 使用 MEDIA_ROOT 的哪一個子目錄保存上傳文件.你的數據庫中要保存的只是文件的路徑(相對於 MEDIA_ROOT). 63 # 出於習慣你必定很想使用 Django 提供的 get_<#fieldname>_url 函數.舉例來講,若是你的 ImageField 64 # 叫做 mug_shot, 你就能夠在模板中以 {{ object.#get_mug_shot_url }} 這樣的方式獲得圖像的絕對路徑. 65 66 <12> URLField 67 # 用於保存 URL. 若 verify_exists 參數爲 True (默認), 給定的 URL 會預先檢查是否存在( 即URL是否被有效裝入且 68 # 沒有返回404響應). 69 # admin 用一個 <input type="text"> 文本框表示該字段保存的數據(一個單行編輯框) 70 71 <13> NullBooleanField 72 # 相似 BooleanField, 不過容許 NULL 做爲其中一個選項. 推薦使用這個字段而不要用 BooleanField 加 null=True 選項 73 # admin 用一個選擇框 <select> (三個可選擇的值: "Unknown", "Yes" 和 "No" ) 來表示這種字段數據. 74 75 <14> SlugField 76 # "Slug" 是一個報紙術語. slug 是某個東西的小小標記(短籤), 只包含字母,數字,下劃線和連字符.#它們一般用於URLs 77 # 若你使用 Django 開發版本,你能夠指定 maxlength. 若 maxlength 未指定, Django 會使用默認長度: 50. #在 78 # 之前的 Django 版本,沒有任何辦法改變50 這個長度. 79 # 這暗示了 db_index=True. 80 # 它接受一個額外的參數: prepopulate_from, which is a list of fields from which to auto-#populate 81 # the slug, via JavaScript,in the object's admin form: models.SlugField 82 # (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields. 83 84 <13> XMLField 85 #一個校驗值是否爲合法XML的 TextField,必須提供參數: schema_path, 它是一個用來校驗文本的 RelaxNG schema #的文件系統路徑. 86 87 <14> FilePathField 88 # 可選項目爲某個特定目錄下的文件名. 支持三個特殊的參數, 其中第一個是必須提供的. 89 # 參數 描述 90 # path 必需參數. 一個目錄的絕對文件系統路徑. FilePathField 據此獲得可選項目. 91 # Example: "/home/images". 92 # match 可選參數. 一個正則表達式, 做爲一個字符串, FilePathField 將使用它過濾文件名. 93 # 注意這個正則表達式只會應用到 base filename 而不是 94 # 路徑全名. Example: "foo.*\.txt^", 將匹配文件 foo23.txt 卻不匹配 bar.txt 或 foo23.gif. 95 # recursive可選參數.要麼 True 要麼 False. 默認值是 False. 是否包括 path 下面的所有子目錄. 96 # 這三個參數能夠同時使用. 97 # match 僅應用於 base filename, 而不是路徑全名. 那麼,這個例子: 98 # FilePathField(path="/home/images", match="foo.*", recursive=True) 99 # ...會匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif 100 101 <15> IPAddressField 102 # 一個字符串形式的 IP 地址, (i.e. "24.124.1.30"). 103 <16># CommaSeparatedIntegerField 104 # 用於存放逗號分隔的整數值. 相似 CharField, 必需要有maxlength參數.
1 <1> null : 數據庫中字段是否能夠爲空 2 3 <2> blank: django的 Admin 中添加數據時是否可容許空值 4 5 <3> default:設定缺省值 6 7 <4> editable:若是爲假,admin模式下將不能改寫。缺省爲真 8 9 <5> primary_key:設置主鍵,若是沒有設置django建立表時會自動加上: 10 id = meta.AutoField('ID', primary_key=True) 11 primary_key=True implies blank=False, null=False and unique=True. Only one 12 primary key is allowed on an object. 13 14 <6> unique:數據惟一 15 16 <7> verbose_name Admin中字段的顯示名稱 17 18 <8> validator_list:有效性檢查。非有效產生 django.core.validators.ValidationError 錯誤 19 20 21 <9> db_column,db_index 若是爲真將爲此字段建立索引 22 23 <10>choices:一個用來選擇值的2維元組。第一個值是實際存儲的值,第二個用來方便進行選擇。 24 如SEX_CHOICES= (( ‘F’,'Female’),(‘M’,'Male’),) 25 gender = models.CharField(max_length=2,choices = SEX_CHOICES)
1 from django.shortcuts import render,HttpResponse 2 from app01.models import * 3 # Create your views here. 4 5 6 def index(req): 7 return render(req,"index.html") 8 9 10 def addbook(req): 11 # 方式一 12 # b = Book(name="python基礎", price=99, author="alex", pub_date="2019-03-30") 13 # b.save() 14 # 方式二 15 Book.objects.create(name="linux", price=99, author="alex", pub_date="2019-03-30") 16 return HttpResponse("添加成功!")
1 from django.shortcuts import render,HttpResponse 2 from app01.models import * 3 # Create your views here. 4 5 6 def index(req): 7 return render(req, "index.html") 8 9 10 def update(req): 11 # 方式一 12 # Book.objects.filter(name="linux").update(price=199) 13 # 方式二 14 b = Book.objects.get(name="linux") 15 b.price = 299 16 b.save() 17 # 注:update是QuerySet對象的方法,get返回的是一個model對象,它沒有update方法,而filter返回的是一個QuerySet對象(filter裏面的條件可能有多個條件符合) 18 19 # 若想查看sql語句,須要在settings中加上日誌 20 # LOGGING = { 21 # 'version': 1, 22 # 'disable_existing_loggers': False, 23 # 'handlers': { 24 # 'console': { 25 # 'level': 'DEBUG', 26 # 'class': 'logging.StreamHandler', 27 # }, 28 # }, 29 # 'loggers': { 30 # 'django.db.backends': { 31 # 'handlers': ['console'], 32 # 'propagate': True, 33 # 'level': 'DEBUG', 34 # }, 35 # } 36 # } 37 return HttpResponse("修改爲功!")
1 from django.shortcuts import render,HttpResponse 2 from app01.models import * 3 # Create your views here. 4 5 6 def index(req): 7 return render(req, "index.html") 8 9 def delete(req): 10 Book.objects.filter(name="linux").delete() 11 return HttpResponse("刪除成功!")
1 # 查詢相關API: 2 3 # <1>filter(**kwargs): 它包含了與所給篩選條件相匹配的對象 4 5 # <2>all(): 查詢全部結果 6 7 # <3>get(**kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。 8 9 #-----------下面的方法都是對查詢的結果再進行處理:好比 objects.filter.values()-------- 10 11 # <4>values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列 model的實例化對象,而是一個可迭代的字典序列 12 13 # <5>exclude(**kwargs): 它包含了與所給篩選條件不匹配的對象 14 15 # <6>order_by(*field): 對查詢結果排序 16 17 # <7>reverse(): 對查詢結果反向排序 18 19 # <8>distinct(): 從返回結果中剔除重複紀錄 20 21 # <9>values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列 22 23 # <10>count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。 24 25 # <11>first(): 返回第一條記錄 26 27 # <12>last(): 返回最後一條記錄 28 29 # <13>exists(): 若是QuerySet包含數據,就返回True,不然返回False。
1 #擴展查詢,有時候DJANGO的查詢API不能方便的設置查詢條件,提供了另外的擴展查詢方法extra: 2 #extra(select=None, where=None, params=None, tables=None,order_by=None, select_params=None 3 4 (1) Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) 5 (2) Blog.objects.extra( 6 select=SortedDict([('a', '%s'), ('b', '%s')]), 7 select_params=('one', 'two')) 8 9 (3) q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) 10 q = q.extra(order_by = ['-is_recent']) 11 12 (4) Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
1 from django.shortcuts import render,HttpResponse 2 from app01.models import * 3 # Create your views here. 4 5 6 def index(req): 7 return render(req, "index.html") 8 9 10 def addbook(req): 11 # 方式一 12 # b = Book(name="python基礎", price=99, author="alex", pub_date="2019-03-30") 13 # b.save() 14 # 方式二 15 Book.objects.create(name="linux", price=99, author="alex", pub_date="2019-03-30") 16 return HttpResponse("添加成功!") 17 18 19 def update(req): 20 # 方式一 21 # Book.objects.filter(name="linux").update(price=199) 22 # 方式二 23 b = Book.objects.get(name="linux") 24 b.price = 299 25 b.save() 26 # 注:update是QuerySet對象的方法,get返回的是一個model對象,它沒有update方法,而filter返回的是一個QuerySet對象(filter裏面的條件可能有多個條件符合) 27 28 # 若想查看sql語句,須要在settings中加上日誌 29 # LOGGING = { 30 # 'version': 1, 31 # 'disable_existing_loggers': False, 32 # 'handlers': { 33 # 'console': { 34 # 'level': 'DEBUG', 35 # 'class': 'logging.StreamHandler', 36 # }, 37 # }, 38 # 'loggers': { 39 # 'django.db.backends': { 40 # 'handlers': ['console'], 41 # 'propagate': True, 42 # 'level': 'DEBUG', 43 # }, 44 # } 45 # } 46 return HttpResponse("修改爲功!") 47 48 49 def delete(req): 50 Book.objects.filter(name="linux").delete() 51 return HttpResponse("刪除成功!") 52 53 54 def select(req): 55 # book_list = Book.objects.all() 56 # print(book_list[0]) 57 58 book_list = Book.objects.filter(id=2) 59 60 # book_list = Book.objects.all()[:3] 61 62 # book_list = Book.objects.all().first() 63 64 # book_list = Book.objects.all().last() 65 66 # book_list = Book.objects.get(id=2) # 只能取一條記錄時纔不會報錯 67 68 # book_list = Book.objects.filter(author="alex").values("name") 69 70 # book_list = Book.objects.filter(author="alex").values_list("name") 71 72 # book_list = Book.objects.exclude(author="alex").values("name") 73 74 # book_list = Book.objects.filter(author="alex").values("name").distinct() 75 76 # book_list = Book.objects.filter(author="alex").values("name").distinct().count() 77 return render(req, "index.html", {"book_list": book_list})
1 <1>Django的queryset是惰性的 2 3 Django的queryset對應於數據庫的若干記錄(row),經過可選的查詢來過濾。例如,下面的代碼會得 4 到數據庫中名字爲‘Dave’的全部的人:person_set = Person.objects.filter(first_name="Dave") 5 上面的代碼並無運行任何的數據庫查詢。你可使用person_set,給它加上一些過濾條件,或者將它傳給某個函數, 6 這些操做都不會發送給數據庫。這是對的,由於數據庫查詢是顯著影響web應用性能的因素之一。 7 8 <2>要真正從數據庫得到數據,你能夠遍歷queryset或者使用if queryset,總之你用到數據時就會執行sql. 9 爲了驗證這些,須要在settings里加入 LOGGING(驗證方式) 10 obj=models.Book.objects.filter(id=3) 11 # for i in obj: 12 # print(i) 13 14 # if obj: 15 # print("ok") 16 17 <3>queryset是具備cache的 18 當你遍歷queryset時,全部匹配的記錄會從數據庫獲取,而後轉換成Django的model。這被稱爲執行 19 (evaluation).這些model會保存在queryset內置的cache中,這樣若是你再次遍歷這個queryset, 20 你不須要重複運行通用的查詢。 21 obj=models.Book.objects.filter(id=3) 22 23 # for i in obj: 24 # print(i) 25 ## models.Book.objects.filter(id=3).update(title="GO") 26 ## obj_new=models.Book.objects.filter(id=3) 27 # for i in obj: 28 # print(i) #LOGGING只會打印一次 29 30 <4> 31 簡單的使用if語句進行判斷也會徹底執行整個queryset而且把數據放入cache,雖然你並不須要這些 32 數據!爲了不這個,能夠用exists()方法來檢查是否有數據: 33 34 obj = Book.objects.filter(id=4) 35 # exists()的檢查能夠避免數據放入queryset的cache。 36 if obj.exists(): 37 print("hello world!") 38 39 <5>當queryset很是巨大時,cache會成爲問題 40 41 處理成千上萬的記錄時,將它們一次裝入內存是很浪費的。更糟糕的是,巨大的queryset可能會鎖住系統 42 進程,讓你的程序瀕臨崩潰。要避免在遍歷數據的同時產生queryset cache,可使用iterator()方法 43 來獲取數據,處理完數據就將其丟棄。 44 objs = Book.objects.all().iterator() 45 # iterator()能夠一次只從數據庫獲取少許數據,這樣能夠節省內存 46 for obj in objs: 47 print(obj.name) 48 #BUT,再次遍歷沒有打印,由於迭代器已經在上一次遍歷(next)到最後一次了,沒得遍歷了 49 for obj in objs: 50 print(obj.name) 51 52 #固然,使用iterator()方法來防止生成cache,意味着遍歷同一個queryset時會重複執行查詢。因此使 53 #用iterator()的時候要小心,確保你的代碼在操做一個大的queryset時沒有重複執行查詢 54 55 總結: 56 queryset的cache是用於減小程序對數據庫的查詢,在一般的使用下會保證只有在須要的時候纔會查詢數據庫。 57 使用exists()和iterator()方法能夠優化程序對內存的使用。不過,因爲它們並不會生成queryset cache,可能 58 會形成額外的數據庫查詢。
1 from django.db.models import Avg,Min,Sum,Max 2 3 從整個查詢集生成統計值。好比,你想要計算全部在售書的平均價錢。Django的查詢語法提供了一種方式描述全部 4 圖書的集合。 5 6 >>> Book.objects.all().aggregate(Avg('price')) 7 {'price__avg': 34.35} 8 9 aggregate()子句的參數描述了咱們想要計算的聚合值,在這個例子中,是Book模型中price字段的平均值 10 11 aggregate()是QuerySet 的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。鍵的名稱是聚合值的 12 標識符,值是計算出來的聚合值。鍵的名稱是按照字段和聚合函數的名稱自動生成出來的。若是你想要爲聚合值指定 13 一個名稱,能夠向聚合子句提供它: 14 >>> Book.objects.aggregate(average_price=Avg('price')) 15 {'average_price': 34.35} 16 17 18 若是你也想知道全部圖書價格的最大值和最小值,能夠這樣查詢: 19 >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) 20 {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
1 # F 使用查詢條件的值,專門取對象中某列值的操做 2 3 # from django.db.models import F 4 # models.Tb1.objects.update(num=F('num')+1) 5 6 7 # Q 構建搜索條件 8 from django.db.models import Q 9 10 #1 Q對象(django.db.models.Q)能夠對關鍵字參數進行封裝,從而更好地應用多個查詢 11 q1=models.Book.objects.filter(Q(title__startswith='P')).all() 12 print(q1)#[<Book: Python>, <Book: Perl>] 13 14 # 二、能夠組合使用&,|操做符,當一個操做符是用於兩個Q的對象,它產生一個新的Q對象。 15 Q(title__startswith='P') | Q(title__startswith='J') 16 17 # 三、Q對象能夠用~操做符放在前面表示否認,也可容許否認與不否認形式的組合 18 Q(title__startswith='P') | ~Q(pub_date__year=2005) 19 20 # 四、應用範圍: 21 22 # Each lookup function that takes keyword-arguments (e.g. filter(), 23 # exclude(), get()) can also be passed one or more Q objects as 24 # positional (not-named) arguments. If you provide multiple Q object 25 # arguments to a lookup function, the arguments will be 「AND」ed 26 # together. For example: 27 28 Book.objects.get( 29 Q(title__startswith='P'), 30 Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) 31 ) 32 33 #sql: 34 # SELECT * from polls WHERE question LIKE 'P%' 35 # AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06') 36 37 # import datetime 38 # e=datetime.date(2005,5,6) #2005-05-06 39 40 # 五、Q對象能夠與關鍵字參數查詢一塊兒使用,不過必定要把Q對象放在關鍵字參數查詢的前面。 41 # 正確: 42 Book.objects.get( 43 Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)), 44 title__startswith='P') 45 # 錯誤: 46 Book.objects.get( 47 question__startswith='P', 48 Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
1 python manage.py makemigrations 2 python manage.py migrate
1 LOGGING = { 2 'version': 1, 3 'disable_existing_loggers': False, 4 'handlers': { 5 'console':{ 6 'level':'DEBUG', 7 'class':'logging.StreamHandler', 8 }, 9 }, 10 'loggers': { 11 'django.db.backends': { 12 'handlers': ['console'], 13 'propagate': True, 14 'level':'DEBUG', 15 }, 16 } 17 }
注:若建立表失敗,請看:https://www.cnblogs.com/chenyanbin/p/10628646.html
admin是Django強大功能之一,它能從數據庫中讀取數據,呈如今頁面中,進行管理。默認狀況下,它的功能已經很是強大,若是你不須要複雜的功能,它已經夠用了,可是有時候,一些特殊的功能還須要定製,好比搜索功能。
1 在setting.py中修改如下選項 2 3 LANGUAGE_CODE = 'en-us' #LANGUAGE_CODE = 'zh-hans'
1 一、register 2 admin.site.register(Book,MyAdmin) 3 4 二、register的裝飾器 5 @admin.register(Book)
建立Django帳號
登錄admin
操做admin
一些經常使用的設置技巧
• list_display:指定要顯示的字段
• search_fields:指定搜索的字段
• list_filter:指定列表過濾器
• ordering:指定排序字段
1 from django.contrib import admin 2 from app01.models import * 3 # Register your models here. 4 5 # @admin.register(Book)#----->單給某個表加一個定製 6 class MyAdmin(admin.ModelAdmin): 7 list_display = ("title","price","publisher") 8 search_fields = ("title","publisher") 9 list_filter = ("publisher",) 10 ordering = ("price",) 11 fieldsets =[ 12 (None, {'fields': ['title']}), 13 ('price information', {'fields': ['price',"publisher"], 'classes': ['collapse']}), 14 ] 15 16 admin.site.register(Book,MyAdmin) 17 admin.site.register(Publish) 18 admin.site.register(Author)
參考文獻:http://www.admin10000.com/document/2220.html
Django練習百度雲盤:
連接:https://pan.baidu.com/s/1MYWFUt1W_o7gC7mz_2veuQ 提取碼:yz6a