django学习笔记
今日内容概要
- 网页伪静态
- 视图层
- 模板层
今日内容详细
网页伪静态
动态页面:用ASP、PHP、JSP、ASP.net、Perl、或CGI等编程语言制作,不是独立存在于服务器上的网页文件,只有当用户请求时服务器才返回一个完整的网页,内容存在于数据库中,根据用户发出的不同请求,其提供个性化的网页内容。
静态页面:静态页面的URL链接是以.html、htm、.shtml、.xml为链接后缀,存在于服务器上的一个文件,每个网页都是一个独立的文件,内容直接保存在文件中,没有连接数据库。
网页伪静态:将动态网页伪装成静态网页,从而提升网页被搜索引擎收录的概率。
表现形式就是网址看着像一个具体的文件路径
伪静态好处:把网页做成伪静态最主要的就是为了搜索引擎方便搜索引擎蜘蛛(Spider)来抓取网页上的相关内容;提高用户对网页的信任度,因为伪静态的后缀也是.html .htm .shtml .xml;网页静态化也影响着网站在搜索引擎的排名;伪静态明确了网站的URL链接,可以更好的让用户传播、浏览以及输入;伪静态不需要全站生成静态页面,可节省服务器空间使用率。
path('index.html', view.index)
视图层
视图函数的返回值
视图函数必须返回一个HttpResponse对象。(HttpResponse其实是一个类)
HttpResponse
class HttpResponse(HttpResponseBase):
return HttpResponse()
render
def render(...):
return HttpResponse(...)
redirect
def redirect(to, *args, permanent=False, **kwargs):
redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect # 三元表达式
return redirect_class(resolve_url(to, *args, **kwargs))
视图函数返回json格式数据
将下列数据用json格式展示到网页
user_dict = {'name': 'jason老师', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
json方法
def obj_json(request):
json_str = json.dumps(user_dict, ensure_ascii=False)
return HttpResponse(json_str)
JsonResponse方法
from django.http import JsonResponse
def obj_json(request):
return JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False}, safe=False)
'''序列化非字典类型的数据还需要指定safe参数为False'''
JsonResponse源码解析
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)
super().__init__(content=data, **kwargs)
from表单携带文件数据
form表单上传的数据中如果含有文件,那么需要做以下几件事。
第一:method属性值必须是post。
第二:enctype属性值必须修改为multipart/form-data,默认是application/x-www-form-urlencoded。
第三:后端需要使用request.FILES获取,然后就可以通过句点符和with open等查看和下载文件信息。
request补充方法
方法 | 说明 |
---|---|
request.body | 存放的是接收过来的最原始的二进制数据,request.POST、request.GET、request.FILES这些获取数据的方法其实都从body中获取数据并解析存放的 |
request.path | 获取路径 |
request.path_info | 获取路径 |
request.get_full_path() | 获取路径并且还可以获取到路径后面携带的参数 |
FBV与CBV
FBV:基于函数的视图
def index(request):
return HttpResponse()
path('index/', views.index)
CBV:基于类的视图
from django import views
class MyView(views.View):
def get(self, request):
return HttpResponse('我是CBV里面的get方法')
def post(self, request):
return HttpResponse('我是CBV里面的post方法')
path('func/', views.MyView.as_view())
"""
CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行
"""
CBV源码分析
源码分析入口
path('func/', views.MyView.as_view())
1.切入点:路由匹配
类名点属性as_view并且还加了括号
as_view可能是普通的静态方法
as_view也可能是绑定给类的方法
2.对象查找属性的顺序
先从对象自身开始、再从产生对象的类、之后是各个父类
MyView.as_view()
先从我们自己写的MyView中查找,没有再去父类Views中查找
3.CBV路由匹配本质:跟FBV是一致的
项目已启动就会执行as_view方法 查看源码返回了一个闭包函数名view
def as_view(cls):
def view(cls):
pass
return view
path('func/', views.view)
# 函数名加括号执行优先级最高
4.路由匹配成功之后执行view函数(访问func触发view执行)
def view(...):
obj = cls() # cls我们直接写的类,加括号产生一个自己写的类的对象
return obj.dispatch(request, *args, **kwargs)
'''涉及到对象点名字 一定要确定对象是谁 再确定查找顺序'''
5.研究dispatch方法
def dispatch(...):
# 利用getattr反射(通过字符串操作对象的属性和方法)
#参数:obj自己写的类产生的对象,当前的请求方法。 handler就等于自己写的类里的请求方法
handler = getattr(obj, request.method.lower())
# 返回的时候加括号传承调用自己写的类里的请求方法
return handler(request, *args, **kwargs)
ps:查看源码也可以修改,但是尽量不要这么做,很容易产生bug。
模板层
模板语法传值
django提供的模板语法只有两个符号:
{{}}:主要用于数据;{%%}:主要用于方法。
传值的两种方式
# 方式1:指名道姓的传,适用于数据量较少的情况,节省资源
return render(request, 'modal.html', {'name':name})
# 方式2:打包传值(关键字locals()),将整个局部名称空间中的名字全部传入,适用于数据量较多的情况,简单快捷
return render(request,'modal.html',locals())
模板语法传值的范围
数据类型 | 说明 |
---|---|
基本数据类型 | 都可以直接传递使用 |
函数名 | 传递会自动加括号执行并将返回值展示到页面上,函数如果有参数不会执行也不会展示,模板语法不支持有参函数 |
类名 | 传递会自动加括号产生对象并展示到页面上 |
对象 | 直接传递使用(显示对象的地址,并且具备调用属性和方法的能力) |
文件名 | 直接显示文件IO对象 |
django的模板语法在操作容器类型的时候只允许使用句点符
data1 = {'info':{'pro':[11, 22, 33, {'name':'jason','msg':'努力就有收获'}]}}
{{ data1.info.pro.3.msg }} # 既可以点key也可以点索引 django内部自动识别
模板语法过滤器(类似于python内置函数)
<p>统计长度:{{ s|length }}</p>
<p>加法运算:{{ i|add:123 }}</p>、<p>加法运算:{{ s|add:'heihei' }}</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>
# 在前端使用 |safe
<p>语法转义:{{ script_tag|safe }}</p> # safe:将后端写的代码可以在前端被识别被转换
# 在后端使用mark_safe
from django.utils.safestring import mark_safe
script_tag1 = '<script>alert(666)</script>'
res = mark_safe(script_tag1)
<p>{{ res }}</p>
ps:有时候html页面上的数据不一定非要在html页面上编写了 也可以后端写好传入
模板语法标签(类似于python流程控制)
在django模板语法中写标签的时候,只需要写关键字然后tab键就会自动补全。
1.if判断
{% if 条件 %} # 条件一般是模板语法传过来的数据 直接写名字使用即可
条件成立执行的代码
{% elif 条件1 %}
条件1成立执行的代码
{% else %}
条件都不成立执行的代码
{% endif %}
2.for循坏
{% for i in s %}
{% if forloop.first %}
<p>这是第一次哟~</p>
{% elif forloop.last %}
<p>这是最后一次!</p>
{% else %}
<p>{{ i }}</p>
{% endif %}
{% empty %} # # empty 循环对象为空执行
<p>你给我的是个空 怎么for循环呢</p>
{% endfor %}
forloop关键字:{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 4, 'revcounter0': 3, 'first': True, 'last': False}
# counter0:从0开始计数;counter:从一开始计数;first': 是否是第一次循环;last是否是最后异常循环
补充:如果数据是字典,同样提供了keys、values、items方法。
a={'name':jason,'age':18}
{{ for i in a.keys}}
<p>{{ i }}</p> # name age
{% endfor %}
{{ for i in a.values}}
<p>{{ i }}</p> # jason 18
{% endfor %}
{{ for i in a.items}}
<p>{{ i }}</p> # ('name',jason) ('age',18)
{% endfor %}
自定义过滤器、标签函数、inclusion_tag
如果想自定义,必须做以下三件事:
1.在应用下创建一个名为templatetags文件夹
2.在该文件夹创建任意名称的py文件
3.在该文件内编写自定义相关固定代码
from django.template import Library
register = Library()
自定义过滤器:只能接收两个参数
@register.filter(name='myfilter') # 括号内可以通过name给过滤器取别名
def my_add(a, b):
return a + b
# 在html页面使用过滤器需要先导入创建的py文件模块
{% load mytag %}
{{ i|myfilter:1 }}
自定义标签函数:可以接收任意参数
@register.simple_tag(name='mt')
def func(a, b, c, d):
return a + b + c + d
{% load mytag %}
{% mt 1 2 3 4 %} # 参数之间空格隔开即可
自定义inclusion_tag
@register.inclusion_tag(filename='it.html')
def index(n):
html = []
for i in range(n):
html.append('第%s页'%i)
return locals()
#it.html里内容
<ul>
{% for i in html %}
<li>{{ i }}</li>
{% endfor %}
</ul>
'''该方法需要先作用于一个局部html页面 之后将渲染的结果放到调用的位置 类似于封装了一个能够快速产生html代码的方法'''
{% load mytag %}
{% index 10 %}
模板的继承
类似于面向对象的继承:继承了某个页面就可以使用该页面上所有的资源。
如果我们想要继承获取一个页面的大部分只修改一部分代码,我们也可以用继承来实现。
母页面
# 先在母板中通过block划定将来可以被修改的区域(可以有多个)
{% block 名字 %}
母板内容
{% endblock %}
子页面
{% extends 'html文件名' %} # html文件名是母页面的HTML文件名,继承了母页面
{% block 名字 %} # 这里写的内容可以直接修改母页面里可以被修改的区域
子板内容
{% endblock %}
'''子板中还可以使用母板的内容 {{ block.super }} '''
模板上最少应该有三个区域可以让子页面继承:css区域、内容区域、js区域。子页面就可以有自己独立的css、js、内容
{% block css %}
css修改内容
{% endblock %}
{% block 名字 %}
子板内容
{% endblock %}
{% block js %}
js修改内容
{% endblock %}
子页面还可以重复使用父页面的内容
{{ block.super }}
模板的导入
类似于将html页面上的局部页面做成模块的形式,哪个地方想要直接导入即可展示。
使用方式
{% include 'menu.html' %}
注释语法补充
<!----> 是HTML的注释语法
{##} 是django模板语法的注释
"""
HTML的注释可以在前端浏览器页面上直接查看到
模板语法的注释只能在后端查看 前端浏览器查看不了
"""
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了