目錄
- 網頁偽靜態
- 1.什么是偽靜態網頁?
- 2.偽靜態的好處
- 3.實作偽靜態網頁
- 視圖層
- 1.三板斧
- 2.三板斧的本質
- Django視圖層函式必須要回傳一個HttpResponse物件
- 研究底層原始碼
- 3.視圖函式回傳json格式資料
- JsonResponse
- JsonResponse序列化(串列注意事項)
- json與pickle區別
- 4.FBV與CBV
- 1.FBV與CBV區別
- 2.CBV
- 3.CBV底層原始碼
- form表單如何攜帶資料檔案
- 模板層
- 1.模板語法的傳值
- 2.模板語法傳值的范圍
- 3.模板語法過濾器(類似于python內置函式)
- 1.模板語法過濾器
- 2.基本語法
- 3.過濾器內置方法
- 4.模板語法標簽(類似于python流程控制)
- 1.if判斷
- 2.for回圈
- 3.with語法起別名
- 5.自定義標簽函式、過濾器、inclusion_tag
- 1.自定義過濾器,標簽,inclusion_tog必須要有一下三步準備
- 2.自定義過濾器filter,最多能有倆個引數
- 3.自定義標簽(函式)
- 4.自定義inclusion_tag
- 6.模板的繼承
- 1.什么是模板的繼承
- 2.如何使用模板的繼承
- 7.模板的匯入
- 1.模板匯入
- 2.匯入格式
網頁偽靜態
1.什么是偽靜態網頁?
偽靜態是相對于靜態檔案來說的,例如https://www.cnblogs.com/hesujian/p/11165818.html
將一個動態網頁偽裝成靜態網頁
將url地址模擬成html結尾的樣子,看上去像是一個靜態檔案,只是改變了URL的表現形式,實際上還是動態頁面
搜索優化:seo
在路由的最后加上.html
2.偽靜態的好處
1、美觀(傳統的問號拼接看起來比較雜亂)
2、seo(搜索引擎優化技術),搜索引擎比較喜歡收錄靜態頁面,所以大家都做成偽靜態去增加收錄機會,增大本網站的seo查詢力度,增加搜索引擎收藏本網站的概率
3.實作偽靜態網頁
# 在路由后面加上.html就可實作靜態頁面效果
path('index.html',view.index)
視圖層
Django視圖層,視圖就是Django專案下的views.py檔案,它的內部是一系列的函式或者是類,用來專門處理客戶端訪問請求后處理請求并且回傳相應的資料,相當于一個中央情報處理系統,
1.三板斧
"""
HttpResponse
回傳字串型別
httpresponse() 括號內直接跟一個具體的字串作為回應體,比較直接簡單,所有這里主要介紹后面兩種形式,
render
回傳html頁面 并且在回傳給瀏覽器之前還可以給html檔案傳值
render(request, template_name[, context])結合一個給定的模板和一個給定的背景關系字典,并回傳一個渲染后的 HttpResponse 物件,
# 引數:
request: 用于生成回應的請求物件,
template_name:要使用的模板的完整名稱,可選的引數
context:添加到模板背景關系的一個字典,默認是一個空字典,如果字典中的某個值是可呼叫的,視圖將在渲染模板之前呼叫它,
render方法就是將一個模板頁面中的模板語法進行渲染,最終渲染成一個html頁面作為回應體,
redirect
傳遞要重定向的一個硬編碼的URL
def my_view(request):
rerurn redirect('/some/url/')
也可以是一個完整的URL
def my_view(request):
...
return redirect('http://www.baidu.com/')
"""
2.三板斧的本質

視圖app01沒有回傳一個HttpResponse物件,回傳一個None代替了
Django視圖層函式必須要回傳一個HttpResponse物件
django視圖層函式必須有一個回傳值,并且回傳值的資料型別必須是HttpResponse物件
研究底層原始碼
1.def index(request):
return HttpResponse()
"""
按住ctrl點擊進入HttpResponse:
發現HttpResponse其實是一個類,那么類名加()實體化產生一個物件
class HttpResponse(HttpResponseBase):
pass
"""
2.def index(request):
return render()
"""
按住ctrl點擊進入render:
def render(request, template_name, context=None, content_type=None, status=None, using=None):
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status)
先執行的是render函式,然后render函式回傳的是HttpResponse(content, content_type, status)
"""
3.def index(request):
return redirect()
"""
按住ctrl點擊進入redirect:
def redirect(to, *args, permanent=False, **kwargs):
redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
return redirect_class(resolve_url(to, *args, **kwargs))
按住ctrl點擊進入HttpResponsePermanentRedirect:
class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
pass
按住ctrl點擊進入HttpResponseRedirectBase:
class HttpResponseRedirectBase(HttpResponse):
pass
會發現它繼承的也是HttpResponse
按住ctrl點擊進入HttpResponseRedirect:
class HttpResponseRedirect(HttpResponseRedirectBase):
pass
按住ctrl點擊進入HttpResponseRedirectBase:
class HttpResponseRedirectBase(HttpResponse):
pass
會發現它繼承的也是HttpResponse
"""
'''綜上研究發現:Django視圖層函式必須要回傳一個HttpResponse物件'''
3.視圖函式回傳json格式資料

def index(request):
# 將后端字典序列化發送到前端
user_dict = {'name': 'jason', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
# 先轉成json格式字串
json_str = json.dumps(user_dict)
# 將該欄位回傳
return HttpResponse(json_str)

解決這個中文輸入的問題我們之前是加了ensure_ascill=False,ensure_ascii 內部默認True自動轉碼,改為False不轉碼,只生成json格式,雙引號

以上實作返滬json格式資料比較麻煩,又得轉換json格式又得編碼設定,那么Django的出現就在這方面做出了改變
JsonResponse
# 匯入JsonResponse模塊
from django.http import JsonResponse
def index(request):
user_dict = {'name': 'jason老師', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
# json_str = json.dumps(user_dict, ensure_ascii=False)
return JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False}) # 直接寫入JsonResponse,不需要去做json序列化操作
# user_dict,json_dumps_params={'ensure_ascii':False} :解決前端中文轉碼問題
JsonResponse底層
# 繼承了HttpResponse,回傳的還是HttpResponse物件
class JsonResponse(HttpResponse):
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
json_dumps_params=None, **kwargs):
# json_dumps_params=None,注意這個引數,是一個默認引數
if safe and not isinstance(data, dict):
raise TypeError(
'In order to allow non-dict objects to be serialized set the '
'safe parameter to False.'
)
if json_dumps_params is None:
# 對應開始json_dumps_params=None,
json_dumps_params = {}
# 如果我們在這里傳入了一個值,那么這里的json_dumps_params = {'XXX':'XXX'},然后在下面的data里面轉換為的是關鍵字引數,XXX=XX
kwargs.setdefault('content_type', 'application/json')
'''
將data資料進行了json序列化,然后做了一個回傳
**json_dumps_param,**加在字典前面,現在是在呼叫一個函式,那么它在這里做實參,**在是實參中將字典打散為關鍵字引數形式,就是什么等于什么
'''
data = https://www.cnblogs.com/zxr1002/archive/2022/09/03/json.dumps(data, cls=encoder, **json_dumps_params)
super().__init__(content=data, **kwargs)


JsonResponse序列化(串列注意事項)
# 匯入JsonResponse模塊
from django.http import JsonResponse
def ab_json(request):
l = [111,222,333,444,555]
# 默認只能序列化字典 序列化其他需要加safe引數 safe=False
return JsonResponse(l,safe=False)

json與pickle區別
import json
'''支持的資料型別:str,list, tuple, dict, set'''
# 序列化出來的資料是可以看得懂的,就是一個字串
dumps 將Python物件轉換成json字串
loads
dump 將Python物件寫入json檔案
load
import pickle
'''支持的資料型別:python中的所有資料型別'''
# 序列化出來的結果看不懂,因為結果是一個二進制
# pickle序列化出的來的資料只能在python中使用
dumps
loads
dump
load
4.FBV與CBV
1.FBV與CBV區別
FBV基于函式的視圖(Function base view) 我們前面寫的視圖函式都是FBV
CBV基于類的視圖(Class base view)
視圖檔案種除了用一系列的函式來對應處理客戶端請求的資料邏輯外,還可以通過定義類來處理相應的邏輯,
# 視圖函式既可以是函式也可以是類
def index(request):
return HttpResponse('index')
2.CBV

從index頁面,后臺修改action的引數,朝func發送post請求

點擊提交以后自動出發了類里面的post方法

CBV比起FBV來說的話,不需要通過request.method來判斷當前是什么請求,CBV會自動判斷,是哪種請求,就去觸發哪種方法(寫在類里面里的函式叫做方法)
3.CBV底層原始碼
原始碼分析入口
path('func/', views.MyView.as_view())
"""
# 面向物件屬性方法查找順序
1.先從物件自己名稱空間找
2.在去產生類物件的類里面找
3.在去父類里面找
"""
1.系結給類的as_view方法(它是我們自己寫的類里面繼承的類)
class View:
@classonlymethod
def as_view(...):
系結給類的,類呼叫會自動將類當作第一個引數傳入
def view(...):
pass
return view
2.CBV路由匹配本質:跟FBV是一致的
path('func/', views.view)
3.訪問func觸發view執行
def view(...):
obj = cls() # 我們自己寫的類加括號產生的物件
return obj.dispatch()
'''涉及到物件點名字 一定要確定物件是誰 再確定查找順序'''
4.研究dispatch方法
def dispatch(...):
判斷 request.method將當前請求方式轉成小寫 在不在 self內 self==MyLogin
"http_method_names 內有八個請求方式 合法"
['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
if request.method.lower() in self.http_method_names:
# getattr 反射: 通過字串來操作物件的屬性或者方法
func_name = getattr(obj,request.method.lower())
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
用到了一個反射的知識,從obj這個物件里面,找一個request.method.lower()這個的函式
form表單如何攜帶資料檔案

form表單如何攜帶資料檔案需要注意滿足以下倆個要求
1.method屬性值必須是post
2.enctype屬性值必須是multipart/form-data
后端獲取檔案資料的操作,request物件方法
1.獲取請求方式POST/GET
request.method
一個字串,表示請求使用的HTTP 方法,必須使用大寫,
2.request.POST
獲取POST請求提交普通的鍵值對資料 一個類似于字典的物件,如果請求中包含表單資料,則將這些資料封裝成
3.獲取GET請求
request.GET
獲取GET請求 一個類似于字典的物件,包含 HTTP GET 的所有引數
4.獲取檔案
request.FILES
一個類似于字典的物件,包含所有的上傳檔案資訊,
FILES 中的每個鍵為<input type="file" name="" /> 中的name,值則為對應的資料,
注意,FILES 只有在請求的方法為POST 且提交的<form> 帶有enctype="multipart/form-data" 的情況下才會包含資料,否則,FILES 將為一個空的類似于字典的物件,
5.原生的瀏覽器發過來的二進制資料
request.body
一個字串,代表請求報文的主體,在處理非 HTTP 形式的報文時非常有用,
例如:二進制圖片、XML,Json等,
6.拿到路由
request.path
print(request.path) # /app01/index/
個字串,表示請求的路徑組件(不含域名)
7.拿到路由
request.path_info
print(request.path_info) # /app01/index/
8.能過獲取完整的url及問號后面的引數
request.get_full_path()
print(request.get_full_path()) # /app01/index/?username=jason
實際案例展示
import json
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
# Create your views here.
def index(request):
# user_dict = {'name': 'jason老師', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
# # json_str = json.dumps(user_dict, ensure_ascii=False)
# return JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False}) # 直接寫入JsonResponse,不需要去做json序列化操作
#
# # user_dict,json_dumps_params={'ensure_ascii':False} :解決前端中文轉碼問題
if request.method == 'POST':
# 普通的鍵值對形式的資料
print(request.POST)
# 專門用來攜帶過來的檔案資料,流式的檔案資料
print(request.FILES) # <MultiValueDict: {'file': [<InMemoryUploadedFile: 今日內容.md (application/octet-stream)>]}>
# 也可以取到這個檔案,注意它也是一個Dict,可以通過點的方式得到,'file'由前端的name標簽決定
file_obj = request.FILES.get('file')
# 可以使用這個物件去點出一些方法
print(file_obj.name)
# 也可以將這個檔案保存下來,這個檔案可以是文本檔案,也可以是音頻檔案,只不過pycharm不能拿播放音頻檔案
with open(file_obj.name, 'wb') as f:
for line in file_obj:
f.write(line)
return render(request, 'index.html')

模板層
1.模板語法的傳值
方式一:指名道姓的傳
urls代碼:
path('modal/', views.modal)
views代碼:
def modal(request):
name = 'jason'
return render(request, 'modal.html', {'name':name})
指名道姓傳參 不浪費資源
方式二:關鍵字locals()
html代碼:
<body>
{{ name }}
{{ age }}
{{ gender }}
</body>
urls代碼:
path('modal/', views.modal)
views代碼:
def modal(request):
name = 'jason'
age = 18
gender = 'female'
return render(request, 'modal.html', locals()) # 將函式體里區域空間里所有的名字全部傳入給前面的那個頁面
將整個區域名稱空間中的名字去全部傳入簡單快捷
2.模板語法傳值的范圍
基本資料型別直接傳遞使用
views代碼
def modal(request):
i = 123
f = 13.4
s = 'study work hard'
d = {'name': 'Tony', 'pwd': 123}
t = (11, 22, 33)
se = {11, 22, 33}
b = True
return render(request, 'modal.html', locals())
html代碼
<body>
<p>{{ i }}</p>
<p>{{ f }}</p>
<p>{{ s }}</p>
<p>{{ l }}</p>
<p>{{ d }}</p>
<p>{{ t }}</p>
<p>{{ se }}</p>
<p>{{ b }}</p>
</body>

函式名的傳遞會自動加括號執行并將回傳值展示到頁面上,注意函式如果有引數則不會執行也不會展示 模板語法不支持有參函式
views代碼
def modal(request):
def func1():
print('函式')
return '這里才能傳過去值哦'
return render(request, 'modal.html', locals())
html代碼
<body>
{#傳遞函式名會自動加括號呼叫 但是模板語法不支持給函式傳額外的引數#}
<p>{{ func1 }}</p>
</body>


類名的傳遞也會自動加括號產生物件并展示到頁面上,物件的傳遞則直接使用即可,物件默認情況下不可以加括號了,除非自己寫__call__方法,模板語法會判斷每一個名字是否可呼叫 如果可以則呼叫!!!
views代碼
class MyClass(object):
def get_obj(self):
return 'obj'
@classmethod
def get_cls(cls):
return 'cls'
@staticmethod
def get_func():
return 'func'
obj = MyClass()'
return render(request, 'modal.html', locals())
html代碼
<body>
{#傳類名的時候也會自動加括號呼叫(實列化) 生成物件#}
<p>{{ MyClass }}</p>
{#內部能夠自動判斷出當前的變數名是否可以加括號呼叫 如果可以就會自動執行 針對的是函式名和類名#}
<p>{{ obj }}</p>
{#模板語法支持物件呼叫類方法#}
<p>{{ obj.get_self }}</p>
<p>{{ obj.get_func }}</p>
<p>{{ obj.get_class }}</p>
</body>

django的模板語法在操作容器型別的時候只允許使用句點符,既可以點鍵,也可以點索引
.key
.index
.key.index.index.key
3.模板語法過濾器(類似于python內置函式)
1.模板語法過濾器
過濾器就類似于是模板語法內置的 內置方法
模板語法提供了一些內置方法,以助于快速的處理資料(過濾器最多只能有兩個引數)
2.基本語法
{{ 變數|過濾器:引數}}
過濾器:會自動將豎杠左側的變數當做第一個引數交給過濾器處理,右側的當做第二個引數,
3.過濾器內置方法
<p>統計長度:{{ s|length }}</p>
# 統計長度:15
<p>加法運算:{{ i|add:123 }}、加法運算:{{ s|add:'heiheihei' }}</p>
# 加法運算:246、字串加法運算:study work hard +every day
<p>日期轉換:{{ s|date:'Y-m-d H:i:s' }}</p>
<p>檔案大小:{{ file_size|filesizeformat }}</p>
# 檔案大小:31.1 KB
<p>資料切片:{{ l|slice:'0:10' }}</p>
# 切片操作(支持步長)
<p>字符截取(三個點算一個):{{ s1|truncatechars:6 }}</p>
# 字符截取(包含三個點):模板語法提供...
<p>單詞截取(空格):{{ s1|truncatewords:6 }}</p>
# 單詞截取(不包含三個點 按照空格切):my name is objk my age is 18 and ...
<p>語法轉義:{{ script_tag }}</p>
# <h1>今晚晚飯又有好多好吃的了</h1>(是不會識別前端標簽的)
<p>語法轉義:{{ script_tag|safe }}</p>
# 今晚晚飯又有好多好吃的了
# 如果不轉移的話,那么無法識別前端標簽,那么以下這種功能的情況就沒有辦法實作
<p>語法轉義:{{ script_tag1|safe }}</p>
script_tag1 = '<script>alert(666)</script>'
# 也可以使用后端轉
from django.utils.safestring import mark_safe
script_tag2 = '<script>alert(666)</script>'
res = mark_safe(script_tag2)
ps:有時候html頁面上的資料不一定非要在html頁面上撰寫了 也可以后端寫好傳入
'''django模板語法中的符號就兩個 一個{{}} 一個{%%}
需要使用資料的時候 {{}}
需要使用方法的時候 {%%}
'''
4.模板語法標簽(類似于python流程控制)
1.if判斷
<body>
{% if 條件 %} 條件一般是模板語法傳過來的資料 直接寫名字使用即可
條件成立執行的代碼
{% elif 條件1 %}
條件1成立執行的代碼
{% else %}
條件都不成立執行的代碼
{% endif %}
</body>
2.for回圈
forloop 模板語法自帶的變數名
{% for i in s %}
{% if forloop.first %}
<p>這是第一次喲~</p>
{% elif forloop.last %}
<p>這是最后一次!</p>
{% else %}
<p>{{ i }}</p>
{% endif %}
{% empty %}
<p>empty專門用來判斷空的時候,當in后面是空的時候執行這個,給予提示</p>
{% endfor %}
決議:
forloop內置物件:運行結果決議
'counter0': 從0開始計數
'counter' : 從1開始計數
'first': True,判斷回圈的開始
'last' : Tues,判斷回圈的結束

3.with語法起別名
# with起別名
{% with d.hobby.3.info as nb %}
<p>{{ nb }}</p>
在with語法內就可以通過as后面的別名快速的使用到前面非常復雜獲取資料的方式
<p>{{ d.hobby.3.info }}</p>
{% endwith %}
決議:
可以通過as后面的別名快速的使用到前面非常復雜獲取資料的方式
取別名后原來的名字也能正常使用
命名規范: 只能在with代碼塊兒的范圍之內才能使用別名
5.自定義標簽函式、過濾器、inclusion_tag
1.自定義過濾器,標簽,inclusion_tog必須要有一下三步準備
1.在應用下創建一個名為templatetags檔案夾
2.在該檔案夾創建任意名稱的py檔案
3.在該py檔案內撰寫自定義相關代碼
from django.template import Library
register = Library()

2.自定義過濾器filter,最多能有倆個引數
# mytag.py
from django import template
register = template.Library()
# 引數 過濾器 過濾器名字
@register.filter(name='myfiltermyfilter')
def my_add(a, b):
return a + b
# index.html頁面使用
加載自定義檔案名
{% load mytag %}
<p>{{ i|myfilter:1 }}</p>
3.自定義標簽(函式)
# 引數 標簽(函式)標簽(函式)名字
@register.simple_tag(name='mt')
def func(a, b, c, d):
return a + b + c + d
加載自定義檔案名
{% load mytag %}
{% mt 1 2 3 4 %}
4.自定義inclusion_tag
當html頁面某一個地方的頁面需要傳引數才能夠動態的渲染出來,并且在多個頁面上都需要使用到該區域
@register.inclusion_tag(filename='it.html')
def index(n):
html = []
for i in range(n):
html.append('第%s頁'%i)
return locals() # 將html傳給filename這個頁面,然后可以在那個頁面上使用
加載自定義檔案名
{% load mytag %}
{% index 10 %}
filename是作用于一個頁面,這個頁面可以不是一個完整的頁面,只是一部分,

6.模板的繼承
1.什么是模板的繼承
你需要事先在你想要使用的主頁面上劃定區域做好標記,之后在子頁面繼承的時候你就可以使用在主頁面劃定的區域,也就意味著,如果你不劃定任何區域,那么你子頁面將無法修改主頁面內容
2.如何使用模板的繼承
1.先在你想要繼承的主頁面上通過bolck劃定你將來可能要改的區域,并做好標記
2.在子頁面上繼承extends,利用block自動提示選取你想要修改的內容區域標記名稱
3.在子頁面extends中寫你要修改主頁面標記區的代碼
4.然后就可以讓子頁面的修改內容渲染到主頁面的劃定區域上
# 模板頁面提前先寫好將來可能要替換的內容
{% block 名字 %}
"""模板內容"""
{% endblock %}
# 新頁面要基于模板頁面替換的內容
{% extends 'html檔案名' %}
{% block 名字 %}
"""子板內容"""
{% endblock %}
"""一般情況下母板中至少應該有三個區域使得擴展性更高!!! css content js"""
{% block css %}
<style>...</style>
{% endblock %}
{% block content %}
...
{% endblock %}
{% block js %}
<script>...</script>
{% endblock %}
'''子板中還可以使用母板的內容 {{ block.super }} '''
7.模板的匯入
1.模板匯入
將頁面的某一個區域當成模塊的形式
哪個地方需要就可以直接匯入使用即可
2.匯入格式
{% include '匯入html檔案名' %}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/503565.html
標籤:其他
