Django的平常-視圖層

Django的平常-3

JsonResponse

在以前咱們就知道,不一樣語言或者說系統之間,Json格式的數據是通用性最好的,因此咱們一般會選擇用json格式來從後端向前端傳輸數據,在Django裏面,咱們不須要像以前那樣導入json模塊而後用json.dumps和json.loads來打包和解析json數據,由於咱們有一個專門的函數來作json數據的轉換,就叫作JsonResponse.前端

# 首先咱們仍是須要導入這個函數
from django.http import JsonResponse
# 下面的內容咱們須要寫在一個函數裏面,方便調用
def index(request):
    user = {'username':'nick哈哈哈','pwd':'123'}
    return JsonResponse(user,json_dumps_params={'ensure_ascii':False})
    l = [1, 2, 3, 4, 5, 5, 6]
    return JsonResponse(l, safe=False)
'''
在使用JsonResponse模塊的時候,要注意的幾點是:
    1. JsonResponse默認只支持序列化字典 若是你想序列化其餘類型(json可以支持的類型) 你須要將safe參數由默認的True改爲False,好比 JsonResponse(l, safe=False)
    2. 在用JsonResponse序列化的時候,若是內容裏面有中文,會自動被解析成二進制碼,因此若是咱們想要保留中文的話,須要在給JsonResponse傳值的時候加入json_dumps_params={'ensure_ascii':False},即不自動解析,這樣就能保留原始數據裏面的中文,例如JsonResponse(user,json_dumps_params={'ensure_ascii':False})
'''

form表單上傳文件

咱們知道form表單是在前端,也就是html文件裏面寫的一種格式,能夠用來給後端傳一些數據,或者上傳文件,下面舉例form的寫法python

# up.html文件裏面
<form action="" method="post" enctype="multipart/form-data">
    <input type="text" name="username">
    <input type="file" name="myfile">
    <input type="submit">
'''
這裏要注意兩點:
    1. form表單在向後端傳輸數據的時候,method方法必須是post
    2. enctype參數必須設置爲"multipart/form-data"
'''
    
    
# views.py後端
def up(request):
    if request.method == 'POST':
        print(request.POST)     # 能夠取到請求的內容
        print(request.FILES)    
        # 獲取文件對象
        file_obj = request.FILES.get('myfile')  # 這裏的別名是前端的html文件裏定義的別名
        print(file_obj.name)  # 獲取文件名
        with open(file_obj.name, 'wb') as f:
            for chunk in file_obj.chunks(): 
                f.write(chunk)
    return render(request, 'up.html')

CBV的源碼分析

首先,咱們要知道CBV的全程爲Class Based View,也就是基於類的視圖,下面咱們經過一個實例來看一下這個東西的做用django

#urls.py    
urlpatterns = [
    url(r'^reg/',views.MyReg.as_view()),
    #其實上面這句url至關於 url(r'^reg/',views.MyReg.get()),或者 url(r'^reg/',views.MyReg.post()),
]

#views.py
class MyReg(View):
    def get(self, request):
        return render(request, 'reg.html')

    def post(self,request):
        return HttpResponse("我是MyReg類中post方法")

#reg.html
<body>
<form action="" method="post">

    <input type="submit">
</form>
</body>

咱們在寫完以上代碼並執行起來之後,輸入網址http://127.0.0.1:8000/reg/,能夠看到有個提交按鈕,按下以後咱們能夠看到"我是MyReg類中post方法"這句話,那麼問題就來了,這個邏輯是怎樣的,咱們定義的MyReg類是怎麼斷定你發來的是get仍是post請求的,下面咱們詳細分析一波.json

咱們先來看路由層裏面,url裏所使用的的as_view的部分源碼如何:後端

#base.py  class View/as_view源碼
class View(object):
    def as_view(cls, **initkwargs):
            def view(request, *args, **kwargs):
                self = cls(**initkwargs)  # cls就是咱們本身的寫的MyReg類
                if hasattr(self, 'get') and not hasattr(self, 'head'):
                    self.head = self.get
                self.request = request
                self.args = args
                self.kwargs = kwargs
                # 上面的操做 就是給咱們本身寫的類的對象賦值
                return self.dispatch(request, *args, **kwargs)
            # 這裏咱們看到,最終返回的是self調用dispatch方法,因此咱們再找到dispatch的源碼來看
            return view
        
# dispatch源碼
    def dispatch(self, request, *args, **kwargs):
            if request.method.lower() in self.http_method_names:  # 判斷當前請求方式在不在默認的八個請求方式中,其實咱們最經常使用的就是post和get請求
                '''
                八種請求方式爲:GET,HEAD,POST,PUT,DELETE,CONNECT,OPTIONS,TRACE
                '''
                handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
                # handler = getattr(本身寫的類產生的對象,'小寫的請求方法(get\post)','獲取不到對應的方法就報錯')
                # handler就是咱們本身定義的跟請求方法相對應的方法的函數內存地址
                # 咱們用反射就是從類對象來反射出來並獲取其生成時候的方法,最後返回調用該方法
            else:
                handler = self.http_method_not_allowed
            return handler(request, *args, **kwargs)  # 在調用獲取到的方法

視圖層

模板傳值

模板傳值,其實就是把存在於後端的變量值傳到前端並經過模板的形式展現出來,模板語法,最經常使用的符號有兩種,即{{}},{% %},其中{{}}裏面寫入變量相關的內容,{% %}裏面寫入邏輯相關的內容.安全

實例以下:dom

#views.py 後端

from datetime import datetime
from django.utils.safestring import mark_safe
def login(request):
    n = 123
    f = 12.12
    s = '你妹的 真難'
    l = [1, 2, 3, 4, 5, 6]
    d = {'username': 'jason', 'password': [123, 222, 444]}
    t = (1, 2, 3, 4, 5)
    se = {1, 2, 3, 4}
    b = True
    ctime = datetime.now()
    file_size = 342384234234
    w = '奧術 大師件 大事肯德 基按 實際對 拉 螺栓空當接 龍'
    w1 = 'asdash ashd jkh sadas asdjjs had sjklad j a kjkjdsklas dkjsakldj dlsjakld '
    w2 = 'he llow ord wqe asdsad sadsadsa dsadasds adasds adsadsadsada sdsad'

    def func():
        return '你好~'


    obj = MyClass()

    sss = "<h1>一臉懵逼</h1>"
    sss1 = "<script>alert(123)</script>"
    sss2 = "<a href='http://www.baidu.com'>好好學習</a>"
    # mark_safe,轉義,即咱們會認定這個語句安全,而後讓其轉義以後再發送給前端,讓前端能夠直接顯示出其特定格式
    res = mark_safe(sss2)

    xo = '123213213'
    xo1 = 222

    yyy = {'user_list': [1, '22', {'username': ['jason', 'egon']}]}
    return render(request, 'login.html', locals())




#login.html 前端
<body>
<p>{{ n }}</p>
<p>{{ f }}</p>
<p>{{ s }}</p>
<p>{{ l }}</p>
<p>{{ d }}</p>
<p>{{ se }}</p>
<p>{{ t }}</p>
<p>{{ b }}</p>
{#以上數值類型均可以直接傳值並顯示出來#}
    
    
{#若是傳遞給前端一個函數名,會直接加括號調用,將函數的返回值展現到前端,尤爲須要注意的是!!!!!django的模板語法,不支持給函數傳參,不支持傳參,不支持傳參,不支持傳參#}
<p>{{ func }}</p>


{#方法也都不能傳參#}
<p>{{ obj }}</p>
<p>{{ obj.get_cls }}</p>
<p>{{ obj.get_func }}</p>
<p>{{ obj.get_self }}</p>

{#模板語法取值,這裏要注意,django模板語法在獲取容器類型內部元素的值的時候,要統一採用句點符的形式取值,也就是(.),不支持別的取值方式#}
<p>{{ l.1 }}</p>
<p>{{ l.3 }}</p>

<p>{{ d.username }}</p>
<p>{{ d.password }}</p>
<p>{{ d.password.1 }}</p>
    
{#前面的變量有值就拿值,沒值就用後面默認的,前面變量不存在的狀況下也是顯示後面的默認值#}
<p>{{ xo|default:'hello' }}
</body>

過濾器

django的過濾器的做用有些相似於咱們以前學習的函數的內置方法,其用法就是:函數

會將|左邊的值當作過濾器的第一個參數 ,|右邊的當前過濾器第二個參數.oop

下面咱們介紹幾種經常使用的過濾器

# login.html
<body>

{#add,若是二者都是數值會相加,若是都是字符串會拼接#}
<p>{{ n|add:100 }}</p>
<p>{{ n|add:'abc' }}</p>
<p>{{ s|add:'sasahhdasda' }}</p>
    
{#upper,大寫#}    
<p>{{ n|upper}}</p>
    
{#lenth,返回前者的長度,經常使用於容器類的元素#}
<p>{{ l|length }}</p>
<p>{{ d|length }}</p>
    
{#capfirst會把第一個字母大寫#}
<p>{{ s|capfirst }}</p>
    
{#random,返回列表中隨機的一項#}
<p>{{ l|random }}</p>

{#filesizeformat,會把數值當作文件大小,並轉換成最合適的單位,好比MB,好比GB,好比TB#}
<p>{{ file_size|filesizeformat }}</p>
    
{#truncatechars,truncatewords 按字符截取和按單詞截取#}
<p>截取10個字符 三個點也算{{ w1|truncatechars:10 }}</p>
<p>截取10個字符 三個點也算{{ w|truncatechars:10 }}</p>
<p>安裝空格截取單詞 三個點不算{{ w1|truncatewords:6 }}</p>
<p>安裝空格截取單詞 三個點不算{{ w|truncatewords:6 }}</p>
<p>安裝空格截取單詞 三個點不算{{ w2|truncatewords:6 }}</p>
    
{#切片,支持索引切片#}
<p>{{ l|slice:'0:5' }}</p>
<p>{{ l|slice:'0:5:2' }}</p>
    
{#date,將日期格式化#}
<p>{{ ctime|date:'Y-m-d' }}</p>
<p>{{ ctime|date:'Y年/m月' }}</p>
    
{#safe,語句安全,支持轉義,即咱們語句中的符合前端的語法會被轉義並顯示出來,這種寫法是前端轉義#}
<p>{{ sss|safe }}</p>
<p>{{ sss1|safe }}</p>
    
{#該句是在後端轉義完畢以後傳到前端的#}
<p>{{ res }}</p>
</body>

#view.py
#這裏的login函數仍是用上面模板傳值的

標籤

django裏面的經常使用標籤即if判斷和for循環

# login.html

<body>

{#if...else判斷#}
{% if xo %}
    <p>xo有值</p>
{% else %}
    <p>xo沒有值</p>
{% endif %}

    
{#if...elif...else#}
{% if xo %}
    <p>xo有值</p>
{% elif xo1 %}
    <p>xo1有值</p>
{% else %}
    <p>去他大爺的</p>
{% endif %}

    
{#for...#}    
{% for foo in l %}
    {% if forloop.first %}
        <p>這是個人第一次</p>
    {% elif forloop.last %}
        <p>這是最後一次了啊</p>
    {% else %}
        <p>嗨起來 大寶貝~</p>
    {% endif %}
{% endfor %}


    
{#設置empty,若是循環體xo爲空的話,會返回empty裏面的內容#}    
{% for foo in xo %}
    <p>{{ forloop.counter }}:{{ foo }}</p>
    {% empty %}
    <p>你給個人對象是個空的無法進行for循環</p>
{% endfor %}


    
{#對字典裏的值進行循環取值,包括items鍵值對,keys關鍵字以及values值#}    
{% for foo in d.items %}
    <p>{{ foo }}</p>
{% endfor %}

{% for foo in d.keys %}
    <p>{{ foo }}</p>
{% endfor %}

{% for foo in d.values %}
    <p>{{ foo }}</p>
{% endfor %}


{#對取到的值起一個別名,這樣在endwith的結構體裏面就能夠直接用這個別名來調用#}
<p>{{ yyy.user_list.2.username.1 }}</p>

{% with  yyy.user_list.2.username.1 as dsb %}
    <p>{{ dsb }}</p>
    <p>{{ yyy.user_list.2.username.1 }}</p>
{% endwith %}
</body>

自定義過濾器和標籤

咱們在自定義過濾器和標籤的時候,要牢記如下三個步驟:

  1. 首先咱們要在應用名下新建一個文件夾,名爲templatetags,注意,名字不能錯,否則django會找不到這個東西以致於自定義的過濾器和標籤都不生效

  2. 在剛剛建立的templatetags文件夾下面新建一個py文件,名字任意,咱們這裏起名字叫作my_tag.py

  3. 在該my_tag.py文件裏寫入如下兩行代碼

    # my_tag.py
    from django.template import Library
    
    register = Library()

作完以上三步咱們就能夠來寫本身的過濾器和標籤了,一樣是在這個my_tag.py文件裏寫

自定義過濾器以下:

# my_tag.py
@register.filter(name='myplus') #給過濾器起別名爲myplus,調用的時候用別名便可
def index(a, b):
    return a + b
# 這個過濾器的做用便是將傳入的兩個參數相加,而後返回
# 另外,過濾器最多隻能穿兩個參數,不能多於兩個參數

自定義過濾器的調用:

# login.html,在前端調用
<body>
{% load my_tag %}
{{ 123|myplus:123 }}
# 顯示的結果爲246
</body>

自定義標籤以下:

# my_tag.py
@register.simple_tag(name='mysm')
def login(a, b, c, d):
    return '%s/%s/%s/%s' % (a, b, c, d)

自定義標籤的調用:

# login.html
<body>
{% mysm 1 2 3 4 %}
</body>

要注意的一點是,自定義標籤是不能在if判斷裏面使用的,可是自定義過濾器能夠.

相關文章
相關標籤/搜索