19 Jun 18 Django


19 Jun 18

一、作業講解(代碼統計)

# views.py

 

from django.shortcuts import HttpResponse,render,redirect

import shutil

import os

import uuid

 

# 導入settings的方式

from django.conf import settings

 

ACCEPT_FILE_TYPE  = ['zip','tar','gztar','bztar','xztar','rar'] # 可以給一個全局變量,放在配置文件中,用之前導入

 

def upload(request):

    if request.method == 'POST':

        file_obj = request.FILES.get('file')

        filename, suffix = file_obj.name.rsplit('.',maxsplit=1)

        if suffix not in ACCEPT_FILE_TYPE: # 增加強健性

            return HttpResponse('wrong file type')

        with open(file_obj.name,'wb') as f:

            for chunk in file_obj.chunks():  # 從上傳文件對象一點一點讀取數據

                f.write(chunk)

        real_file_path = os.path.join(settings.BASE_DIR,file_obj.name)  # 拼接得到上傳文件的全路徑

        upload_path = os.path.join(settings.BASE_DIR,'files',str(uuid.uuid4()))  # 對上傳的文件做處理

        shutil.unpack_archive(real_file_path,extract_dir=upload_path)  # 解壓代碼文件至指定文件夾

        total_num = 0

        for (dir_path,dir_names,filenames) in os.walk(upload_path):

        # os.walk() 用來遍歷所有的文件,可以拿到以下三個參數

        # dir_path: 根目錄dir_names: 文件夾filenames: 文件

            for filename in filenames:

                file_path = os.path.join(dir_path,filename)  # 將文件名和根目錄拼接成完整的路徑

                file_path_list = file_path.rsplit('.',maxsplit=1)

                if len(file_path_list) != 2:

                    continue

                if file_path_list[1] != 'py':

                    continue

                line_num = 0

                with open(file_path,'r') as f:

                    for line in f:

                        if line.strip().startswith('#'):

                           continue

                        line_num += 1

                total_num += line_num

        return

render(request,'done.html',{'file_name':file_obj.name,'file_size':file_obj.size,'total_num':total_num})

    return render(request,'upload.html')

二、內容補充

目前,this和箭頭函數一起使用可能出現問題。所以,推薦盡量少用箭頭函數;但要能看懂。

 

三、今日內容

  1. 模版語言剩下的

http://www.cnblogs.com/liwenzhou/p/7931828.html

  1. csrf_token: 用於跨站請求偽造保護。是Django提供的一個解決方案:在提交表單時帶着之前Django給該頁面生成的token,如果沒有token,或token匹配失敗,將拒絕繼續訪問;這樣,釣魚網站就不可以通過單單設置action,而跳轉至正經網站某個頁面,進而修改正經網站的數據庫。

在頁面的form表單里面寫上{% csrf_token %},在settings中即可不注釋csrf相關

 

#釣魚網站html

<h1>這是一個釣魚網站</h1>

<formaction="http://127.0.0.1:8000/zhuanzhang/"method="post">

# action直接跳轉到別的網站

    <p>轉給誰:<input type="text"></p>

    <p><input style="display: none" type="text" name="id" value="3"></p>

    <p>轉多少:<input type="text" name="num"></p>

    <p>密碼:<input type="password" name="pwd"></p>

    <p><input type="submit" value="提交"></p>

</form>

 

#正經網站html

<h1>這是一個正經網站</h1>

<formaction="/zhuanzhang/"method="post">

    {% csrf_token %}  # 阻止跨站請求偽造

    <p>轉給誰:<input type="text" name="id"></p>

    <p>轉多少:<input type="text" name="num"></p>

    <p>密碼:<input type="password" name="pwd"></p>

    <p><input type="submit" value="提交"></p>

</form>

 

   ps:如果不設置數據庫,使用默認的數據庫db.sqlite3

 

  1. 靜態文件相關(取代硬編碼(/static/…))

如果有改static這個名字的需求,用硬編碼要通篇改;如果使用以下方式,則不存在這個問題;一般來說,上述需求比較不常見

{% load static %}

<img src="{% static "images/hi.jpg" %}" alt="Hi!" />

 

引用JS文件時使用:

{% load static %}

<script src="{% static "mytest.js" %}"></script>

 

某個文件多處被用到可以存為一個變量

{% load static %}

{% static "images/hi.jpg" as myphoto %}

<img src="{{ myphoto }}"></img>

 

  1. get_static_prefix

# 極少使用

{% load static %}

<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />

 

{% load static %}

{% get_static_prefix as STATIC_PREFIX %}

<img src="{{ STATIC_PREFIX }}images/hi.jpg"alt="Hi!" />

<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

 

  1. 自定義simpletag和自定義filter類似,只不過接收更靈活的參數。

自定義的filter,simpletag和inclusion_tag都要放在templatetags 這個新建的package中的py文件下

filter: {{ }}   在變量的基礎上做額外的調整

simpletag  {% %}  可傳多個參數,返回它們之間所做運算的結果

定義注冊simple tag

@register.simple_tag(name="plus")

def plus(a, b, c):

return "{} + {} + {}".format(a, b, c)

 

使用自定義simple tag

{% load app01_demo %}

{% plus "1" "2" "abc" %}

 

  1. inclusion_tag:多用於返回html代碼片段;后續項目會使用

# templatetags/my_inclusion.py

 

from django import template

register = template.Library()

 

@register.inclusion_tag('result.html')

def show_results(n):

    n = 1 if n < 1 else int(n)

    data = ["第{}項".format(i) for i in range(1, n+1)]

    return {"data": data}

 

templates/snippets/result.html

 

<ul>

  {% for choice in data %}

    <li>{{ choice }}</li>

  {% endfor %}

</ul>

 

templates/index.html

 

<!DOCTYPE html>

<html lang="en">

<head>

 <meta charset="UTF-8">

 <meta http-equiv="x-ua-compatible" content="IE=edge">

 <meta name="viewport" content="width=device-width, initial-scale=1">

 <title>inclusion_tag test</title>

</head>

<body>

{% load inclusion_tag_test %}

{% show_results 10 %}

</body>

</html>

 

  1. urls.py(路由系統)

http://www.cnblogs.com/liwenzhou/p/8271147.html

    a. URLconf配置

    # 基本格式:

    from django.conf.urls import url

 

    urlpatterns = [

    url(正則表達式, views視圖函數,參數,別名),

    ]

 

     # 在Django2.0 中用path替換了url(from django.urls import path)

 

    b. 正則表達式詳解

       1)urlpatterns中的元素按照書寫順序從上往下逐一匹配正則表達式,一旦匹配成功則不再繼續。

       2)若要從URL中捕獲一個值,只需要在它周圍放置一對圓括號(分組匹配)。

       3)不需要添加一個前導的反斜杠,因為每個URL 都有。例如,應該是^articles 而不是^/articles。

          # Django settings.py配置文件中默認沒有APPEND_SLASH 這個參數,但 Django 默認這個參數為APPEND_SLASH = True。 其作用就是自動在網址結尾加'/'。可設置APPEND_SLASH = False,改變默認值。

       4)每個正則表達式前面的'r' 是可選的但是建議加上。

 

    c. 正則匹配的模式

        1) 分組匹配      --> 調用視圖函數的時候額外傳遞位置參數;正則表達式分組匹配(通過圓括號)來捕獲URL中的值並以位置參數形式自動傳遞給視圖的args。

           # *args, agrs = (a,b)

           url(r'^articles/([0-9]{4})/$', views.year_archive),

 

        2) 分組命名匹配   --> 調用視圖函數的時候額外傳遞關鍵字參數

           url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

 

        注意:

           a) 要么全都用分組匹配,要么全都用分組命名匹配,不要混着用!

           b) Django utl正則表達式匹配的位置:從第一個斜線到問號之前這一段的路徑

           c) URL正則表達式捕獲的值都是字符串類型,如果要參與后續運算,應先進行類型轉換。

           d) 可以給視圖函數的參數設置默認值

# 正則匹配時,不論是否分組\帶參數,即都可以調用views中的page方法

               # urls.py中

               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),

               ]

 

               # views.py中,可以為num指定默認值

               def page(request, num="1"):

                   pass

 

    d. include 分級路由(級級匹配:/app01/upload; 在第一級匹配app01,在第二級匹配upload)

       # 推薦在各個app下建立自己的urls.py

       查找的順序:請求--> project/urls.py  --> app/urls.py  --> app/views.py

 

       from django.conf.urls import include, url

 

       urlpatterns = [

          url(r'^admin/', admin.site.urls),

          url(r'^blog/', include('blog.urls')),  # 可以包含其他的URLconfs文件

       ]

 

    e. 傳遞額外的參數給視圖函數

       from django.conf.urls import url

       from . import views

 

       urlpatterns = [

          url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),

       ]

 

    f. URL匹配規則的別名(命名URL和URL反向解析(別名->正則表達式(URL)))

        1) 起別名是為了,增加代碼的健壯性,不將URL硬編碼到代碼中!

 

        2) 用法

            a) 在views.py中如何根據別名找到url

                from django.urls import reverse

                url = reverse('別名')

 

            b) 在模板語言中如何根據別名找到url

                {% url '別名' %}

 

        3) 帶參數的url如何反向生成?

            a) 位置參數

                i) 在views.py中:

                    reverse("別名", args=(參數1, 參數2, ...))

 

                ii) 在模板語言中:

                    {% url "別名" 參數1, 參數2... %}

 

            b). 關鍵字參數

                i) 在views.py中:

                    reverse("別名", kwargs={"k1":參數1, ...})

 

                ii) 在模板語言中:

                    {% url "別名" 參數1, 參數2... %}

                    # 在模版語言中,無法傳遞關鍵字參數,只能根據位置,依次傳參

 

        4) namespace(命名空間), 是include的一個參數

           # 使用include語法,將其他的urls.py 包含進來

            from django.conf.urls import url, include

 

            urlpatterns = [

               url(r'^app01/', include('app01.urls', namespace='app01')),

               url(r'^app02/', include('app02.urls', namespace='app02')),

            ]

 

            語法:'命名空間名稱:URL名稱'

 

            # 這樣兩個app中url名稱重復了,反轉URL的時候就可以通過命名空間的名稱得到當前的URL;即使app中URL的命名相同,也可以反轉得到正確的URL了。

            模板中使用:

            {% url 'app01:detail' pk=12 pp=99 %}

 

            views中的函數中使用

            v = reverse('app01:detail', kwargs={'pk':11})

 

四、今日作業

用一個函數一個URL匹配模式實現 書書籍表、作者表、出版社表的展示和刪除操作

關鍵點:

  1. URL匹配模式的設計(分組匹配或分組命名匹配;給URL匹配模式起別名)

2. 反射:由一個字符串,找到對應的類變量

3. URL的反向解析(別名--> 完整的URL)

4. 正則表達式

import re

# 寫一個正則表達式, 只能從add delete edit list  這四個單次里面選一個

s1 = "delete"  # 匹配成功

s2 = "cut"  # 匹配不成功

 

r = re.compile(r'add|delete|edit|list')

print(r.match(s1))

print(r.match(s2))

 

# urls.py

url(r'(?P<operation>list|delete)_(?P<table_name>[a-zA-Z]+)/', views.op, name = 'list_delete'),

 

# views.py

def op(request,operation,table_name):

    table = table_name.capitalize()

    if hasattr(models,table):

        class_obj = getattr(models,table)

        if operation.upper() == 'LIST':

            ret = class_obj.objects.all()

            return render(request,'{}_{}.html'.format(table_name,operation),{'ret':ret})

        elif operation.upper() == 'DELETE':

            id = request.GET.get('id')

           class_obj.objects.get(id=id).delete()

            url = reverse('list_delete', kwargs={'operation':'list','table_name':table_name})

            return redirect(url)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM