Django-(4)

内容概览

  • 网页伪静态
  • 视图层
    • 视图函数的返回值
    • 视图函数返回JSON格式数据
    • form表单携带文件数据
    • FBV与CBV
    • CBV源码分析
  • 模板层
    • 模板语法传值
    • 模板语法传值的范围
    • 模板语法过滤器
    • 模板语法标签
    • 自定义标签函数、过滤器、inclusion_tag
    • 模板的继承
    • 模板的导入

网页伪静态

将动态网页伪装成静态网页,提升网页被搜索引擎收录的概率
表现形式就是使网址看上起像一个具体的文件路径

urls:
# 将路由写成文件路径的样式
urlpatterns=[
	path('home.html', views.home)
]

视图层

视图函数的返回值

如果视图函数不写返回值会直接报错
在这里插入图片描述

视图函数必须返回一个HttpResponse对象
render与redirect其实底层也是返回的HttpResponse对象
render:
在这里插入图片描述
redirect返回的是一个继承了HttpResponse的类的对象:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

视图返回JSON格式数据

想要返回JSON格式数据可以直接使用json模块序列化

def fn(request):
	import json
	user_dict = {'name': 'jason', 'age': 28}
	json_str = json.dumps(user_dict, ensure_ascii=False)  # 如果数据中有中文,需要设置ensure_ascii属性确保中文正常显示
	return HttpResponse(json_str)

但是django提供了一种更简便的方式

def fn(request):
	from django.http import JsonResponse
	user_dict = {'name': 'jason', 'age': 28}
	return JsonResponse(user_dict)

JsonResponse源码:

class JsonResponse(HttpResponse):
    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)  # 将json_dumps_params拆解为关键字参数
        super().__init__(content=data, **kwargs)

通过查看源码可以知道,使用JsonResponse想要使中文正常显示,返回值需要这样写:

return JsonResponse(data, json_dumps_params={ensure_ascii:False})
# 如果想要序列化非字典类型的数据还需要将参数safe设定为False
form表单携带文件数据

想要使后端接收到form表单发送的文件数据,需要下述条件:
from表单的method属性必须为post;enctype属性值必须是multipart/form-data

<form method='post' enctype='multipart/form-data'>
	<input class='file' name='file'>
	<input class='submit' value='提交'>
</form>

后端使用request.FILES接收

def fn(request):
	f = request.FILES.get('file')
	print(f.name)  # 可以用.name获取标签的name属性的值
FBV与CBV

FBV:基于函数的视图

"""urls"""
path('func/', views.func)
"""views"""
def func(request):
	return HttpResponse()

CBV:基于类的视图

"""urls"""
path('func/',views.MyView.as_view())
# path('路由',views.类名.内置的方法)
"""views"""
from django import views
class MyView(views.View):
	def get(self, request):
		return HttpResponse('get')
	
	def post(self, requese):
		return HttpResponse('post')

CBV会根据请求方式的不同匹配类中定义的方法并自动执行

CBV源码分析

源码分析入口:

path('func/', views.MyView.as_view())
# 在程序运行时,会直接调用as_view()方法

as_view:
在这里插入图片描述
返回了view方法名,那么路由匹配就可以看做是:

path('func/', views.MyView.view)

访问func/触发view执行,接下来就看view中发生了什么

def view(request, *args, **kwargs):
	self = cls(**initkwargs)  # cls是之前自动传入的类
	if hasattr(self, 'get') and not hasattr(self, 'head'):  # hasattr反射函数,通过字符串判断类里是否有get属性或方法
	    self.head = self.get
	self.setup(request, *args, **kwargs)
	if not hasattr(self, 'request'):
	    raise AttributeError(
	        "%s instance has no 'request' attribute. Did you override "
	        "setup() and forget to call super()?" % cls.__name__
	    )
	return self.dispatch(request, *args, **kwargs)  #相当于又用类调用了一个方法

dispatch:

def dispatch(self, request, *args, **kwargs):
    if request.method.lower() in self.http_method_names: 
    # http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] 如果请求方式是这常见的8个,那么就可以直接调用
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)  # request.method获取请求方式,lower转成小写然后获取
    else:
        handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs)  # return 调用返回值

模板层

模板语法传值
# 方式一:指定数据
return render(request, 'modal.html', {'data': data})
"""指定数据传参,不浪费资源;但是文件数量太多会很麻烦"""
# 方式而:关键字locals()
return render(request, 'madal.html'locals())
"""将整个局部名称空间中的名字全部传入,简单快捷;但是如果只需要一条数据而传了很多,那么造成了资源浪费"""
模板语法传值的范围

基本数据类型能够直接传递使用:
int、float、str、bool、list、tuple、set、dict
函数名的传递会自动加括号调用,并将返回值展示到html页面上;模板语法只支持无参函数,对于有参函数则不会执行和展示
python:

def func1(request):
    def fn1():
        return 'from fn1'

    def fn2(a):
        return 'from fn2'

    return render(request, 'myhtml01.html', locals())

html:

<p>{{ fn1 }}</p>
<p>{{ fn2 }}</p>

浏览器:
在这里插入图片描述
类名的传递也会自动加括号产生对象并将对象展示到页面上,而对象的传递则可直接使用
python:

def func1(request):
    class cls1(object):
        pass
    obj1 = cls1()
    return render(request, 'myhtml01.html', locals())

html:

<p>{{ cls1 }}</p>
<p>{{ obj1 }}</p>

浏览器:
在这里插入图片描述

模板语法过滤器(类似于python内置函数)

管道符|与冒号:左右不能有空格

1. 统计长度
	<p>{{ s|lenght }}</p>				统计s中值的数量
2. 加法运算
	<p> {{ i|add:666 }} </p>			将i中的值与666相加,可以是算数运算,也可以是字符串拼接;如果都报错则返回空字符串
3. 日期转换
	<p>{{ new_date|date:'Y-m-d H:i:s' }}</p>	将传入数据转换为格式化日期
4. 文件大小
	<p>{{ file_size|filesizeformat }}</p>		将传入数据转换为合适的单位展示,最大支持PB
5. 数据切片
	<p>{{ l1|slice:'0:2'}}</p>			将容器数据类型切片取值,遵循左闭右开原则
6. 字符截取
	<p>{{ s1|truncatechars:5 }}</p>		截取指定个数字符,如果数据没有被截取完,那么截取的最后一个字符会替换成...
	<p>{{ s1|truncatewords:2 }}</p>		按照空格截取指定个数数据,如果数据没有被截取完,那么在最后会添加...
7. 语法转义
	<p>{{ scr|safe }}</p>				传入的参数默认全都是字符串传入,使用语法转义后就可以从后端写html的代码,例如:
	scr = '<script>alert(123)</script> <h1>Title</h1>'

django模板语法中的符号就只有{{}}与{%%}两个
在需要使用数据的时候使用{{}}
在需要使用方法的时候使用{%%}

模板语法标签(类似于流程控制)
<!--if分支-->
{% if 条件1 %}	条件一般是模板语法传过来的数据,已经使用了{%%}符号就直接写名字即可
	条件1成立执行的代码
{% elif 条件2 %}
	条件2成立执行的代码
{% else %}
	上述条件都不成立执行的代码
{% endif %}  结束符

<!--for循环-->
{% for i in s %}
	{% if forloop.first %}
	    <p>判断是否为第一次循环</p>
	{% endif %} 
	{% if forloop.counter == 3 %}
	    <p>counter是当前循环次数,从1开始;counter0从0开始</p>
	{% endif %} 
	{% if forloop.revcounter == 1 %}
	    <p>revcounter是倒数,从1开始;revcounter0从0开始</p>
	{% endif %}
	{% if forloop.last %}
	    <p>判断是否为最后一次循环</p>
	{% endif %}
	{% empty %}
	    <p>传入循环的数据为空</p>
{% endfor %}
自定义标签函数\过滤器\inclusion_tag

如果想要使用自定义,有以下条件:

  1. 在应用下创建一个名为templatetags文件夹
  2. 在文件夹内创建一个py文件
  3. 在py文件内编写自定义相关代码
  4. py文件中输入代码
    from django.template import Library
    register = Library()
    
  5. 在html页面使用前需要先加载文件
{% load '创建的py文件' %}
  • 自定义过滤器
@register.filter(name='myfilter')
def my_add(a, b):
	return a + b
# 最多只支持两个参数传入
  • 自定义标签函数
@register.simple_tag(name='mt')
def fn(a, b, c, d):
	return a + b + c + d
# 能够使用多个参数
# 使用方式:{% fn 1 2 3 4 %}
  • 自定义inclusion_tag
@register.inclusion_tag(filename='myhtml.html')  
def fn2(n):
	num_list = []
	    for i in range(n):
        html.append(f'第{i}页')
    return locals()

myhtml:

<ul>
	<% for i in num_list %>
		<li>{{ i }}</li>
	<% forend %>
</ul>

提前写好一个动态网页,后续调用函数名相当于插入了一段html代码
使用方式:

{% fn2 5 %}
模板的继承

使用{% extends html文件名 %}就相当于是复制了指定html文件的代码过来
那么如果想要修改其中部分内容,则需要提前在母版中划分哪些部分需要修改
母版:

{% block 名字 %}
	待修改的模板内容
{% endblock %}

子版:

{% extends '母版名' %}
{% block 名字 %}
	修改的模板内容
	{{ block.super }}  <!--使用母版中的内容,类似于python中类super方法-->
{% endblock %}

一般情况下母版中至少应该有三个区域可更改:css、模板内容、script;使得扩展性更高

模板的导入

将html页面当做模块的形式导入使用

{% include 'html文件名' %}

类似于自定义inclusion_tag;区别在于模板导入的是一个静态的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值