一 路由系統進階(urls.py)css
動態路由html
urls.py中經過正則表達式的分組匹配,捕獲用戶訪問的url中的值,傳遞給視圖函數
1 分組匹配(經過圓括號):
至關於給視圖函數傳遞 位置參數前端
例子:jquery
1 from django.conf.urls import url 2 3 from . import views 4 5 urlpatterns = [ 6 url(r'^articles/2003/$', views.special_case_2003), 7 url(r'^articles/([0-9]{4})/$', views.year_archive), 8 url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), 9 url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), 10 ]
2 分組命名匹配:
至關於給視圖函數傳遞 關鍵字參數正則表達式
在Python的正則表達式中,分組命名正則表達式組的語法是(?P<name>pattern)
,其中name
是組的名稱,pattern
是要匹配的模式。數據庫
例子:django
1 from django.conf.urls import url 2 3 from . import views 4 5 urlpatterns = [ 6 url(r'^articles/2003/$', views.special_case_2003), 7 url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), 8 url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), 9 url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), 10 ]
3 namejson
防止將url硬編碼到咱們的業務邏輯代碼中,給url起別名
經過別名,反向找到 urlbootstrap
配置:後端
在views.py中:
from django.urls import reverse
具體的url = reverse('url別名')
例子:
urls.py裏面配置:
url(r'^publisher_list/$', views.publisher_list, name="alex")
vivews.py引用:
# def edit_publisher(request, edit_id): # print(reverse('alex')) # print("=" * 120) # if request.method == "POST": # new_name = request.POST.get("name888") # # 去數據庫修改出版社名字 # obj = models.Publisher.objects.get(id=edit_id) # obj.name = new_name # obj.save() # return redirect(reverse('alex')) #返回一個url # print(edit_id) # publisher_obj = models.Publisher.objects.get(id=edit_id) # return render(request, "edit_publisher.html", {"obj": publisher_obj})
4 傳參數的兩種寫法(一不當心就被坑了)
例子一:url傳參
1 urls.py配置:
url(r'^edit_publisher/$', views.edit_publisher),
2 views.py
3 def edit_publisher(request):
if request.method=="POST": 4 #獲取用戶更改的id 5 edit_id=request.POST.get("id")#從瀏覽器傳的參數獲取的id 6 new_name=request.POST.get("name")#從form表單獲取的名字 7 #去數據庫找到這條記錄 8 obj=models.Publisher.objects.get(id=edit_id) 9 obj.name=new_name 10 obj.save() 11 return redirect("/publisher_list/") 12 else: 13 edit_id = request.GET.get("id") 14 publisher_edit = models.Publisher.objects.get(id=edit_id) 15 return render(request,"edit_publisher.html",{"obj":publisher_edit})
注意:#上面紅色字體裏面的的obj必定要和你相應的edit_publisher裏面的value,裏面的一致,好比value=obj.name 這裏就必定用obj
3 html配置:
publisher_list.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>出版社列表</title> 6 <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> 7 </head> 8 <body> 9 <div class="container"> 10 <div class="row"> 11 <div class="col-md-8 col-sm-offset-2"> 12 <table class="table table-bordered"> 13 <tr> 14 <th>#</th> 15 <th>id</th> 16 <th>出版社名字</th> 17 <th>操做</th> 18 </tr> 19 20 {# data這裏必定要跟views裏面的data同樣#} 21 {% for publisher in data %} 22 <tr> 23 <td>{{ forloop.counter }}</td> 24 <td>{{ publisher.id }}</td> 25 <td>{{ publisher.name }}</td> 26 <td> 27 {# 這是動態傳參#} 28 {# <a href="/edit_publisher/{{ publisher.id }}/" class="btn btn-info">編輯</a>#} 29 {# 這是瀏覽器傳參數#} 30 <a href="/edit_publisher/?id={{ publisher.id }}" class="btn btn-info">編輯</a> 31 <a href="/del_publisher" class="btn btn-info">刪除</a> 32 </td> 33 </tr> 34 {% endfor %} 35 </table> 36 37 </div> 38 </div> 39 </div> 40 41 </body> 42 </html>
edit_publisher.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>編輯</title> 6 <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> 7 </head> 8 <body> 9 <form class="form-horizontal" action="" method="post"> 10 <input type="text" name="id" value="{{ obj.id }}" style="display: none"> 11 <div class="form-group"> 12 <label for="inputEmail3" class="col-sm-2 control-label">出版社名稱</label> 13 <div class="col-sm-10"> 14 <input type="text" class="form-control" name="name" value="{{ obj.name }}" id="inputEmail3" 15 placeholder="新名稱"> 16 </div> 17 </div> 18 19 <div class="form-group"> 20 <div class="col-sm-offset-2 col-sm-10"> 21 <button type="submit" class="btn btn-default">提交</button> 22 </div> 23 </div> 24 </form> 25 26 </body> 27 </html>
例子二 動態傳參
1 urls配置:
url(r'^edit_publisher/(\d+)/$', views.edit_publisher),
2 views.py配置
1 # def edit_publisher(request,edit_id): 2 # if request.method=="POST": 3 # #獲取用戶更改的id 4 # 5 # new_name=request.POST.get("name")#從form表單獲取的名字 6 # #去數據庫找到這條記錄 7 # obj=models.Publisher.objects.get(id=edit_id) 8 # print(obj.name) 9 # obj.name=new_name 10 # obj.save() 11 # return redirect("/publisher_list/") 12 # else: 13 # 14 # publisher = models.Publisher.objects.get(id=edit_id) 15 # return render(request,"edit_publisher.html",{"obj":publisher})
3 html配置:
publisher_list.html
<a href="/edit_publisher/{{ publisher.id }}/" class="btn btn-info">編輯</a>
edit_publisher.html不變
二 視圖函數進階(views.py)
1. 1-views.py
1.基礎必會三件套
1. HttpResponse('字符串')
2. render(request, "xx.html", {"key": value})
3. redirect("/其它的url/")
2. FBV(Function Base View) 基於函數的視圖
經過request.method == "POST" 去判斷
例子:
1 # def edit_publisher(request, edit_id): 2 # print(reverse('alex')) 3 # print("=" * 120) 4 # if request.method == "POST": 5 # new_name = request.POST.get("name888") 6 # # 去數據庫修改出版社名字 7 # obj = models.Publisher.objects.get(id=edit_id) 8 # obj.name = new_name 9 # obj.save() 10 # return redirect(reverse('alex')) 11 # print(edit_id) 12 # publisher_obj = models.Publisher.objects.get(id=edit_id) 13 # return render(request, "edit_publisher.html", {"obj": publisher_obj})
3. CBV(Class Base View) 基於類的視圖
1. 必須繼承views.View -->在views.py裏面導入: from django import views
2. 寫一個本身的視圖類
3. 經過定義不一樣的方法,來處理用戶不一樣的請求
4. 在urls.py中註冊視圖的時候要寫 views.類名.as_view()
urls.py中配置:
url(r'^edit_publisher/(?P<edit_id>\d+)/$', views.EditPublisher.as_view(), name="wusir"),
view.py配置:
例子:
1 class EditPublisher(views.View): 2 def get(self, request, edit_id): 3 publisher_obj = models.Publisher.objects.get(id=edit_id) 4 return render(request, "edit_publisher.html", {"obj": publisher_obj}) 5 6 def post(self, request, edit_id): 7 new_name = request.POST.get("name888") 8 # 去數據庫修改出版社名字 9 obj = models.Publisher.objects.get(id=edit_id) 10 obj.name = new_name 11 obj.save() 12 return redirect(reverse('alex'))
2.1 request對象的經常使用屬性和方法(經常使用的幾個)
request表示的是和用戶請求相關的全部數據
1. request.method --> 用戶當前請求的請求方法
2. request.GET --> 用戶請求中url中的參數
3. request.POST --> 用戶POST請求的數據
4. request.path_info --> 用戶訪問的url路徑是什麼
3.1 Django上傳文件
1. 前端頁面
1. form表單必定要有action,method必須是post
2. 必定要配置enctype="multipart/form-data
2. 後端:
def upload(request): """ 保存上傳文件前,數據須要存放在某個位置。默認當上傳文件小於2.5M時,django會將上傳文件的所有內容讀進內存。從內存讀取一次,寫磁盤一次。 但當上傳文件很大時,django會把上傳文件寫到臨時文件中,而後存放到系統臨時文件夾中。 :param request: :return: """ if request.method == "POST": # 從請求的FILES中獲取上傳文件的文件名,file爲頁面上type=files類型input的name屬性值 filename = request.FILES["file"].name # 在項目目錄下新建一個文件 with open(filename, "wb") as f: # 從上傳的文件對象中一點一點讀 for chunk in request.FILES["file"].chunks(): # 寫入本地文件 f.write(chunk) return HttpResponse("上傳OK")
4.1 JsonResponse
專門用來返回JSON格式數據的響應對象
from django.http import JsonResponse
例子:
from django.http import JsonResponse response = JsonResponse({'foo': 'bar'}) print(response.content) b'{"foo": "bar"}'
默認只能傳遞字典類型,若是要傳遞非字典類型須要設置一下safe關鍵字參數。
例子:
urls.py url(r'^json_test/$', views.JsonTest.as_view()), views.py class JsonTest(views.View): def get(self, request): res = {"code": 0, "data": "alex"} res2 = ["alex", "污Sir", "金老闆", "小姨媽", "MJJ"] return JsonResponse(res2,safe=False)
三 模板引擎進階
1 模板語法:
1. 兩個語法:
1. {{ }} --> 跟變量相關的操做
2. {% %} --> 跟邏輯相關的操做
2. 變量相關
1. 傳字典或對象類型的數據 obj.name/obj.age
2. 傳數組類型的數據 obj.索引值
例子:
1 def template_test(request): 2 l = [11, 22, 33] 3 d = {"name": "alex"} 4 5 class Person(object): 6 def __init__(self, name, age): 7 self.name = name 8 self.age = age 9 10 def dream(self): 11 return "{} is dream...".format(self.name) 12 13 Alex = Person(name="Alex", age=34) 14 Egon = Person(name="Egon", age=9000) 15 Eva_J = Person(name="Eva_J", age=18) 16 17 person_list = [Alex, Egon, Eva_J] 18 return render(request, "template_test.html", {"l": l, "d": d, "person_list": person_list})
取值:
{# 取l中的第一個參數 #} {{ l.0 }} {# 取字典中key的值 #} {{ d.name }} {# 取對象的name屬性 #} {{ person_list.0.name }} {# .操做只能調用不帶參數的方法 #} {{ person_list.0.dream }}
3. 日期格式化
<p>{{ today|date:"Y-m-d H:i:s"}}</p>
4. 顯示真正的html代碼
<p>{{ link|safe }}</p>
例子:
view配置:
1 def template_test(request): 2 data = ["金老闆", "景女神", "MJJ"] 3 # data = "" 4 filesize = 1234567890 5 import datetime 6 today = datetime.datetime.today() 7 link = "<script>for(;;){alert(123)}</script>" 8 9 10 class Person(object): 11 def __init__(self, name, dream): 12 self.name = name 13 self.dream = dream 14 15 def dream(self): 16 return "個人夢想是學好Python!" 17 pw = Person("彭瑋", "不去下一期!") 18 19 return render(request, "t.html", { 20 "data": data, 21 "file_size": filesize, 22 "today": today, 23 "link": link, 24 "person": pw 25 })
html中配置:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 9 10 {#<p>{{ data.1 }}</p>#} 11 <p>{{ data|default:"暫無數據" }}</p> 12 <p>{{ file_size|filesizeformat }}</p> 13 <p>{{ today }}</p> 14 15 16 <p>{{ link }}</p> 17 {#<p>{{ link|safe }}</p>#} 18 19 <hr> 20 21 <p> 22 {% for teacher in data %} 23 {% if forloop.last %} 24 {{ teacher }} 25 {% else %} 26 {{ teacher }}, 27 {% endif %} 28 {% endfor %} 29 </p> 30 {#<p>{% if 3 > 2 > 1 %}{% endif %}</p>#}(不支持這樣寫) 31 {##} 32 {#<p>{% if 3 > 2 and 2 > 1 %}{% endif %}</p>#} 33 34 <hr> 35 36 {{ person.name }} 37 {{ person.dream }} 38 39 40 </body> 41 </html>
2. 母板
1. 爲何要用母版?
不一樣的頁面有大量重複的代碼,咱們能夠把公用的部分提取出來放在單獨一個文件
2. 怎麼使用?
1.1. 在子頁面 經過使用 {% extends ‘模板名’ %} --> 放在子頁面的最上面
2. 1{% block xx %}{% endblock %}
母版例子:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>{{ html_title }}</title> 6 <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> 7 {% block page-css %} 8 9 {% endblock %} 10 </head> 11 <body> 12 {% include 'nav.html' %} 13 <div class="container"> 14 <div class="row"> 15 <div class="col-md-8 col-md-offset-2"> 16 17 {% block page-main %} 18 19 {% endblock %} 20 21 </div> 22 </div> 23 </div> 24 <script src="/static/jquery.js"></script> 25 {% block page-js %} 26 27 {% endblock %} 28 </body> 29 </html>
3. 組件
能夠將經常使用的頁面內容如導航條,頁尾信息等組件保存在單獨的文件中,而後在須要使用的地方按以下語法導入便可。
使用 {% include '組件名' %}導入
如何繼承母版例子:
1 {% extends 'mama.html' %} 2 3 {% block page-main %} 4 <table class="table table-bordered"> 5 <thead> 6 <tr> 7 <th>#</th> 8 <th>id</th> 9 <th>出版社名稱</th> 10 <th>操做</th> 11 </tr> 12 </thead> 13 <tbody> 14 {% for publisher in publisher_list %} 15 <tr> 16 <td>{{ forloop.counter }}</td> 17 <td>{{ publisher.id }}</td> 18 <td>{{ publisher.name }}</td> 19 <td> 20 <a href="/edit_publisher/{{ publisher.id }}/" class="btn btn-info">編輯</a> 21 <a href="/delete_publisher/" class="btn btn-danger">刪除</a> 22 </td> 23 </tr> 24 {% endfor %} 25 </tbody> 26 </table> 27 28 {% endblock %} 29 30 {#我這個頁面纔用到的一個js文件#} 31 {% block page-js %} 32 <script src="/static/1.js"></script> 33 {% endblock %}
四 CSRF
1. 爲何要有csrf_token?
2. Django中如何使用?
在render的頁面上寫上{% csrf_token %}
3. 若是是form表單形式提交,必須放在form表單中
4 若是不加csrf_token默認是不讓提交的報403錯誤
例子:
urls.py配置
1 url(r'^csrf_test/$', views.csrf_test),
views.py配置:
def csrf_test(request): if request.method=="POST": print(request.POST) return HttpResponse("OK") else: return render(request,"csrf_test.html")
html配置:
<form action="" method="post"> {% csrf_token %} <input type="text" name="name"> <input type="submit" value="提交"> </form>