Django之视图层
Django之视图层
JsonResponse
JsonResponse是用来反回json格式的数据的.
1.因为要实现前后端分离, 那么他就是基于json格式来进行格式传输的.比如后端就专门写接口,前端调用这个接口,就能拿到一个json格式的字符串.然后前端在通过序列化反序列化转换成前端对应的数据类型.
json常用数据类型:
数值类型
字符类型
数组
自定义对象
undefined与null
布尔值 true False
symbol
前端序列化和反序列化
JSON.stringify 序列化 ---> json.dumps
JSON.parse 反序列化 ----> json.loads
from表单上传数据
form表单上传文件
注意事项:
1.提交的方式必须是post
2.enctype参数必须有默认值urlencoded变成formdata
FBV与CBV之CBV源码分析
FBV与CBV 即CBV源码分析
FBV(Function Based View) 基于函数的视图
CBV(Class Based View) 基于类的视图
你在类中写了两个方法 一个叫get一个叫post
为什么前端get请求来就会触发get方法
post请求来就会触发post方法 如何实现的???
# CBV路由
url(r'^reg/',views.MyReg.as_view())
@classonlymethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
self = cls(**initkwargs) # cls就是我们自己的写的MyReg类
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
# 上面的一通操作 就是给我们自己写的类的对象赋值
return self.dispatch(request, *args, **kwargs)
# 对象在查找属性或方法的时候 顺序是什么? 先从自己找 再从产生对象的类中找 再去类的父类中找...
"""也就意味着你在看源码的时候 你一定要牢记上面的话"""
return view
# views.py
from django.views import View
class MyReg(View):
def get(self,request):
return render(request,'reg.html')
def post(self,request):
return HttpResponse("我是MyReg类中post方法")
"""CBV最精髓的部分"""
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names: # 判断当前请求方式在不在默认的八个请求方式中
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
# handler = getattr(自己写的类产生的对象,'小写的请求方法(get\post)','获取不到对应的方法就报错')
# handler就是我们自己定义的跟请求方法相对应的方法的函数内存地址
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) # 在调用获取到的方法
模板传值
模板传值
传函数名的时候 会自动加括号调用函数 将函数的返回值展示在html页面上
django模板语法不支持函数传参
django模板语法在获取容器类型内部元素的值的时候 统一只采用 句点符(.)
过滤器
1.add过滤器:
{{ value|add:"2" }} 用来做拼接.如果是int会相加
2.cut过滤器:
{{ value|cut:" "}} 会移除所有的空格
3.date过滤器:
{{ birthday|date:"Y/m/d" }} 将一个日期安照指定格式变成字符串反回
4.default过滤器:
{{ value|default:"0"}} 可以设置默认值
5.first过滤器
{{ value|first }} 反回列表/元祖/字符串的第一个元素
标签
1.标签用于解决编码问题,提高灵活性,方便项目管理
2.标签的语法:you{% 和 %}来定义的, 例如: { %tag% }{% endtag%}
1.if/else标签
{% if condition1 %}
display1
{% elif condition2 %}
display2
{% else %}
display3
{ %endif% }
根据条件判断是否输出, if/else支持嵌套
接受 and, or 或则 not关键字来对多个变量做判断
2.for标签
1.# 遍历每一元素
{% for person in person_list %}
<p>{{ person.name }}</p>
{% endfor %}
2.#可以利用{% for obj in list reversed %}反向循环
3.遍历每一个字典
{% for key,val in dic.items %}
<p>{{key}}:{{val}}</p>
{% endfor %}
4.循环序号可以通过{{ forloop }} 显示
forloop.counter 当前循环的索引值(从1开始)
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(从1开始)
forloop.revcounter0 当前循环的倒序索引值(从0开始)
forloop.first 当前循环的第一次循环则返回True,否则反回False
forloop.last 当前循环是最后一次循环则反回True, 否则反回False
forloop.parentloop 当前循环的外层循环
5.for标签可以带有一个可选的{% empty %} 从句, 在变量person_list为空或者没有被找到时,则执行 empty子句
{% for person in person_list %}
<p>{{person.name }}</p>
{% empty %}
<p>sorry,no person here</p>
{% endfor %}
演示:
url(r'^test/', views.test),
def test(request):
names = ['kang', 'wei']
dic = {'name': 'Kang', 'age': 14, 'sex': 'male'}
list1 = []
return render(request, 'test.html', locals())
<body>
<hr>
{% for name in names %}
<p>{{ forloop.counter0 }}</p>
{% endfor %}
取出:
0
1
<hr>
{% for name in names reversed %}
<p>{{ forloop.revcounter0 }}</p>
{% endfor %}
取出:
1
0
<hr>
{% for k, v in dic.items %}
<p>{{ forloop.counter }} {{ k }}:{{ v }}</p>
{% endfor %}
取出:
1 name:kang
2 age:16
3 sex:male
{% for item in list1 %}
<p>{{ item }}</p>
{% empty %}
<p>sorry, no value here</p>
{% endfor %}
取出:
sorry, no value here
</body>
常用之with标签
#with标签用来为一个复杂的变量起别名,如果变量的值来自于数据库,在起别名后只需要要使用别名即可,不需要每一次都向数据库发送请求,来从新获取变量值
{% with li.1.user as v %}
{{ v }}
{% endwith %}
#常用之csrf_token标签
1.当用from表单提交POST请求时必须加上标签{% crsf_token %},该标签用于防止跨站伪造请求
<form action="" method="POST">
<% csrf_token %>
<p>用户名: <input type="text" name="name"></p>
<p>密码: <input type="password" name="pwd"></p>
<p><input type='submit' value="提交"></p>
</form>
#具体工作原理:
1.在GET请求到form表单时,标签{% csrf_token %}会被渲染成隐藏的input标签,该标签包含了由服务端生成的一串随机字符串,如:<input type="hidden" name="hjkasdhfjkds" value="hfdsiaf">
2.在使用form表单提交POST请求时,会提交上诉随机字符串, 服务端在接收到该POST请求时会对比随机字符串,对比成功则处理该POST请求,否则拒绝,以此来确定客户端的身份.
自定义过滤器、 标签
当内置的过滤器或标签无法满足我们的需求的时候,我们就可以自定义,具体操作步骤如下
步骤:
1.在应用名下新建一个templatetags文件夹,(规定必须是这个名字)
2.在这个文件夹下面,新建一个任意名称的py文件.
3.在这个py文件内你要固定的写两行代码:
from django.template import Library
register = Lobrary()
1.自定义过滤器:
@register.filter
def my_milti_filter(v1, v2): # 自定义的过滤器只能定义最多两个参数, 针对{{ value | filter_multi:value2 }},参数传递为v1=value, v2=value2
return v1 * v2
2.自定义标签
@register.simple_tag
def my_multi_tag(v1, v2): #自定义的标签可以定义多个参数
return v1 * v2
4. 自定义过滤器或标签必须重新启动django方可生效
5. 自定义过滤器或标签的使用
<body>
<!--必须先加载存有自定义过滤器和标签的文件-->
{% load my_tags %}
<!--salary的值为10,经过滤器my_multi_filter的处理结果为120-->
{{ salary|my_multi_filter;12 }}
<!--结果为2-->
{% my_multi_tag 1 2%}
##对比自定义标签与自定义过滤器
1.自定义过滤器只能传两个参数, 而自定义标签却可以传多个参数
2.过滤器可以用于if判断,而标签不能
{% if salary|my_multi_filter:12 > 200 %}
<p>优秀</p>
{% else %}
<p>垃圾</p>
{% endif %}
模板的继承
模板的继承
事先需要在模板中 通过block来划定区域.
{% block 区域名字 %}
{% endblock %}
子版如何使用
{% extends 区域名字 %}
{% block %}
<h1>登录页面<h1>
{% endblock %}
在一个页面上面 block块越多, 那么页面的扩展性也就越高.
在统称情况下都应该有三片区域
{% block css %} #css不同
{% endblock %}
{% block content %} #中间的一些内容
{% endblock %}
{% block js %} #js的不同
{% endblock %}
子板中还可以通过
{{ block.super }} 来继续使用母版的内容
模板的导入
模板的导入
当你写了一个比价好看的form表单,你想在多个页面中去调用它,你就可以将你写的form表单当作模块的形式导入. 导入过来之后就可以直接展示.
{% include 'good_page.html' %}