目录
- 视图层
- 模板层
视图层
一.视图函数返回的都是一个HttpResponse对象
render 和 redirect 都是直接或者间接传的
二.JsonResponse
下面这个是正常的json的序列化
views.py 层
def test1(request):
user_dict={'username':'jason 顶天立地 ','password':123}
json_str= json.dumps(user_dict,ensure_ascii= False)###保证中文不会转成bytes
return HttpResponse(json_str)
浏览器展示的:
{"username": "jason 顶天立地 ", "password": 123}
JsonResponse 序列化
from django.http import JsonResponse
def test1(request):
user_dict={'username':'jason 顶天立地 ','password':123}
# json_str= json.dumps(user_dict,ensure_ascii= False)
return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})#后面的这个代表的是保证中文不会转成bytes
浏览器展示的:
{"username": "jason 顶天立地 ", "password": 123}
如果序列的不是字典样式
def test1(request):
# user_dict={'username':'jason 顶天立地 ','password':123}
# json_str= json.dumps(user_dict,ensure_ascii= False)
l1=[1,'磁场强大','人缘极好']
return JsonResponse(l1,json_dumps_params={'ensure_ascii':False},safe=False)###最后safe为False这个保证非字典 也可以识别
浏览器展示的:
[1, "磁场强大", "人缘极好"]
三.form表单的上传
home.html
Title
views.py
def test1(request):
if request.method == 'POST':
print(request.FILES)
file_obj= request.FILES.get('myfile')
print(file_obj.name)
with open(file_obj.name,'wb') as f:
for line in file_obj:
f.write(line) ###把图片保存起来
return render(request,'home.html')
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
]}>
333.png
FILES可以通过这个拿到文件
注意:form表单上传文件
1.必须做的事
method必须是post
enctype必须是formdata
2.暂时需要做的
提交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)
四.ab_render的原理
from django.template import Template,Context
def ab_render(request):
temp=Template('{{user_dict}}
')
user_dict = Context({'user_dict':{'username':'jason','password':123}})
res= temp.render(user_dict)
return HttpResponse(res)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
浏览器显示的:
{'username': 'jason', 'password': 123}
五.FBV 和CBV
视图函数并一定就是函数 也可以是类
FBV:基于函数的视图
CBV:基于类的视图
下面是CBV的类的视图
urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^ab_render/', views.ab_render),
url(r'^login/', views.MyLogin.as_view()), #这个是路由与视图函数对应关系相当于url(r'^login/', views.view)
]
views
from django.views import View
class MyLogin(View):
def get(self,request):
return render(request,'login.html')
def post(self,request):
return HttpResponse('我是类里面post的方法')
login.html
Title
遇到上面的这个我们需要考虑一下,并且考虑 一些源码的问题
朝login提交get请求会自动执行MyLogin里面的get方法
而提交post请求也会自动执行MyLogin里面的post方法
为什么MyLogin针对不同的请求方法能够自动执行对应的方法
研究源码的突破口
url(r'^login/',views.MyLogin.as_view())
猜想
as_view要么是类里面定义的普通函数 @staticmethod
要么是类里面定义的绑定给类的方法 @classmethod
看源码发现是绑定给类的方法
CBV源码(******)
MyClass.as_view()
# 函数名加括号执行优先级最高
@classonlymethod
def as_view(...):
def view(...):
...
return view
# 变形
url(r'^index/',views.view) # CBV与FBV在路由匹配上本质是一样的
def view(...):
self = cls(...) # 生成的是我们自己写的类的对象
...
return self.dispatch(...)
"""
当你看到self.属性或方法的时候 不要想当然
一定要遵循对象的属性和方法的查询顺序
对象本身 产生对象的类 类的父类
"""
def dispatch(...):
# 先判断当前请求方式是否在默认的八个合法请求方式内
if request.method.lower() in ['get','post','delete','options'...]
# 利用反射获取对象中对应的属性
handler = getattr(self,request.method.lower(),报错信息)
return handler(...) # 执行获取到的方法
FBV和 CBV在路由匹配上本质是一样的,都是路由和函数内存地址的对应关系
六.importlib
我们正常的通过模块可以获取模块里面的值
conf包 里面有b.py
name= 'david'
a.py
# from conf import b
# print(b.name)
>>>>>>>>>>>>>>>>>>>>
david
上面的我们可以用其他的importlib来写
conf包 里面有b.py
name= 'david'
a.py
import importlib
res= 'conf.b'
md=importlib.import_module(res)
#该方法的最小单位是模块 不是模块里面的单个名字
print(md.name)
>>>>>>>>>>>>>>>>>>>>
david
模板层
一.模板传值
python基本数据类型全部支持传递给html文件
函数
类
函数和对象会自动加括号
# 模板语法不支持传参
对象
后端给html文件传递数据的两种方式
1.指名道姓
return render(request,'index.html',{'n':n,'f':f})###放在一个字典里
2.locals() # 会将当前名称空间中所有的变量名全部传递给html页面
return render(request,'index.html',locals())
html页面上 如何获取到后端传递过来的数据
{{ 变量名 }}
取值
django模板语法取值 只有一种操作方式 句点符 .
点索引
点键
{{ l.2 }}
{{ d.username }}
{{ d.password }}
{{ d.hobby.1.username.1 }}
8种数据类型和函数 、类 、对象传递给html文件
views
def index(request):
#python的所有的数据类型都支持传递给html页面
n=11
f=11.111
s='hello world'
l=[1,2,3,4,5,6]
d={'username':'jason','password':123,'hobby':['read',{'username':['egon','jason']}]}
t=(1,2,3,4,5,6,)
se={1,2,3,4,5}
b= True
ff= False
ss='dsdkljgjsg sjg;d djle dejs;egl dee kd;le;lk '
sss='是的K歌 警方介入进来大家多 罚款交了比较 房间里人家给 外婆'
file_size= 3290237579476
def func():
print('func 被执行了')
return 'from func'
class MyClass(object):
def get_self(self):
return 'from self'
@staticmethod
def get_func():
return 'from func'
@classmethod
def get_cls(cls):
return 'from cls'
obj = MyClass()
return render(request,'index.html',locals())
index.html
Title
{#{{ n }}
#}
{#模板语法的注释 这个注释前端浏览器检查是看不见的#}
{#{{ f }}
#}
{#{{ s }}
#}
{#{{ l }}
#}
{#{{ d }}
#}
{#{{ t }}
#}
{#{{ se }}
#}
{#{{ b }}
#}
{#函数名会自动加括号执行 展示的是函数的返回值:{{ func }} 模板语法不支持给函数传参
#}
{#传类名 也会自动加括号实例化 拿到的是对象地址{{ MyClass }}
#}
{#{{ MyClass }}
#}
{#{{ MyClass.get_func }}
#}
{#{{ MyClass.get_cls }}
#}
{#{{ MyClass.get_self }}
#}
{#{{ obj }}
#} ##得到的是对象的地址
{#{{ obj.get_func }}
#}
{#{{ obj.get_self }}
#}
{#{{ obj.get_cls }}
#}
{#取值
#}
{#{{ l.2 }}
#}
{#{{ d.username }}
#}
{#{{ d.password }}
#}
{#{{ d.hobby.1.username.1 }}
#}
二.模板的过滤器
如下是具体的语法
|length:求长度
|add:增加值
|default :设置默认值 如果是True 返回True 如果是false 返回默认值
|truncatechars: 截取字符 后面加3个点
|truncatewords:截取单词 后面加3个点
|filesizeformat:文件大小 换算成多少B
|slice :切片
|date: 转化成日期格式
|safe:转义 可以把css js等样式渲染到前端
views
def index(request):
from datetime import datetime
s= 'hello world dvdlej vdnelegjn nej dje vnle vgjnlew ldeg gel eglkkeg '
a= 12
b= True
ff = False
file_size= 298355976576
ddd= datetime.now()
res= '你好啊
'
res1= ''
return render(request,'index.html',locals())
index.html
{#过滤器 |左边的会当做过滤器的第一个参数 过滤器名右边的会当做过滤器的第二个参数
#}
{#求数据长度:{{ s|length }}
#}
{#加法运算:{{ n|add:10 }}、{{ s|add:13132 }}、{{ s|add:'DSB' }}
#}
{#默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}、{{ ff|default:'这个ff布尔值是Flase' }}
#}
{#截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}
#}
{#截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}、{{ sss|truncatewords:4 }}
#}
{#文件大小:{{ file_size|filesizeformat }}
#}
{#切片操作:{{ s|slice:'0:2' }}、{{ s|slice:"0:8:2" }}
#}
{#日期格式化:{{ ddd|date:'Y年/m月/d日' }}
#}
{#转义:{{ res|safe }}、{{ res1 }}、后端直接标识安全:{{ res2 }}
#}
浏览器的显示结果
70
True、2222ff
he...
hello world dvdlej vdnelegjn nej dje vnle vgjnlew ...
277.9 GB
he
2020年/01月/07日
你好啊
前后端取消转义
前端
|safe
后端
from django.utils.safestring import mark_safe
mark_safe('
安全滴
')总结:前端代码不一定非要在前端页面写,可以在后端写好传递给前端页面使用
这样的话 你就可以利用到后端更加多的逻辑语法
下面是举例
from django.utils.safestring import mark_safe
res2= mark_safe('积极阳光帅气
')
return render(request,'index.html',locals())
index.html
{{ res2 }}
三.模板语法逻辑相关
forloop 对象
判断for循环的开始结束的位置
索引 计数
如下是在html页面上
{# {% for foo in l %}#}
{#{{ forloop }}#}
{# {% endfor %}#}
打印的结果是:
{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 6, 'revcounter0': 5, 'first': True, 'last': False} {'parentloop': {}, 'counter0': 1, 'counter': 2, 'revcounter': 5, 'revcounter0': 4, 'first': False, 'last': False} {'parentloop': {}, 'counter0': 2, 'counter': 3, 'revcounter': 4, 'revcounter0': 3, 'first': False, 'last': False} {'parentloop': {}, 'counter0': 3, 'counter': 4, 'revcounter': 3, 'revcounter0': 2, 'first': False, 'last': False} {'parentloop': {}, 'counter0': 4, 'counter': 5, 'revcounter': 2, 'revcounter0': 1, 'first': False, 'last': False} {'parentloop': {}, 'counter0': 5, 'counter': 6, 'revcounter': 1, 'revcounter0': 0, 'first': False, 'last': True}
###第一个是True 最后一个是True
for 循环 if 判断
views.py 里面的是 l=[1,2,3,4,5,6]
html页面
{% for foo in l %}
{% if forloop.first %}
这是我的第一次
{% elif forloop.last %}
这个是最后一次
{% else %}
{{ foo }}
{% endif %}
{% endfor %}
浏览器结果
这是我的第一次
2
3
4
5
这个是最后一次
如果是空的 可以用下面的empty来判断
views.py 里面的是 l=[]
html页面
{% for foo in l %}
{% if forloop.first %}
这是我的第一次
{% elif forloop.last %}
这个是最后一次
{% else %}
{{ foo }}
{% endif %}
{% empty %} {# 这个是用来的判断的 如果容器内没有值#}
for循环的对象没有值
{% endfor %}
四.对于多用和常用的可以起个别名
这个别名只能在with里面使用
views.py
def index(request):
d = {"username": 'jason', 'password': 123, 'hobby': ['read', {'username': ['jason', 'egon']}]}
return render(request,'index.html',{'l':l,'d':d} )
index.html
{% with d.hobby.1.username.1 as eg %}
别名{{ eg }}
{% endwith %}
五.自定义的过滤器、标签 、inclusion_tag
自定义过滤器 标签 inclusion_tag
先完成以下前期准备工作
1.在应用名下新建一个名字必须叫templatetags文件夹
2.在该文件夹内新建一个任意名称的py文件(eg:mytag)
3.在该文件内 必须先写以下两句代码
from django.template import Library
register= Library()
总结 页面上使用他们 统一先导入
{% load mytag %}
mytag.py
from django.template import Library
register= Library()
#自定义的过滤器
@register.filter(name= 'my_sum')
def index(a,b):
return a +b
#自定义的标签
@register.simple_tag(name= 'my_baby')
def index1(a,b,c,d):
return '%s?%s?%s?%s?'%(a,b,c,d)
#自定义inclusion_tag
@register.inclusion_tag('demo.html',name='myin')
def index(n):
l=[]
for i in range(n):
l.append(i)
#将列表传递给demo.html ## 这个return给demo.html在上面@register这个里面
return {'l':l}
index.html
自定义的过滤器
{% load mytag %}
{{ 10|my_sum:90 }}
{% if 10|my_sum:100 %}
条件成立
{% endif %}
>>>>>>>>>>>>>>>>>>>>>>>
100
自定义的标签
{% load mytag %}
{% my_baby 1 2 3 'hello world' %}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
1?2?3?hello world?
自定义的inclusion_tag的使用
{% load mytag %}
{% myin 5 %}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
0
1
2
3
4