今日内容详细
- 网页伪静态
- 视图层
- 模板层
网页伪静态
1.本质
将动态网页伪装成静态网页,从而提升网页被搜索引擎收录的概率。
2.表现形式
表现形式就是网址看着像一个具体的文件路径。path('index.html',view.index)
视图层
1.视图函数的返回值问题
视图函数必须返回一个HttpResponse对象
注意HttpResonse其实是一个类
class HttpResponse(HttpResponseBase): pass
def render(): return HttpResponse(...)
def redirect(to, *args, permanent=False, **kwargs): redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect return redirect_class(resolve_url(to, *args, **kwargs))
2.视图函数返回json格式数据
- 前戏之展示json存数据
def index(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方法
def index(request): user_dict = {'name':'jason老师','pwd':123,'hobby':['read','run','music']} return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
推导方法如下:
from django.http import JsonResponse class JsonResponse(HttpResponse): def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs): if json_dumps_params is None: json_dumps_params = {} data = json.dumps(data, cls=encoder, **json_dumps_params)
- 序列化非字典类型的数据还需要指定safe参数为False
return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False},safe=False)
3.form表单携带文件数据
- 前端需要:form表单需要具备的条件
(1)method属性值必须是post (2)enctype属性值必须是multipart/form-data <form action="" method="post" enctype="multipart/form-data">
- 前端完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <form action="" method="post" enctype="multipart/form-data"> <p>username: <input type="text" name="username"> </p> <p>file: <input type="file" name="file"> </p> <input type="submit" value="提交"> </form> </body> </html>
- 后端获取文件数据的操作
request.FILES
- 后端完整代码
def index(request): if request.method == 'POST': print(request.POST) # <QueryDict: {'username': ['jason']}> print(request.FILES) # <MultiValueDict: {'file': [<InMemoryUploadedFile: 9.9.md (application/octet-stream)>]}> file_obj = request.FILES.get('file') print(file_obj.name) # 9.9.md # 将文件保存到后端 with open(file_obj.name,'wb')as f: for line in file_obj: # 循环写入 f.write(line) return render(request,'index.html')
4.FBV与CBV
- FBV:基于函数的视图
def index(request): return HttpResponse() path('index/', views.index)
- CBV:基于类的视图
后端view.py文件: from django import views class MyView(views.View): def get(self, request): return HttpResponse('我是CBV里面的get方法') def post(self, request): return HttpResponse('我是CBV里面的post方法') 后端urls.py文件: urlpatterns = [ # CBV路由匹配 path('func/', views.MyView.as_view()) ]
CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行。
5.CBV源码分析(重要)
源码分析入口
path('func/', views.MyView.as_view())
源码分析步骤
- 绑定给类的as_view方法
def as_view(...): def view(...): pass return view
- CBV路由匹配本质:跟FBV是一致的
path('func/', views.view)
- 访问func触发view执行
def view(...): obj = cls() return obj.dispatch()
涉及到对象点名字,一定要确定对象是谁,再确定查找顺序!!!
- 研究dispatch方法
def dispatch(...): func_name = getattr(obj,request.method.lower()) func_name(...)
模板层
1.模板语法传值
- 方式1:指名道姓 指名道姓传参 不浪费资源
def modal(request): # 方式一:指名道姓的传 name = 'jason' return render(request,'modal.html',{'name':name})
- 方式2:关键字locals() 将整个局部名称空间中的名字去全部传入简单快捷
def modal(request): name = 'jason' age = 18 gender = 'male' # return render(request,'modal.html',{'name':name,'age':age,'gender':gender}) return render(request,'modal.html',locals())
2.模板语法传值的范围
django的模板语法在操作容器类型的时候只允许使用句点符
- 基本数据类型(整型,浮点型,列表,字典,布尔值,元组,集合)直接传递使用;
- 函数名的传递会自动加括号执行并将返回值展示到页面上;
注意函数如果有参数则不会执行也不会展示,没有传参功能,模板语法不支持有参函数。
- 类名的传递也会自动加括号产生对象并展示到页面上;
- 对象的传递则直接使用即可
ps:模板语法会判断每一个名字是否可调用 如果可以则调用!!!
3.模板语法过滤器(类似于python内置函数)
<p>统计长度:{{ s|length }}</p> <p>加法运算:{{ i|add:123 }}、加法运算:{{ s|add:'heiheihei' }}</p> <p>日期转换:{{ s|date:'Y-m-d H:i:s' }}</p> <p>文件大小:{{ file_size|filesizeformat }}</p> <p>数据切片:{{ l|slice:'0:10' }}</p> <p>字符截取(三个点算一个):{{ s1|truncatechars:6 }}</p> <p>单词截取(空格):{{ s1|truncatewords:6 }}</p> <p>语法转义:{{ script_tag|safe }}</p> <p>语法转义:{{ script_tag1|safe }}</p>
后端语法转义:
from django.utils.safestring import mark_safe script_tag1 = '<script>alert(666)</script>' res = mark_safe(script_tag1)
ps:有时候html页面上的数据不一定非要在html页面上编写了 也可以后端写好传入。
- django模板语法中的符号就两个,一个{{}}; 一个{%%}。
(1)需要使用数据的时候 {{}}
(2)需要使用方法的时候 {%%};包括流程控制,内置方法等。
4.模板语法标签(类似于python流程控制)
- 支持if判断:
条件一般为后端传来的值;直接写名字使用即可。 语法结构: {% if 条件 %} 条件成立执行的代码 {% elif 条件1 %} 条件1成立执行的代码 {% else %} 条件都不成立执行的代码 {% endif %}
- 支持for循环:
语法结构: {% for i in s %} {% if forloop.first %} <p>这是第一次哟~</p> {% elif forloop.last %} <p>这是最后一次!</p> {% else %} <p>{{ i }}</p> {% endif %} {% empty %} <p>你给我的是个空 怎么for循环呢</p> {% endfor %}
- with(定义一个中间变量,多用于一个复杂的变量起别名。)
语法结构: {% with d.others.1b.2 as aaa %} {{aaa}} {% endwith %}
5.自定义标签函数、过滤器、inclusion_tag
(1)如果想自定义 必须先做以下三件事:
- 在应用下创建一个名为templatetags文件夹
- 在该文件夹创建任意名称的py文件
- 在该py文件内编写自定义相关代码
from django.template import Library register = Library()
敲重点:自定义之后使用的时候需要在HTML页面先导入{% load 自定义内容 %}才能使用。
(2)自定义过滤器(过滤器最多只能有两个参数!!!)from django.template import Library register = Library() # 自定义过滤器 @register.filter(name='myfilter') def my_add(a,b): return a+b
(3)自定义标签函数
from django.template import Library register = Library() @register.simple_tag(name='mt') def func(a, b, c, d): return a + b + c + d
(4)自定义inclusion_tag
from django.template import Library register = Library() @register.inclusion_tag(filename='it.html') def index(n): html = [] for i in range(n): html.append('第%s页'%i) return locals()
{% load mytag %} {{ i|myfilter:1 }} {% mt 1 2 3 4 %} {% index 10 %}
6.模板的继承
语法结构: {% extends 'html文件名' %} {% block 名字 %} 模板内容 {% endblock %} {% block 名字 %} 子板内容 {% endblock %}
一般情况下母板中至少应该有三个区域使得扩展性更高!!!
分别是css;content;js。CSS: {% block css %} {% endblock %} content: {% block content %} {% endblock %} Js: {% block js %} {% endblock %} 注意:子板中还可以使用母板的内容 {{ block.super }}
扩展性更高,子板有自己的样式。
7.模板的导入(了解)
将html页面的某个部分当做模块的形式导入使用{% include 'menu.html' %}