請求與響應篇html
1、HttpRequest對象python
ajax
chrome
django
屬性: path:一個字符串,表示請求的頁面的完整路徑,不包含域名 method:一個字符串,表示請求使用的HTTP方法,經常使用值包括:'GET'、'POST' encoding:一個字符串,表示提交的數據的編碼方式 若是爲None則表示使用瀏覽器的默認設置,通常爲utf-8 這個屬性是可寫的,能夠經過修改它來修改訪問表單數據使用的編碼,接下來對屬性的任何訪問將使用新的encoding值 GET:一個相似於字典的對象,包含get請求方式的全部參數 POST:一個相似於字典的對象,包含post請求方式的全部參數 FILES:一個相似於字典的對象,包含全部的上傳文件 COOKIES:一個標準的Python字典,包含全部的cookie,鍵和值都爲字符串 session:一個既可讀又可寫的相似於字典的對象,表示當前的會話,只有當Django 啓用會話的支持時纔可用,詳細內容見「狀態保持」 方法: is_ajax():若是請求是經過XMLHttpRequest發起的,則返回True
(二).QueryDict對象json
request對象的GET、POST屬性,都是QueryDict類型的對象。它不是python的字典!QueryDict類型的對象用來處理同一個鍵帶有多個值的狀況。瀏覽器
(1).get()緩存
根據鍵獲取值,只能獲取鍵的一個值。若是一個鍵同時擁有多個值,獲取最後一個值安全
(2).getlist()服務器
根據鍵獲取值,將鍵的值以列表返回,能夠獲取一個鍵的多個值。
(3).例
dict.get('鍵',default) # 或簡寫爲 dict['鍵'] dict.getlist('鍵',default)
(三).
(1).QueryDict類型的對象
(2).包含get請求方式的全部參數
(3).與url請求地址中的參數對應,在url的?後面進行拼接
(4).參數的格式是鍵值對,如key1=value1
(5).多個參數之間,使用&鏈接,如key1=value1&key2=value2
(1).QueryDict類型的對象
(2).包含post請求方式的全部參數
(3).與form表單中的控件對應
(4).表單中控件要有name屬性,則name屬性的值爲鍵,value屬性的值爲鍵,構成鍵值對提交
(5).對於checkbox控件,name屬性同樣爲一組,當控件被選中後會被提交,存在一鍵多值的狀況
2、HttpResponse對象
(一).屬性及方法
屬性: content:表示返回的內容,字符串類型 charset:表示response採用的編碼字符集,字符串類型 status_code:響應的HTTP響應狀態碼 方法: init:使用頁內容實例化HttpResponse對象 write(content):以文件的方式寫 flush():以文件的方式輸出緩存區 set_cookie(key, value='', max_age=None, expires=None):設置Cookie key、value都是字符串類型 max_age是一個整數,表示在指定秒數後過時 expires是一個datetime或timedelta對象,會話將在這個指定的日期/時間過時,注意datetime和timedelta值只有在使用PickleSerializer時纔可序列化 max_age與expires二選一 若是不指定過時時間,則關閉瀏覽器就失效. delete_cookie(key):刪除指定的key的Cookie,若是key不存在則什麼也不發生
(二).cookie的例子
def cookie_test(request): response = HttpResponse() response.set_cookie("a", "123") # 設置一個cookie cookie = response.COOKIES a = cookie.get("a", None) # 獲取cookie response.write(a) return response
cookie是以明文的方式保存在客戶端的,若是有敏感的信息則不安全。
(三).HttpResponse的子類:
(1).返回
json
數據
(2).幫助用戶建立JSON編碼的響應
(3).參數data是字典對象
(4).JsonResponse的默認Content-Type爲application/json
(5).例
from django.http import JsonResponse def jpTest(request): return JsonResponse({'ss':'123456'})
3、狀態保持
(1).http協議是無狀態的:每次請求都是一次新的請求,不會記得以前通訊的狀態
(2).客戶端與服務器端的一次通訊,就是一次會話實現狀態保持的方式:在客戶端或服務器端存儲與會話有關的數據
(3).存儲方式包括cookie、session,會話通常指session對象
(4).使用cookie,全部數據存儲在客戶端,注意不要存儲敏感信息
(5).推薦使用sesison方式,全部數據存儲在服務器端,在客戶端cookie中存儲session_id
(6).狀態保持的目的是在一段時間內跟蹤請求者的狀態,能夠實現跨頁面訪問當前請求者的數據
(7).注意事項:不一樣的請求者之間不會共享這個數據,與請求者一一對應
4、會話(session)
session是保存在服務端的,使用sessionid對應服務端中的session,sessionid則保存在cookie中。
cookie對應sessionid,sessionid對應服務端的session
(一).啓用session
(1).檢查settings.py文件
檢查settings.py文件是否有下面這些屬性
# 沒有的話,就添加 # INSTALLED_APPS 列表中: 'django.contrib.sessions', # MIDDLEWARE_CLASSES 列表中: 'django.contrib.sessions.middleware.SessionMiddleware',
(二).使用session
(1).啓用會話後,每一個HttpRequest對象將具備一個session屬性,它是一個類字典對象
(2).get(key, default=None):根據鍵獲取會話的值
(3).clear():清除全部會話
(4).flush():刪除當前的會話數據並刪除會話的Cookie
(5).del request.session['member_id']:刪除會話
(三).session保持用戶登陸的例子
(1).視圖函數
from django.shortcuts import render, HttpResponse, redirect, reverse # Create your views here. def session_index(request): """ 首頁 :param request: :return: """ login_status = request.session.get("username", "你未登陸,請登陸!") return render( request, "ts11/session_index.html", context={ "login_status": login_status, }, ) def session_login(request): """ 登陸頁面 用session實現登陸 :param request: :return: """ if request.method == "GET": return render(request, "ts11/session_login.html") elif request.method == "POST": request.session["username"] = request.POST.get("username") return redirect(reverse("index")) else: return HttpResponse("無效的請求") def session_login_out(request): """ 註銷 清空session :param request: :return: 清除session後,直接重定向,回到首頁 """ request.session.flush() return redirect(reverse("index"))
(2).url配置
from django.conf.urls import url from . import views urlpatterns = [ url(r"^session_index/$", views.session_index, name="index"), url(r"^session_login/$", views.session_login, name="login_in"), url(r"^session_login_out/$", views.session_login_out, name="login_out"), ]
(3).模板
# session_index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>session_index</title> </head> <body> 你好!{{ login_status }}<br> <a href="{% url "login_in" %}">登陸</a> <br><br> <a href="{% url "login_out" %}">註銷</a> </body> </html> # session_login.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>session_login</title> </head> <body> <form action="" method="post"> {% csrf_token %} 用戶名:<input type="text" name="username"><br> <input type="submit" value="提交"> </form> </body> </html>
(四).會話過時時間
(1).set_expiry(value):設置會話的超時時間
(2).若是沒有指定,則14天后過時
(3).若是value是一個整數,會話將在values秒沒有活動後過時
(4).若果value是一個imedelta對象,會話將在當前時間加上這個指定的日期/時間過時
(5).若是value爲0,那麼用戶會話的Cookie將在用戶的瀏覽器關閉時過時
(6).若是value爲None,那麼會話永不過時
(7).在視圖函數中設置過時的示例
#------------view.py-------------- def login(request): if request.method == 'GET': return render(request,'login.html') elif request.method == 'POST': username = request.POST.get('username') request.session['username']=username request.session.set_expiry(0) # 關閉瀏覽器就過時 return redirect(reverse('ts11_home'))
(8).
# 是否關閉瀏覽器使得Session過時,默認是False SESSION_EXPIRE_AT_BROWSER_CLOSE = False #是否每次請求都保存Session,默認修改以後才保存 SESSION_SAVE_EVERY_REQUEST = False # Session的cookie失效日期,默認是2周 SESSION_COOKIE_AGE = 1209600
(五).如何查看cookie和session
我是chrome的忠實粉,因此只看了Google Chrome的設置。
步驟:設置 - 高級 - 內容設置 - Cookie - 查看全部Cookie和網站數據 - 找到你本身的IP或域名
表單篇
django中的表單不是html中的那個<form>表單。而是app中的forms.py這個文件所生成的(這個文件名不像templates那樣嚴格,能夠寫form.py也能夠寫forms.py,但基本是寫forms)
django的表單一般是用來驗證數據的合法性。不多用來生成HTML代碼(django生成的表單較難調整樣式)
1、使用表單
(一).表單經常使用的屬性、方法
(1).建立一個forms.py的文件,放在app當中,而後在裏面寫表單
(2).表單是經過類實現的,繼承自forms.Form,而後在裏面定義要驗證的字段
(3).在表單中,建立字段跟模型是如出一轍的,可是沒有null=True或者blank=True等這幾種參數了,有的參數是required=True/False
(4).使用is_valid()方法能夠驗證用戶提交的數據是否合法,並且HTML表單元素的name必須和django中的表單的name保持一致,不然匹配不到
(5).is_bound屬性:用來表示form是否綁定了數據,若是綁定了,則返回True,不然返回False
(6).cleaned_data:這個是在is_valid()返回True的時候,保存用戶提交上來的數據.
(7).示例
# forms.py from django import forms class RegisterForm(forms.Form): """ 驗證註冊頁面的form """ username = forms.CharField( max_length=100, min_length=6, error_messages={ "min_length": "用戶名不能少於6位", } ) password = forms.CharField( max_length=100, min_length=6, widget=forms.PasswordInput(), error_messages={ "min_length": "密碼不能少於6位", } ) password_repeat = forms.CharField( max_length=100, min_length=6, widget=forms.PasswordInput(), error_messages={ "min_length": "密碼不能少於6位", } ) email = forms.EmailField() class RegisterLogin(forms.Form): """ 驗證登陸頁面的form """ username = forms.CharField( max_length=100, min_length=6, error_messages={ "min_length": "用戶名不能少於6位", } ) password = forms.CharField( max_length=100, min_length=6, widget=forms.PasswordInput(), error_messages={ "min_length": "密碼不能少於6位", } )
(二).字段類型中的一些參數
這些參數會對頁面的輸入作一些限制條件
max_length 最大長度
min_length 最小長度
widget 負責渲染網頁上HTML 表單的輸入元素和提取提交的原始數據
attrs 包含渲染後的Widget 將要設置的HTML 屬性
error_messages 報錯信息
2、表單小案例
需求:實現註冊、登陸。
要求:使用djang的form進行表單驗證。
(一).寫模型
from django.db import models # Create your models here. class Register(models.Model): """ 註冊頁面的模型 """ username = models.CharField(max_length=100, unique=True) password = models.CharField(max_length=100) email = models.EmailField() def __str__(self): return "Register <username:{},password:{},email:{}>".format( self.username, self.password, self.email )
而後進行makemigrations和migrate
(二).寫forms.py
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # __author__ = "Jack" from django import forms class RegisterForm(forms.Form): """ 驗證註冊頁面的form """ username = forms.CharField( max_length=100, min_length=6, error_messages={ "min_length": "用戶名不能少於6位", } ) password = forms.CharField( max_length=100, min_length=6, widget=forms.PasswordInput(), error_messages={ "min_length": "密碼不能少於6位", } ) password_repeat = forms.CharField( max_length=100, min_length=6, widget=forms.PasswordInput(), error_messages={ "min_length": "密碼不能少於6位", } ) email = forms.EmailField() class RegisterLogin(forms.Form): """ 驗證登陸頁面的form """ username = forms.CharField( max_length=100, min_length=6, error_messages={ "min_length": "用戶名不能少於6位", } ) password = forms.CharField( max_length=100, min_length=6, widget=forms.PasswordInput(), error_messages={ "min_length": "密碼不能少於6位", } )
(三).寫視圖函數views.py
(1).導包
from django.shortcuts import render, HttpResponse, redirect, reverse from .forms import * from .models import *
(2).index()
def index(request): """ 首頁 :param request: :return: """ login_status = request.session.get("username", "請登陸") return render( request, "ts22/index.html", context={ "login_status": login_status, }, )
(3).register()
def register(request): """ 註冊頁面的視圖函數 :param request: :return: """ if request.method == "GET": return render(request, "ts22/register.html") elif request.method == "POST": form = RegisterForm(request.POST) # 使用django的form進行驗證 if form.is_valid(): username = request.POST["username"] password = request.POST["password"] password_repeat = request.POST["password_repeat"] email = request.POST["email"] if password == password_repeat: Register.objects.create(username=username, password=password_repeat, email=email) else: return render( request, "ts22/register.html", context={"error_message": "兩次密碼輸入的不一致,請檢查!", }, ) else: return render(request, "ts22/register.html", context={"error_message": form.errors, }, ) return render(request, "ts22/register_success.html") # 直接渲染模板,進行跳轉 else: return render(request, "ts22/register.html")
(4).login()
def login(request): """ 登陸頁面的視圖函數 :param request: :return: """ if request.method == "GET": return render(request, "ts22/login.html") elif request.method == "POST": form = RegisterLogin(request.POST) if form.is_valid(): form_data = form.cleaned_data username = form_data["username"] password = form_data["password"] try: Register.objects.get(username=username, password=password) # get()沒有返回值是會報錯的 except Register.DoesNotExist: return HttpResponse("登陸失敗,請檢查用戶名或密碼!") # 用異常捕獲來檢驗是否登陸成功 else: request.session["username"] = username # 保存session return redirect(reverse("index")) else: return render(request, "ts22/login.html", context={"error_messages": form.errors}, ) else: return HttpResponse("無效的請求")
(5).logout()
def logout(request): """ 註銷頁面的視圖函數 :param request: :return: 註銷後直接回到首頁 """ request.session.flush() return redirect(reverse("index"))
(四).寫模板templates/ts22
(1).index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> 你好,{{ login_status }}! <br> <a href="{% url "register" %}">註冊</a> <br> <a href="{% url "login" %}">登陸</a> <br> <a href="{% url "logout" %}">註銷</a> </body> </html>
(2).login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> <form action="" method="post"> {% csrf_token %} 用戶名:<input type="text" name="username"> <br> 密碼:<input type="password" name="password"> <br> <input type="submit" value="登陸"> {{ error_messages }} </form> </body> </html>
(3).register.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>register</title> </head> <body> <form action="" method="post"> {% csrf_token %} 用戶名:<input type="text" name="username" placeholder="請輸入用戶名"> <br> 密碼:<input type="password" name="password" placeholder="請輸入密碼"> <br> 確認密碼:<input type="password" name="password_repeat" placeholder="請確認密碼"> <br> 郵箱:<input type="email" name="email" placeholder="請輸入郵箱地址"> <br> <input type="submit" value="當即註冊"> {{ error_message }} </form> </body> </html>
(4).register_success.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>註冊成功</title> <style> * { margin: 0; padding: 0; } .bigbox { width: 400px; height: 200px; text-align: center; border: 2px solid rgb(180, 9, 28); border-radius: 7px; position: absolute; margin: auto; top: 0; right: 0; bottom: 0; left: 0; box-shadow: lightgrey 3px 3px 3px; } .cell { position: relative; top: 50%; transform: translateY(-50%); } </style> </head> <body> <div class="bigbox"> <div class="cell"> 註冊成功!感謝您註冊成爲咱們的會員! <br> <span id="countdown_seconds">5</span>秒後,將會自動回到首頁! <br> 若是瀏覽器沒有自動跳轉,<a href="{% url "index" %}">點此回到主頁</a> </div> </div> <script> window.onload = function () { let time = document.getElementById("countdown_seconds").innerText; let set = setInterval(function () { time--; if (time < 1) { {#<1就不會出現0了#} window.location = "{% url "index" %}"; } else { document.getElementById("countdown_seconds").innerText = time; } }, 1000); } </script> </body> </html>
(五).註冊路由
from django.conf.urls import url from . import views urlpatterns = [ url(r"^index/$", views.index, name="index"), url(r"^register/$", views.register, name="register"), url(r"^login/$", views.login, name="login"), url(r"^logout/$", views.logout, name="logout"), ]
(六).注意事項
(1).新的app不要忘記去總url中註冊
(2).新的app不要忘記去settings.py中的INSTALLED_APPS中註冊
中間件篇
中間件,顧名思義:中途做處理。能夠介入Django的請求和響應處理過程,修改Django的輸入或輸出。它針對的是request、response
1、自定義中間件
(一).在settings.py同級目錄下建立myself_middleware.py文件(中間件的命名隨意,但要符合python變量命名規則)
(二).寫入代碼
例如:
from ts22.models import * def is_my_user_login(request): username = request.session.get("username", "") user = Register.objects.filter(username=username).first() if user: return {"login_or_not": user.username} else: return {"login_or_not": "請登陸"}
返回的必須是一個字典!
(三).把這個函數註冊進TEMPLATES中去
模型直接沿用了表單篇的小案例
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # __author__ = "Jack" from django.http import HttpResponse from django.utils.deprecation import MiddlewareMixin from ts22.models import * class MyExceptionMiddleware(MiddlewareMixin): def process_exception(self, request, exception): return HttpResponse("程序出錯了:" + str(exception)) class RegisterMiddleware(MiddlewareMixin): def __init__(self, get_response): # 接收一個請求對象,也就是request self.get_response = get_response def __call__(self, request): # request到達view以前執行的代碼 username = request.session.get("username", "") user = Register.objects.filter(username=username).first() if user: if not hasattr(request, "my_user"): setattr(request, "my_user", user.username) else: setattr(request, "my_user", "請登陸.this is from middleware") response = self.get_response(request) # 返回響應 """ 這塊代碼是response對象,到達瀏覽器以前執行的代碼 """ return response
(三).每一箇中間件組件是一個獨立的Python類,能夠在類中定義下面方法中的一個或多個
注意:它們的方法名都是固定的!
_init _:無需任何參數,服務器響應第一個請求的時候調用一次,用於肯定是否啓用當前中間件
process_request(request):執行視圖以前被調用,在每一個請求上調用,返回None或HttpResponse對象
process_view(request, view_func, view_args, view_kwargs):調用視圖以前被調用,在每一個請求上調用,返回None或HttpResponse對象
process_template_response(request, response):在視圖恰好執行完畢以後被調用,在每一個請求上調用,返回實現了render方法的響應對象
process_response(request, response):全部響應返回瀏覽器以前被調用,在每一個請求上調用,返回HttpResponse對象
process_exception(request,response,exception):當視圖拋出異常時調用,在每一個請求上調用,返回一個HttpResponse對象
(四).註冊
將(二)中的兩個類,註冊到settings.py中間件中的MISSLEWARE裏面去
(五).在視圖函數中使用中間件
def index(request): """ 首頁 :param request: :return: """ login_status = request.my_user return render( request, "ts22/index.html", context={ "login_status": login_status, }, )
(六).做用
後期須要加功能,直接加中間件處理了,不可能一個個視圖去改了。
若是有好多視圖須要同一個功能,中間件就很好用了。一處寫,整個項目都能用了。
上下文處理器篇
實質上就是視圖函數中的render(context={}),上下文處理器就是個模板變量,只針對模板。
1、自定義上下文處理器
(一).在settings.py同級目錄下建立myself_contextprocessor.py文件(命名隨意,但要符合python變量命名規則)
(二).寫入代碼
仍是沿用了表單篇的models
from ts22.models import * def is_my_user_login(request): username = request.session.get("username", "") user = Register.objects.filter(username=username).first() if user: return {"login_or_not": user.username} else: return {"login_or_not": "請登陸"}
返回的必須是一個字典!
(三).把這個函數註冊進settings.py中的TEMPLATES去。
(四).使用它
直接去模板中,在你想要的地方,寫上{{ login_or_not }}