将动态网页伪装称静态网页 从而提升网页被搜索 收录的概率
表现形式就是网址看着像是一个具体的文件路径
path('index.htm',views.index)
视图函数必须返回一个HTTPResponse对象
注意HTTPResponse 其实是一个类
HttpResponse
class HttpResponse(HttpResponseBase):
render
def render(request, template_name, context=None, content_type=None, status=None, using=None):
#查看源码 发现 返回的是 HttpResponse
return HttpResponse(content, content_type, status)
redirect
def redirect(to, *args, permanent=False, **kwargs):
#查看 源码 得知 redirect 中 三元表达式 返回 其中的结果 然后我们继续深入
redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
return redirect_class(resolve_url(to, *args, **kwargs))
#深入 后发现 他最后 还是 继承了 HttpResponse
class HttpResponseRedirectBase(HttpResponse):
利用json模块 先序列化 然后 返回
from django.http import JsonResponse # 可以导入 jsonRespons 直接可以 序列化字典
def func2(request):
user_dict = {'name': 'jason老师', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
json_str= json.dumps(user_dict,ensure_ascii=False)
return HttpResponse(json_str)
return JsonResponse(user_dict)
查看JsonResponse 源码 查找 中文 取消编码 方法
ef __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
json_dumps_params=None, **kwargs):
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 = {}
kwargs.setdefault('content_type', 'application/json')
#那么 data 数据 在 序列化的时候 后面 就会 得到一个 关键字 参数 那么 这个字典 就可以 是 {'ensure_ascii':False}
#然后 一关键字参数 传给dumps 来 取消 编码
data = json.dumps(data, cls=encoder, **json_dumps_params)
super().__init__(content=data, **kwargs)
序列化 非字典类型数据 还需要指定 safe参数 为False
JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False})
form表单 需要具备的条件
multipart/form-data
获取表单数据
def func1(request):
if request.method=='POST':
print(request.POST)
return render(request,'login.html')
#获取到的 只是拿到文件 名称 并未 文件数据
<QueryDict: {'file': ['微信图片_20220824171248.jpg'], '提交': ['提交']}>
获取 文件携带 数据的操作
前端 必要操作
enctype="multipart/form-data"
<form action="/func1/" method="post" enctype="multipart/form-data">
后端操作
request.FILEs
print(request.FILES) #获取 列表 套对象
file_obj=request.FILEs.get('file')
获取 的是文件迭代器对象 可以点name 方法 获取文件名 然后通过 for循环 写入
def func1(request):
if request.method=='POST':
print(request.FILES)
file_pbj=request.FILES.get('file')
with open(file_pbj.name,'wb')as f:
for data in file_pbj:
f.write(data)
return render(request,'login.html')
FBV:基于函数的视图
#views
def func(request):
return HttpResponse()
#urls
path('index/',views.index)
CBV:基于类的视图
#views
from django import views
class Myviews(views.View):
def get(self,request):
return HttpResponse('CBV GET方式')
def post(self,requset):
return HttpResponse('CBV,POST方式')
#urls
path('func3/',views.Myviews.as_view()
CBV 源码分析
源码分析路口
path('func3/',views.Myviews.as_view()
绑定类的as_view方法
@classonlymethod
def as_view(cls, **initkwargs): # 通过 装饰语法 将其定义为类的属性方法
...
def view(request, *args, **kwargs):
self = cls(**initkwargs)
...
return self.dispatch(request, *args, **kwargs)
...
return view #最后 返现 返回的是 view函数
发现CBV路由匹配的本质 跟FBV是一致的
#都是 点 函数的形式
path('func/', views.view) #都是 通过访问路由 然后 调用函数
访问到func 触发view函数执行
def view(request, *args, **kwargs):
self = cls(**initkwargs) #类产生一个对象 就是 我们写的类产生的对象, cls 是我们自己写的类 点 as_views 传进来的
...
#最后 对象 点 dispatch 先从 对象本身找该方法 没有 再到父类找
return self.dispatch(request, *args, **kwargs)
研究dispatch方法
# http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
def dispatch(self, request, *args, **kwargs):
# 请求方式小写字符串 在不在 后面这个列表里面面
if request.method.lower() in self.http_method_names:
# 面向对象 反射 通过字符串请求方式 获取 对象内属性 赋值给变量
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
#最后 变量 直接执行该方法 即执行 我们写的类下的方法
return handler(request, *args, **kwargs)
方式一:指名道姓的传
return render(request,'modal.html',{'name':name})
方式二:关键字locals()
return render(request,'modeal.html',locals())
基本数据类型直接传递使用
函数名:
函数名的传递会自动加括号执行 并将返回值展示到页面上
注意
函数如果有参数则不会执行也不会展示 模板语法不支持有参函数
类名:
类名得传递也会自动加括号产生对象 并展示到页面上
对象:
对象得传递则直接使用即可
规律:
模板语法会判断每个名字是否可调用 如果可以则调用
类似于python的内置函数
<p>同级长度:{{ s|length }}</p>
<p>数字加法运算:{{ i|add:100 }}</p>
<p>字符串拼接:{{ s|add:'python' }}</p>
<p>日期转换:{{ res|date:'Y-m-d H:i:s' }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<p>数据切片:{{ l|slice:'0:4' }}</p>
<p>字符截取:(按字符个数截取 三个点 算一个){{ s|truncatechars:6 }}</p> #超出范围 会返回完整的数据
<p>单词截取:(三个点不算 按空格截取){{ s|truncatewords:2 }}</p>
<p>语法转义:{{ script|safe }}</p> # 重点
<p>语法转义 (后端转):{{ script_mak }}</p>
后端语法转义
from django.utils.safestring import mark_safe
script_mak=mark_safe('我在干饭
')
<p>语法转义 (后端转):{{ script_mak }}</p>
类似于 python中流程控制
django 模板语法中符号 就两个 {{}}
{% %}
需要使用数据的时候{{}}
需要使用方法的时候{% %}
分支结构
# if...elif..else
{% if '' %} # 条件 一般是模板语法传过来的数据 直接写名字就行 不需要双大括号
<p>哈哈哈</p>
{% elif '2'%}
<p>嘿嘿嘿</p>
{% else %}
<p>呵呵呵</p>
{% endif %}
for循环
{% for re in s %}
{% if forloop.first %}
<p>这是第一次</p>
{% elif forloop.last %}
<p>这是最后一次</p>
{% else %}
<p> {{ re }}</p>
{% endif %}
{% empty %}
<p>是空的无法循环</p>
{# {{ forloop }}#}
{% endfor %}
如果想自定义 必须做以下三件事
在应用下创建名为templatetags文件夹
在该文件夹传进啊任意名称的py文件
在该py文件内编写自定义相关代码
from django.template import Library
register = Library()
在temp latetags 文件夹下创建任意名称py文件
过滤器 至多只能有两个函数
from django.template import Library
register = Library()
# 自定义 过滤器
@register.filter(name='myfilter')
def my_add(a, b):
return a + b
引用过滤器
{% load mytags %} #引用
{{ i|myfilter:1 }}
@register.simple_tag(name='mt')
def func(a, b, c, d):
return a + b + c + d
引用函数
{% load mytags %}
{% mt 1 2 3 4 %}
@register.inclusion_tag(filename='it.html')
def index(n):
html = []
for i in range(n):
html.append('第%s页'%i)
return locals()
引用函数
将要 变动的 内容 利用block包起来
#模板 继承 母板内容
{% extends 'html文件名' %} # 继承了 就可以 获取的 该文件 所有内容
{% block 名字 %}
模板内容
{% endblock %}
{% block 名字 %} #创建标记
子板内容
{% endblock %}
一般情况下母板中至少应该有三个区域使得扩展性更高!!!
{% block css %}
{% endblock %}
{% block content %}
{% endblock %}
{% block js %}
{% endblock %}
{子板中 可以使用母版的内容}
模板 导入到 母版
将html页面的某个部分当做模块的形式导入使用
{% include 'menu.html' %} #只能是 部分