django4/网页伪静态/视图层/模板层
网页伪静态
动态页
动态网页,页面代码虽然没有变,但是显示的内容却是可以随着时间、环境或者数据库操作的结果而发生改变的。
静态页
即静态网页,是实际存在的,无需经过 服务器 的 编译 ,直接加载到客户 浏览器 上显示出来。
特点
1、静态网页每个网页都有一个固定的URL,且网页URL以.htm、.html、.shtml等常见形式为后缀,而不含有“?”。2、静态网页是实实在在保存在服务器上的文件,每个网页都是一个独立的文件。
3、静态网页的内容相对稳定,因此容易被搜索引擎检索;
-------------缺点--------------------------------------------------------------
4、静态网页没有数据库的支持,在网站制作和维护方面工作量较大,因此当网站信息量很大时完全依靠静态网页制作方式比较困难;
5、静态网页的交互性较差,在功能方面有较大的限制。
6、页面浏览速度迅速,过程无需连接数据库,开启页面速度快于动态页面。
7、减轻了服务器的负担,工作量减少,也就降低了数据库的成本。
伪静态页
将动态网页伪装成静态网页,从而提升网页被搜索引擎收录的概率
表现形式就是网址看着像一个具体的文件路径
-------------=--------------------
#路由层urls.py可以直接写一个。
path('index.html',view.index)
伪静态页的缺点
使用伪静态将占用一定量的CPU占有率,大量使用将导致CPU超负荷;
降低服务器访问承载量比如服务器能承载1000人,开启大量伪静态后,三百人。
视图层
每新添加一个功能都应该在路由文件 urls.py 中添加一个路由与视图的对应关系(请求路径的时候才有对应的 视图函数/类 去处理)
最简单的步骤:
先创建app
配置路由(路由与视图函数的对应关系)
写视图函数(要用到 HttpResponse, redirect,记得自己导过来)
编写模板页面
视图函数返回值
视图函数必须返回一个HttpResonse对象
HttpResponse
class HttpResponse(...):
pass
render
def render(...):
return HttpResponse(...)
redirect
def redirect(...):
# 多继承
1.视图层返回值问题,必须返回一个什么?
当我们在视图层返回None,或者不返回时,页面报错,需要我们必须返回一个HttpResponse对象;
小疑问?
那么视图层,三板斧中,除了返回HttpResponse我们比较觉得合理
返回的render和redirect为什么不报错呢?底层源码其实他俩调用的也是HttpResponse对象
from django.shortcuts import render, HttpResponse,redirect
#以下是部分源码
class HttpResponse(HttpResponseBase):
pass
-----------render源码中也是返回的HttpResponseBase对象-------------------------------------
def render(request, template_name, context=None, content_type=None, status=None, using=None):
"""
Return a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status)
----------------redirect源码中也是返回的HttpResponseBase对象---------------------------------------
def redirect(to, *args, permanent=False, **kwargs):
redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
return redirect_class(resolve_url(to, *args, **kwargs))
2.视图函数返回json格式数据
小需求:不借助模板语法,视图层返回数据给浏览器,如图
两种方法
1.借助httpResponse,jsondump
user_dict = {'name': 'lzl', 'pwd': 1111, 'hobby': ['read', 'music']}
json_str = json.dumps(user_dict, ensure_ascii=False) #有中文的情况,把转码关闭掉。
return HttpResponse(json_str)
2.借助JsonResponse [用这个]
from django.http import JsonResponse
def index(request):
user_dict = {'name': 'lzl中文不转码', 'pwd': 1111, 'hobby': ['read', 'music']}
return JsonResponse(user_dict)
return JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False}) #中文不转码
如果想返回非字典类型数据
序列化非字典类型的数据还需要指定safe参数为False
from django.http import JsonResponse
def index(request):
l1 = [1,2,3,4,5,6,7,8,'lzl牛']
return JsonResponse(l1, json_dumps_params={'ensure_ascii':False},safe = False)
JasonResponse是源码底层封装json
def __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 = json.dumps(data, cls=encoder, **json_dumps_params)
super().__init__(content=data, **kwargs)
3. form表单携带文件数据
小需求:浏览器上传文件数据,通过前端传给后端数据
1.前端form表单
2.后端
form表单需要具备的条件
1.method 属性必须是post
2.enctype属性必须是multipart/form-data
<form action="" method="post" enctype=multipart/form-data></form>
3.后端获取文件数据的操作
request.FILES
#示例 获取
#v
file_obj = request.FILE.get('file')
print(file_obj.name)
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:基于函数的视图
CBV:基于类的视图
FBV示例
#urls.py路由层
from django import views
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', view.index),
]
#views视图层
from django import views
def index(request):
return HttpResponse()
CBV示例
#urls.py路由层
from django import views
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', view.index),
path('func/', views.MyView.as_view()),
]
#views视图层
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会自动根据请求方式的不同匹配类中定义的方法并自动执行
模板层
1.模板语法传值两种方式
方式1:指名道姓传参,不浪费资源,
def modal(request)
name = 'lzl'
return render(request,'modal.html',{'name':name})
方式二:关键字local() 将整个局部名称空间中的名字去全部 传入简单快捷
def modal(request)
name = 'lzl'
age = '18'
time = '7'
return render(request,'modal.html',locals())
2.模板语法传值范围特性
1.基本数据类型(整型,浮点型,字符串,元组,列表)直接传递使用
#基本数据类型
#路由层
--------------------------------views.py--------------------------------------------
def modal(request):
i = 123
f = 11.11
s = 'hello world'
l = [11, 22, 33]
d = {'name':'jason', 'pwd':123, 'others':[11, {'a':123, 'b':[111, 222, 333]},22]}
t = (11, 22, 33)
se = {11, 22, 33}
b = True
return render(request,'modal.html')
#模板层
-------------------------------modal.html--------------------------------------------
<!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>内容
{# <p>{{ i }}</p>#}
{# <p>{{ f }}</p>#}
{# <p>{{ s }}</p>#}
{# <p>{{ l }}</p>#}
{# <p>{{ d }}</p>#}
{# <p>{{ t }}</p>#}
{# <p>{{ se }}</p>#}
{# <p>{{ b }}</p>#}
{# <p>{{ d.name }}</p>#}
{# <p>{{ l.2 }}</p>#}
{# <P>{{ d.others.1.b.2 }}</P>#}
2.函数名的传递会自动加括号执行并返回值展示到页面上
def modal(request):
def func1():
print('哈哈哈')
return '你到底行不行'
<p>{{ func1 }}</p>
------页面展示效果------------
你到底行不行
3.注意函数如果有参数则不会执行也不会展示,模板语法不支持有参函数
def modal(request):
def func1(a,b):
print('哈哈哈')
return '你到底行不行'
<p>{{ func1 }}</p>
------页面不展示效果(模板语法不支持传参)------------
4.类名的传递也会自动加括号产生对象并展示到页面上
def modal(request):
class MyClass(object):
def get_obj(self):
return 'obj'
@classmethod
def get_cls(cls):
return 'cls'
@staticmethod
def get_func():
return 'func'
obj = MyClass()
----------------模板层modal.html--------------------------------------------
#前端 body内容
<p>{{ MyClass }}</p>
#名的传递也会自动加括号产生对象并展示到页面上
如果类调用打印对象
<p>{{ obj.get_obj }}</p>
<p>{{ obj.get_cls }}</p>
<p>{{ obj.get_func }}</p>
5.对象的传递则直接使用即可
#前端 body内容
<p>{{ obj }}</p>
ps:模板语法会判断每个名字是否可调用,如何可以则调用
注意!!!
django的模板语法在操作容器类型的时候只允许使用句点符
3.模板语法的过滤器(类似于python内置函数)
过滤器大概有五六十个,我们简单的罗列一些。
#路由层
--------------------------------views.py-------------------------
def modal(request):
i = 123
f = 11.11
s = 'hello world'
l = [11, 22, 33]
d = {'name':'jason', 'pwd':123, 'others':[11, {'a':123, 'b':[111, 222, 333]},22]}
t = (11, 22, 33)
se = {11, 22, 33}
b = True
from datetime import datetime
#日期
res = datetime.today()
#文件大小
file_size = 214324322432344353234
return render(request,'modal.html')
=================modal.html==================================
#模板层body内容
<p>统计长度:{{s|length}}</p>
<p></p>加法运算:{{i|add:123}}、加法运算:<p>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>单词截取(一个空格算一个)</p>
重点掌握过滤器
过滤器重点:语法转义
#为什么要加safe参数?
因为前端默认是不加载视图层的脚本标签语法的,如果默认加载,后果就是一旦后端写死循环弹出框,或者不友好的脚本,浏览器会直接崩溃,如果我们写的一定要加载,在后面跟上safe参数即可,告诉前端页面,此代码可以加载。
#视图层
-----------------------视图层view.py-------------------------
def modal(request):
script_tag = '<h1>还认识我吗???</h1>'
from django.utils.safestring import mark_safe
script_tag1 = '<script>alert(666)</script>'
res = mark_safe(script_tag1)
return render(request,'modal.html')
----------------------前端模板层modal.html-------------------------------
#body内容
<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 模板语法中的符号就两个,一个{{}} 一个{%%}
需要使用数据的时候{{}},类似于上述的取值操作
需要使用方法的时候{%%},类似于之前的反向解析操作
4.模板语法标签(类似于python的流程控制)
以下是常用的,还有一些冷门的了解
#body内容
{% if 条件 %} 条件一般是模板语法传过来的数据 直接写名字使用即可
条件成立执行的代码
{% elif 条件1 %}
条件1成立执行的代码
{% else %}
条件都不成立执行的代码
{% endif %}
{% for i in s %}
{% if forloop.first %}
<p>这是第一次哟~</p>
{% elif forloop.last %}
<p>这是最后一次!</p>
{% else %}
<p>{{ i }}</p>
{% endif %}
{% empty %}
<p>你给我的是个空 怎么for循环呢</p>
{% endfor %}
5.自定义相关功能(了解)
一般写全栈的时候会用到。
1.标签函数,
2,过滤器
3.inclusion_tag
如果想自定义 必须先做以下三件事
1.在应用下创建一个名为templatetags文件夹(文件夹名字必须为templatetags)
2.在该文件夹创建任意名称的py文件
3.在该py文件内编写自定义相关代码
from django.template import Library
register = Library()
# 自定义过滤器
@register.filter(name='myfilter')
def my_add(a, b):
return a + b
---------------------------------------------------- -----------
# 自定义标签函数
@register.simple_tag(name='mt')
def func(a, b, c, d):
return a + b + c + d
-------------------------------------------------------------
# 自定义inclusion_tag
@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.模板的继承
1.模板的继承作用?
为了减少代码的编写
2.使用方法
#主模板调用
{% block 名字 %}
模板内容
{% endblock %}
2.把字模板html文件内容清理
3.调用继承文件
#字模板调用
{% etends 'html文件名' %}
4.子板内容修改
{% block 名字 %}
子板内容
{% endblock %}
一般情况下母板中至少应该有三个区域使得扩展性更高!!!
css
content
js
-------#css---------------------------------
{% block css %}
{% endblock %}
-------#content---------------------------
{% block content %}
{% endblock %}
----#js-----------------
{% block js %}
{% endblock %}
'''子板中还可以使用母板的内容 {{ block.super }} '''
7.模板的导入(了解)
将html页面的某个部分当做模块的形式导入使用
{% include 'menu.html' %}