文章目录
Django视图层进阶、模板层
一、视图层
三板斧:
HttpResponnse、redirect、render视图函数返回都是一个HttpResponse对象
JasonResponse
可以试着阅读以下方法的源码(jsonresponse)
import json
json.dumps({'username':'你好啊'},ensure_ascii=False) # 不会转码
from django.http import JsonResponse
user_dict = {'username':'你好啊'}
return JsonResponse(user_dict)
参数
1.json_dumps_params 字典
JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
2.safe
该方法默认只用来序列化字典
l = [1,2,3,4]
JsonResponse(l,safe=False)
form表单上传文件
-
必须做的事
method必须是post
enctype必须是formdata
-
暂时需要做的事
提交post请求需要将中间件里面的一个csrfmiddleware注释掉(权限认证)
后端获取用户上传的文件
file_obj = request.FILES.get('前端input框name属性值')
file_obj.name # 文件名
for line in file_obj:
print(line)
# django中推荐以下写法
for chunk in file_obj.chunks():
print(chunk)
render简单实现原理
def ab_render(request):
temp = Template("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>")
user_dict = Context({'user_dict':{'username':'jason','password':123}})
res = temp.render(user_dict)
return HttpResponse(res)
视图函数并不一定是函数,也可以是类
FBV:基于函数的视图
CBV:基于类的视图
CBV基本写法
from django.views import view
class MyLogin(view):
def get(self,request):
return render(request,'login.html')
def post(self,request):
return HttpResponse('我是类里面的post方法')
url(r'^login/',views.MyLogin.as_view())
朝login提交get请求会自动执行MyLogin里面的get方法
而提交post请求也会自动执行MyLogin里面的post方法
为什么MyLogin针对不同的请求方法能够自动执行对应的方法
CBV源码
url(r'^login/',views.MyLogin.as_view())
猜想
as_view要么是类里面定义的普通函数 @staticmethod
要么是类里面定义的绑定给类的方法 @classmethod
看源码发现是绑定给类的方法(看源码不需要每一句都看懂 只看自己能够看得懂)
二、模板层
{{}} 变量相关
{%%} 逻辑相关
模板语法传值
python基本数据类型全部支持传递给HTML文件
类:
- 函数和对象会自动加括号
- 模板语法不支持传参
对象:
后端给HTML文件传递数据的两种方式
-
指名道姓
return render(request,'index.html',{'n':n,'f':f})
-
locals() #会将当前名称空间所有的变量名全部传递给HTML页面
return render(request,'index.html',locals())
html页面上,获取到后端传递过来的数据
{{ 变量名 }}
取值:
django模板语法取值,只有一种方式—句点符。
点索引、点键
<p>{{ l.2 }}</p>
<p>{{ d.username }}</p>
<p>{{ d.password }}</p>
<p>{{ d.hobby.1.username.1 }}</p>
过滤器
|length
|add
|default
|truncatechars
|truncatewords
|filesizeformat
|slice
|date
|safe
#验证之前先定义好|左边的变量
<p>过滤器 |左边的会当做过滤器的第一个参数 过滤器名右边的会当做过滤器的第二个参数</p>
1. <p>求数据长度:{{ s|length }}</p>
2. <p>加法运算:{{ n|add:10 }}、{{ s|add:13132 }}、{{ s|add:'DSB' }}</p>
3. <p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}、{{ ff|default:'这个ff布尔值是Flase' }}</p>
4. <p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}</p>
5. <p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}、{{ sss|truncatewords:4 }}</p>
6. <p>文件大小:{{ file_size|filesizeformat }}</p>
7. <p>切片操作:{{ s|slice:'0:2' }}、{{ s|slice:"0:8:2" }}</p>
8. <p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}</p>
9. <p>转义:{{ res|safe }}、{{ res1 }}、后端直接标识安全:{{ res2 }}</p>
前后端取消转义
前端:
|safe
后端:
取消转义模块,告诉前端界面字符串内的标签正常显示在页面上,否则就是一串普通字符。
from django.utils.safestring import mark_safe
mark_safe('<h1>安全滴</h1>')
总结:前端代码不一定非要在前端页面写,可以在后端写好后传递给前端页面使用,这样的话,你就可以利用到后端更加多的逻辑语法。
模板语法之标签(逻辑相关)
{% for foo in l %} <!--l = [1,2,3,4,5,6]-->
{% if forloop.first %}
<p>这是我的第一次</p>
{% elif forloop.last %}
<p>这是最后一次了啊~</p>
{% else %}
<p>{{ foo }}</p>
{% endif %}
{% empty %}
<p>for循环的对象内部没有值</p>
{% endfor %}
#first代表第一个,last代表最后一个执行结果为:
这是我的第一次
2
3
4
5
这是最后一次了啊~
自定义过滤器及标签 inclusion_tag
先完成一下前期准备工作
-
在应用名下新建一个名字必须叫templatetags文件夹
-
在该文件夹内新建一个任意名称的py文件(eg:mytag)
-
在该文件内,必须先写以下两句代码
from django.template import Library register = Library()
自定义过滤器
@register.filter(name='my_sum')
def index(a,b):
return a + b
<p>自定义过滤器的使用</p>
{% load mytag %}
<p>{{ 10|my_sum:90 }}</p>
<p>自定义的过滤器可以在逻辑语句中而自定义的标签不可以</p>
{% if 10|my_sum:100 %}
<p>条件成立</p>
{% endif %}
自定义标签
@register.simple_tag(name='my_baby')
def xxx(a,b,c,d):
return '%s?%s?%s?%s'%(a,b,c,d)
<p>自定义标签的使用</p>
{% load mytag %}
<p>{% my_baby 1 2 3 'hello world' %}</p>
{% if my_baby 1 2 3 4 %}
<p>条件成立</p>
{% endif %}
自定义inclusion_tag
@register.inclusion_tag('demo.html',name='myin')
def index1(n):
l = []
for i in range(n):
l.append(i)
# 将列表传递给demo.html
# return locals()
return {'l':l}
<p>自定义inclusion_tag的使用</p>
{% load mytag %}
{% myin 5 %}
使用 总结 页面上使用他们 统一先导入
{% load mytag %}
模板的继承
某一个页面大部分区域是公用的,那这个页面就可以作为模板页面,当别人继承这个页面之后,如何修改对应的区域
先在模板页面上通过block实现划定区域
{% block content %}
模板页面内容
{% endblock %}
子页面中先导入整个模板
{% extends '模板页面.html'%}
修改特定的区域 通过实现划定好的区域名称
{% block content %}
子页面内容
{% endblock %}
通常情况下,模板页面应该起码有三块区域
{% block css %}
模板页面内容
{% endblock %}
{% block content %}
模板页面内容
{% endblock %}
{% block js %}
模板页面内容
{% endblock %}
模板的block块越多,可扩展性越高,还支持子页面调用父页面对应区域的内容,并且可以无限次调用。
{{ block.super }}
模板的导入
将HTML页面当作模块使用,哪里需要就导哪里,这个HTML页面通常都不是完整的,只是一个局部样式
{% include 'left.html' %}
基于django settings源码实现项目配置文件的,插拔设计