视图层
小白必备三板斧
HTTPresponse 返回字符串
render 返回HTML页面
redirect 重定向
视图函数必须有一个返回值,并且返回值的数据类型必须是HttpResponse对象
JsonResponse
前后端分离
前后端数据交互,如何进行
通常情况下前后端数据交互采用的都是json的字符串(字典)后端只需要写好相应的url接口,前端访问你的接口
后端只需要返回一个大字典+开发文档,用来告诉前端工程师接口返回什么数据
前后端序列化反序列化
python后端 js
json.dumps JSON.stringify
json.loads JSON.parse
from django.http import JsonResponse
def index(request):
user_dic={'name':'jason好帅','password':'123'}
# json_str=json.dumps(user_dic)#{"name": "jasonu597du5e05", "password":"123"}
#如何让json不会对中文转码
json_str=json.dumps(user_dic,ensure_ascii=False)#{"name": "jason好帅", "password": "123"}
# return HttpResponse(json_str)
# return JsonResponse(user_dic)#{"name": "jasonu597du5e05", "password": "123"}
# return JsonResponse(user_dic,json_dumps_params={'ensure_ascii':False})#{"name": "jason好帅", "password": "123"}
l=[1,2,3,4,5,6,7,8,9]
#JsonResponse默认是序列化字典用的,如果想要序列化其他数据类型(json模块能够序列化的),需要加一个safe参数
return JsonResponse(l,safe=False)
FBV与CBV
FBV:基于函数的视图
CBV:基于类的视图
from django.views import View
class MyLogin(View):
def get(self,request):
print('mylogin里的get方法')
return render(request,'login.html')
def post(self,request):
print('mylogin里post方法')
return HttpResponse('post')
路由的写法
#FBV写法 路由》》》视图函数内存地址
url(r'^index/', views.index),
#CBV写法
url(r'^login/', views.MyLogin.as_view()),
给CBV加装饰器,推荐使用内置模块
1.直接写
import time
from functools import wraps
def ouuter(func):
@wraps(func)
def inner(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
end_time=time.time()-start_time
print('函数只执行的时间%s'%end_time)
return res
return inner
class MyLogin(View):
@ouuter
def get(self,request):
print('mylogin里的get方法')
return render(request,'login.html')
@ouuter
def post(self,request):
print('mylogin里post方法')
time.sleep(1)
return HttpResponse('post')
2.使用内置模块
import time
from functools import wraps
from django.utils.decorators import method_decorator
def ouuter(func):
@wraps(func)
def inner(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
end_time=time.time()-start_time
print('函数只执行的时间%s'%end_time)
return res
return inner
# @method_decorator(ouuter,name='post')#指定给那个方法加装饰器
class MyLogin(View):
@method_decorator(ouuter)#如果在视图函数执行前,做一些操作,可以在CBV中定义dispatch方法拦截4
#下面两个方法都加了装饰器
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
# @method_decorator(ouuter)
def get(self,request):
print('mylogin里的get方法')
return render(request,'login.html')
# @method_decorator(ouuter)
def post(self,request):
print('mylogin里post方法')
time.sleep(1)
return HttpResponse('post')
CBV的源码
django settings源码
基于settings源码,应用到我们自己的项目中去
模板层
模板语法
只有两种书写格式:
{{ }} 变量相关
{% %} 逻辑相关
模块传值
可以传哪些数据类型:
基本数据类型全都支持
{#基本数据类型全部支持#}
<p>{{ n }}</p>
<p>{{ f }}</p>
<p>{{ s }}</p>
<p>{{ l }}</p>
<p>{{ d }}</p>
<p>{{ se }}</p>
<p>{{ t }}</p>
<p>{{ b }}</p>
<p>传函数名:{{ index1 }}</p>
{#给HTML页面传递函数名的时候,模板语法会自动加括号,调用函数,并将函数的返回值当作展示依据#}
{#模板语法不支持函数传参,也就意味着,传给HTML页面的只能是不需要传参的函数#}
<p>传类名:{{ MyClass.get_self }}</p>
<p>传类名:{{ MyClass}}</p>
{#传类名 自动加括号实例化对象,可以调用对象的方法#}
<p>传对象:{{ obj }}</p>
<p>传对象:{{ obj.get_self }}</p>
<p>传对象:{{ obj.get_cls }}</p>
<p>传对象:{{ obj.get_func }}</p>
总结:只要是能够加括号调用的,传递到HTML页面上会自动加括号调用
def test(request):
n=1
f=1.11
s='hello world'
l=[11,22,33,44,55]
d={'username':'json','passowrd':'123'}
t=(11,22,33,44,55)
se={1,2,3,4,5}
b=True
def index1():
return 'index1的返回值'
class MyClass(object):
def get_self(self):
return 'get_self'
@classmethod
def get_cls(cls):
return 'get_cls'
@staticmethod
def get_func():
return 'get_func'
obj=MyClass()
#给HTML页面传值的方式
#第一种 指名道姓 当需要传递的变量名特别多的情况下,有点麻烦
# return render(request,'test.html',{'n':n})
#第二种 locals()会将当前所在名称空间中所有的名字全部传递给HTML页面
return render(request,'test.html',locals())
过滤器
模板语法也提供了一些内置方法,帮你快速处理数据(会自动将|做左边的数据当作过滤器的第一个参数传入,:右边的当作第二个参数传入
最多只能有两个参数
前后端取消转义
前端 |safe
后端 res=mark_safe()
<p>模板语法之过滤器</p>
<p>统计长度(如果无法统计默认返回0):{{ s|length }}</p>
<p>加法运算(内部异常捕获,支持数字相加 字符串拼接 都不符合返回空):{{ n|add:f }}</p>
<p>切片操作 顾头不顾尾 支持步长:{{ l|slice:'0:5:2' }}</p>
<p>判断是否有值(有值展示值本身,没值展示默认值):{{ is_value|default:'is_value变量值为空' }}</p>
<p>自动转成文件大小格式{{ file_size|filesizeformat }}</p>
<p>截取文本内容(字符)截取五个字符 三个点也算:{{ s|truncatechars:5 }}</p>
<p>截取文本内容(按照空格计算)截取五个单词 三个点不算:{{ s1|truncatewords:5 }}</p>
<p>默认情况下,是不会自动帮你转换成前端HTML标签 防止恶意攻击</p>
<p>展示带有标签的文本:{{ sss|safe }}</p>
<p>展示带有标签的文本:{{ sss1|safe }}</p>
<p>{{ res }}</p>
标签
逻辑相关,if for循环
{% for foo in l %}
<p>{{ forloop }}</p>
{% endfor %}
{% for foo in l %}
{% if forloop.first %}
<p>这是第一次</p>
{% elif forloop.last %}
<p>这是最后一次</p>
{% else %}
<p>{{ foo }}</p>
{% endif %}
{% empty %}
<p>当for循环的对象是空的时候会走</p>
{% endfor %}
<p>模板语法的取值 只有一种方式,统一采用句点符(.)</p>
<p>{{ comp_dic.hobby.2.2.age }}</p>
<p>如果数据是通过比较复杂的点点点获取到的,后续又要经常使用,可以给数据起个别名,别名只能在with内部使用</p>
{% with comp_dic.hobby.2.2.age as age %}
<p>{{ age }}</p>
<p>{{ comp_dic.hobby.2.2.age }}</p>
{% endwith %}
自定义过滤器和标签
django支持用户自定义
必须要有的三步:
1.在应用名下新建一个名字必须叫templatetags的文件夹
2.在该文件夹内,新建一个任意名称的py文件
3.在py文件内写下面两句
from django.template import Library
register=Library()
mytag.py
from django.template import Library
register=Library()
#自定义过滤器,跟我忍的过滤器一样,最多是能接受两个参数
@register.filter(name='baby')
def index(a,b):
return a+b
#自定义标签,可以接受任意多的参数
@register.simple_tag(name='mytag')
def login(a,b,c,d):
return '%s%s%s%s'%(a,b,c,d)
#自定义inclusion_tag
@register.inclusion_tag('mytag.html',name='xxx')
def index111(n):
l=[]
for i in range(n):
l.append('第%s项'%i)
return locals()#将l直接传递给mytag.html页面
.html
<p>自定义过滤器的使用</p>
{% load mytag %}
{{ 1|baby:1 }}
{{ 1|baby:100 }}
<p>自定义标签的使用,可以接受多个参数,参数与参数之间必须空格隔开</p>
{% load mytag %}
{% mytag 'a' 'b' 'c' 'd' %}
<p>自定义的过滤器可以在逻辑语句使用,而自定义的标签不可以</p>
{% if 1|baby:1 %}
<p>有值</p>
{% else %}
<p>无值</p>
{% endif %}
<p>自定义inclusion_tag的使用,当你需要使用一些页面组件的时候,并且该页面组件需要参数才能够正常渲染,可以使用Inclusion_tag</p>
{% load mytag %}
{% xxx 5 %}
mytag.html
<ul>
{% for foo in l %}
<li>{{ foo }}</li>
{% endfor %}
</ul>
模板的继承
需要事先在想要使用的页面,划定区域,之后在继承的时候,就可以使用你划定。如果不划定区域,就无法修改页面
先在页面上利用block划定你以后可能改的区域
{% block content %}
{% endblock %}
继承以后,就可以通过名字找到对应的区域进行修改
{% extends 'home.html' %}
{% block conent%}
修改模板中content区域内容
{% endblock %}
模板上的block区域越多,页面的扩展性就越强
建议一个模板页面至少有三块区域
css区域
html代码区域,可以设置多个block
js区域
有了这三块区域,就能实现每个页面都有自己独立的css和js代码
{% extends 'home.html' %}
{% block css %}
<style>
p {
color: red;
}
</style>
{% endblock %}
{#针对想要修改的区域 做内容的变更#}
{% block content %}
<p>我改成reg页面内容</p>
{{ block.super }}用父标签原来的
{% include 'bform.html' %} 导入
{% endblock %}
{% block js %}
<script>
alert('reg')
</script>
{% endblock %}
还可以在子页面上继续沿用父页面的内容
模板的继承:
1.现在要继承的页面上通过block划定你将来可能要改的区域
2.在子页面上先继承extends
3.利用block自动提示,选择想要修改的内容区域
模板的导入
将HTML页面当模块直接导入使用
{% include 'html页面' %}
{#针对想要修改的区域 做内容的变更#}
{% block content %}
<p>我改成reg页面内容</p>
{{ block.super }} 用父标签原来的
{% include 'bform.html' %} 导入
{% endblock %}