1. 程式人生 > >Django - - - -視圖層之視圖函數(views)

Django - - - -視圖層之視圖函數(views)

obb hose content ken 會話 style 用戶 指定 lec

視圖層之視圖函數(views)

一個視圖函數,簡稱視圖,是一個簡單的Python 函數,它接受Web請求並且返回Web響應。響應可以是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片. . . 是任何東西都可以。無論視圖本身包含什麽邏輯,都要返回響應。代碼寫在哪裏也無所謂,只要它在你的Python目錄下面。除此之外沒有更多的要求了——可以說“沒有什麽神奇的地方”。為了將代碼放在某處,約定是將視圖放置在項目或應用程序目錄中的名為views.py的文件中。

視圖函數:
一定包含兩個對象:
requset---->用戶請求相關的所有信息(對象)

Httpresponse---->響應字符串

一個簡單的視圖

下面是一個返回當前日期和時間作為HTML文檔的視圖:

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

讓我們逐行閱讀上面的代碼:

  • 首先,我們從 django.http模塊導入了HttpResponse類,以及Python的datetime庫。

  • 接著,我們定義了current_datetime函數。它就是視圖函數。每個視圖函數都使用HttpRequest對象作為第一個參數,並且通常稱之為request

    註意,視圖函數的名稱並不重要;不需要用一個統一的命名方式來命名,以便讓Django識別它。我們將其命名為current_datetime,是因為這個名稱能夠精確地反映出它的功能。

  • 這個視圖會返回一個HttpResponse對象,其中包含生成的響應。每個視圖函數都負責返回一個HttpResponse

    對象。

技術分享

視圖函數,圍繞著兩個對象進行:HttpResponse和HttpRequest

1.HttpRequest

  request---->請求信息

屬性:

request.path   # 獲取訪問文件路徑

request.method屬性 #獲取請求中使用的HTTP方式(POST/GET)

request.GET  #GET請求的數據(類字典對象)  請求頭中的url中?後面拿值
request.POST # POST請求的數據(類字典對象) 請求體裏拿值

request.COOKIES #包含所有cookies的標準Python字典對象;keys和values都是字符串。

request.FILES:      包含所有上傳文件的類字典對象;FILES中的每一個Key都是<input type="file" name="" />標簽中
             name屬性的值,FILES中的每一個value同時也是一個標準的python字典對象,包含下面三個Keys:

             filename:      上傳文件名,用字符串表示
             content_type:   上傳文件的Content Type
             content:       上傳文件的原始內容


request.user:       是一個django.contrib.auth.models.User對象,代表當前登陸的用戶。如果訪問用戶當前
             沒有登陸,user將被初始化為django.contrib.auth.models.AnonymousUser的實例。你
             可以通過user的is_authenticated()方法來辨別用戶是否登陸:
             if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware
             時該屬性才可用

request.session:    唯一可讀寫的屬性,代表當前會話的字典對象;自己有激活Django中的session支持時該屬性才可用

request.GET.get(‘name‘) 拿到GET請求裏name的值

如果某個鍵對應有多個值,則不能直接用get取值,需要用getlist,如:
request.POST.getlist("hobby")


請求url:http://127.0.0.1:8000/index.html/23?a=1

request.path : 請求路徑
request.path結果為:/index.html/23

request.get_full_path()
request.get_full_path()結果為:/index.html/23?a=1


方法:

1 get_full_path()

註意:鍵值對的值是多個的時候,比如checkbox類型的input標簽,select標簽,需要用:

1 request.POST.getlist("hobby")

2.HttpResponse

  HttpResponse---->相應字符串

  對於HttpRequest請求對象來說,是由django自動創建的,但是,HttpResponse響應對象就必須我們自己創建。每個view請求處理方法必須返回一個HttpResponse響應對象。HttpResponse類在django.http.HttpResponse。

在HttpResponse對象上擴展的常用方法

1.render 函數

  將指定頁面渲染後返回給瀏覽器

render(request, template_name[, context])

結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的 HttpResponse 對象。

參數:
     request: 用於生成響應的請求對象。

     template_name:要使用的模板的完整名稱,可選的參數

     context:添加到模板上下文的一個字典。默認是一個空字典。如果字典中的某個值是可調用的,視圖將在渲染模板之前調用它。

     content_type:生成的文檔要使用的MIME類型。默認為DEFAULT_CONTENT_TYPE 設置的值。

     status:響應的狀態碼。默認為200。
from django.shortcuts import render

def test(request):
    return render(request,index.html)   #向用戶顯示一個html頁面

下面為render官方源碼,可以看出render最後也是返回了一個HttpResponse給webserver

def render(request, template_name, context=None, content_type=None, status=None, using=None):
    """
    Returns a HttpResponse whose content is filled with the result of calling
    django.template.loader.render_to_string() with the passed arguments.
    """
    content = loader.render_to_string(template_name, context, request, using=using)
    return HttpResponse(content, content_type, status)

細說render:

  render方法主要是將從服務器提取的數據,填充到模板中,然後將渲染後的html靜態文件返回給瀏覽器。這裏一定要註意:render渲染的是模板,下面我們看看什麽叫作模板:

<!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>Title</title>
    <style>
        li,ul,ol{  list-style: none;  }
        a{ text-decoration: none; }
    </style>
</head>
<body>
<ul>
    {% for book in list %}
        <li><a href="{{book.id}}">{{ book.btitle }}</a></li>
    {% endfor %}
</ul>
</body>
</html>

上面{%%}之間包括的就是我們要從數據庫取出的數據,進行填充。對於這樣一個沒有填充數據的html文件,瀏覽器是不能進行渲染的,所以,對於上述{%%}之間的內容先要被render進行渲染之後,才能發送給瀏覽器。

  下面舉個例子:

技術分享
<!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>Title</title>
    <style>
        li,ul,ol{  list-style: none;  }
        a{ text-decoration: none; }
    </style>
</head>
<body>
<ul>
    {% for book in list %}
        <li><a href="{{book.id}}">{{ book.btitle }}</a></li>
    {% endfor %}

</ul>
</body>
</html>
show.html
def show(request, id):  
    book = BookInfo.objects.get(pk=id)   #從數據庫中取出對應id的數據
    herolist = book.heroinfo_set.all()  
    context = {list: herolist}       # 將數據保存在list
    return render(request, booktest/show.html, context) #通過render進行模板渲染

2.redirect 函數

參數可以是:

  • 一個模型:將調用模型的get_absolute_url() 函數
  • 一個視圖,可以帶有參數:將使用urlresolvers.reverse 來反向解析名稱
  • 一個絕對的或相對的URL,將原封不動的作為重定向的位置。

默認返回一個臨時的重定向;傳遞permanent=True 可以返回一個永久的重定向。

示例:

你可以用多種方式使用redirect() 函數。

傳遞一個對象

將調用get_absolute_url() 方法來獲取重定向的URL:

1 2 3 4 5 6 from django.shortcuts import redirect def my_view(request): ... object = MyModel.objects.get(...) return redirect(object)

傳遞一個視圖的名稱

可以帶有位置參數和關鍵字參數;將使用reverse() 方法反向解析URL: 

1 2 3 def my_view(request): ... return redirect(‘some-view-name‘, foo=‘bar‘)

傳遞要重定向的一個硬編碼的URL

1 2 3 def my_view(request): ... return redirect(‘/some/url/‘)

也可以是一個完整的URL:

1 2 3 def my_view(request): ... return redirect(‘http://example.com/‘)

默認情況下,redirect() 返回一個臨時重定向。以上所有的形式都接收一個permanent 參數;如果設置為True,將返回一個永久的重定向:

1 2 3 4 def my_view(request): ... object = MyModel.objects.get(...) return redirect(object, permanent=True)  

跳轉(重定向)應用

技術分享
-----------------------------------url.py

 url(r"login",   views.login),
 url(r"yuan_back",   views.yuan_back),

-----------------------------------views.py
def login(req):
    if req.method=="POST":
        if 1:
            # return redirect("/yuan_back/")
            name="yuanhao"

            return render(req,"my backend.html",locals())

    return render(req,"login.html",locals())


def yuan_back(req):

    name="苑昊"

    return render(req,"my backend.html",locals())

-----------------------------------login.html

<form action="/login/" method="post">
    <p>姓名<input type="text" name="username"></p>
    <p>性別<input type="text" name="sex"></p>
    <p>郵箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>
</form>
-----------------------------------my backend.html
<h1>用戶{{ name }}你好</h1>
View Code

下面我們來看一個現象:

技術分享
--------------------urls.py------------------------------

urlpatterns = [
    url(r^admin/, admin.site.urls),
    url(r^login/, views.login),
    url(r^index/, views.index,),
    # url(r‘^register/‘, views.register,name=‘reg‘),

]

------------------view.py-------------------------------
def login(request):
    if request.method==POST:
        username=request.POST.get(user)
        password=request.POST.get(pwd)
        if username==yuan and password==123:
            # return render(request,‘index.html‘)
            return redirect(/index/)
        else:
            return render(request,login.html,{info:賬號或密碼錯誤})
    else:
        return render(request,login.html)


def index(request):
        name=yuan
        return render(request,index.html,{a:name})

---------------login.html--------------------------------
<h1>登陸界面</h1>
<form action="/login/" method="post">
    <p>姓名 <input type="text" name="user"></p>
    <p>密碼 <input type="password" name="pwd"></p>
    <p><input type="submit"></p>
    <p>{{ info }}</p>
</form>


---------------login.html--------------------------------
<h1>個人主頁</h1>
<h2>hello,{{ a}}</h2>
代碼

首先,啟動服務器後,我們進入login頁面

技術分享

技術分享

正確輸入姓名,密碼後,此時執行redirect函數,結果如下

技術分享

現在我們將redirect換成render,再重新走一遍看看,在login頁面,正確輸入姓名,密碼後,結果如下:

技術分享

細心的人會發現,用render函數執行後的,地址欄的地址沒有變化,還是login,且頁面上的{{a}}此時也沒有被渲染,所以hello,後面沒有內容顯示!

對比render與redirect:

原因是
render: 只是返回頁面內容,但是未發送第二次請求
redirect:發送了第二次請求,url更新

技術分享

總結兩者區別:    

     第一,render返回一個登陸成功後的頁面,刷新該頁面將回復到跳轉前頁面。而redirect則不會

     第二,如果頁面需要模板語言渲染,需要的將數據庫的數據加載到html,那麽render方法則不會顯示這一部分,render返回一個登陸成功頁面,不會經過url路由分發系統,也就是說,不會執行跳轉後url的視圖函數。這樣,返回的頁面渲染不成功;而redirect是跳轉到指定頁面,當登陸成功後,會在url路由系統進行匹配,如果有存在的映射函數,就會執行對應的映射函數。

Django - - - -視圖層之視圖函數(views)