17-1 djanjo進階-路由,視圖,模板

一 路由系統進階(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>
View Code

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>
View Code

例子二 動態傳參

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     })
View Code

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>
View Code

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>
View Code

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 %}
View Code

 四 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>
相關文章
相關標籤/搜索