路由:视图函数的内存地址

视图层

render方法是Template和Contex两个对象的组合使用

from django .template import Template,Context
def func1(request):
res = Template('<h1>{{user}}</h>')
con=Context({'user':{'username':'zhang','password':123,}})
return HttpResponse(res.render(con))

JsonResponse对象

JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应。

# ensure_ascii=False 默认等于True,设置成False,遇到中文不再进行转码,仅仅只是进行序列化,转换成json形式的字符串
import json
def func(request):
d={'a':1,'b':3,'c':3,'d':4,'e':'速度发货!!!!!!!'}
return HttpResponse(json.dumps(d,ensure_ascii=False),) #
from django.http import JsonResponse
def func(request):
d={'a':1,'b':3,'c':3,'d':4,'e':'速度发货!!!!!!!'}
l=[1,2,3,4,5,]
# return JsonResponse(d) # 加括号是个对象,内部也是基于json.dumps进行的序列化,默认遇到中文也会转成ASCII编码,
# return JsonResponse(d,json_dumps_params={'ensure_ascii':False}) # 遇到中文不转码
return JsonResponse(l,safe=False) # In order to allow non-dict objects to be serialized set the safe parameter to False. 根据报错信息,去源码找到JsonResponse不能序列化其他数据类型的原因,就是修改safe=True 为False,之后就能序列化其他数据类型(json模块能序列化的)了

CBV及源码分析

我们之前写过的都是基于函数的view,就叫FBV。还可以把view写成基于类的。

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') # 路由的书写 与CBV有点不同
# FBV写法 路由 >>> 视图函数内存地址
url(r'^index/',views.index),
# CBV写法
url(r'^login/',views.MyLogin.as_view()) # views.view 本质也是FBV
	 http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

     def http_method_not_allowed(self, request, *args, **kwargs):
logger.warning(
'Method Not Allowed (%s): %s', request.method, request.path,
extra={'status_code': 405, 'request': request}
)
return http.HttpResponseNotAllowed(self._allowed_methods()) @classonlymethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs): # 闭包函数
self = cls(**initkwargs) # cls是我们自己写的类 MyLogin self是我们自己定义的类的对象
# 在看源码的时候 你一定要把握住一个顺序 对象在查找属性和方法的时候
# 先从对象自身找 再去产生对象的类中找 再去类的父类中找
return self.dispatch(request, *args, **kwargs)
return view def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
# 判断当前请求方式在不在默认的八个方法内
# 1.先以GET请求为例
if request.method.lower() in self.http_method_names:
# 利用反射去我们自己定义类的对象中查找get属性或者是方法 getattr(obj,'get')
# handler = get方法
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) # 调用get方法

CBV 加装饰器的方式

使用装饰器装饰FBV

FBV本身就是一个函数,所以和给普通的函数加装饰器无差:

def wrapper(func):
def inner(*args, **kwargs):
start_time = time.time()
ret = func(*args, **kwargs)
end_time = time.time()
print("used:", end_time-start_time)
return ret
return inner # FBV版添加班级
@wrapper
def add_class(request):
if request.method == "POST":
class_name = request.POST.get("class_name")
models.Classes.objects.create(name=class_name)
return redirect("/class_list/")
return render(request, "add_class.html")

CBV 加装饰器的方式

类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。

Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器

#使用CBV时要注意,请求过来后会先执行dispatch()这个方法,如果需要批量对具体的请求处理方法,如get,post等做一些操作的时候,这里我们可以手动改写dispatch方法,这个dispatch方法就和在FBV上加装饰器的效果一样。

给CBV加装饰器 推荐你使用内置模块
from django.utils.decorators import method_decorator # 2.可以指定给谁装
# @method_decorator(wrapper,name='post') # name=... 表示指定给谁装
# @method_decorator(wrapper,name='dispatch')
class MyLogin(View):
@method_decorator(wrapper)
def dispatch(self, request, *args, **kwargs): # 如果你想在视图函数执行之前 做一些操作 你可以在你的CBV中定义dispatch方法来拦截 return super().dispatch(request,*args,**kwargs)
# @outter # 1.直接写
# @method_decorator(outter) # 1.推荐写法
def get(self,request):
print('我是MyLogin里面的get方法')
return render(request,'login.html')
# @outter
def post(self,request):
print('我是MyLogin里面的post方法')
time.sleep(1)
return HttpResponse('post')

模板层

模板语法传值

模板语法

		只有两种书写格式:
{{}} 变量相关
{%%} 逻辑相关 模板传值:python基本数据类型全部支持传值

变量

在Django的模板语言中按此语法使用:{{ 变量名 }}。

当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。 变量的命名包括任何字母数字以及下划线 ("_")的组合。 变量名称中不能有空格或标点符号。

点(.)在模板语言中有特殊的含义。当模版系统遇到点("."),它将以这样的顺序查询:

字典查询(Dictionary lookup)

属性或方法查询(Attribute or method lookup)

数字索引查询(Numeric index lookup)

注意事项:

  1. 如果计算结果的值是可调用的,它将被无参数的调用。 调用的结果将成为模版的值。
  2. 如果使用的变量不存在, 模版系统将插入 string_if_invalid 选项的值, 它被默认设置为'' (空字符串)
# test.py文件
def test(request):
n=1
f=1.11
s='hello baby~'
l=[1,2,3,4,]
t=(1,2,3,44,55)
d={'name':'zhangsan','hobby':'read'}
se={12,13,14,15,}
b=False
def index1(): #给HTML页面传递函数名的时候 模板语法会自动加括号调用该函数 并且将函数的返回值当做展示依据,模板语法不支持函数传参 也就意味着 你传给html页面的只能是不需要传参调用的函数
return '都是废话'
class Test(object):
def get_self(self):
return 'get_self'
obj = Test()
return render(request,'test.html',locals()) # 传类名像函数名一样,也是加括号调用,实例化一个对象;传对象,就是对象本身,是类的对象的内存地址;只要是能够加括号调用的 传递到html页面上都会自动加括号调用
<!--test.html文件-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head>
<body>
<p>{{ n }}</p>
<p>{{ f }}</p>
<p>{{ s }}</p>
<p>{{ l }}</p>
<p>{{ se }}</p>
<p>{{ d }}</p>
<p>{{ b }}</p>
<p>传函数名:{{ index1 }}</p>
<p>传函数名:{{ Test }}</p>
<p>传函数名:{{ obj }}</p>
</body>
</html>

过滤器(Filters)

模板语法也给你提供了一些内置的方法 帮你快速的处理数据

过滤器的语法: {{ value|filter_name:参数 }}

例如:{{ name|lower }}会将name变量应用lower过滤器之后再显示它的值。lower在这里的作用是将文本全都变成小写。

注意事项:

1.过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。

2.过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。

3.过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:', ' }}

4.'|'左右没有空格没有空格没有空格

前后端取消转义(*)


前端
|safe
后端
from django.utils.safestring import mark_safe
sss2 = "<h2>我的h2标签</h2>"
res = mark_safe(sss2)
<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:8 }}</p>
<p>截取文本内容(按照空格计算) 截取五个字符 三个点不算 :{{ s1|truncatewords:5 }}</p>
<p>默认情况下,不会转换成前端html标签 :{{sss}}</p> # 后端传来的字符串类型的标签
<p>展示带有标签的文本:{{ sss|safe }}</p> 添加safe参数之后可以转换后端传来的字符串标签
<p>展示带有标签的文本:{{ ss|safe }}</p> 后端: ss='<script>alert(123)</script>'

标签

标签 逻辑相关

if

for循环

{% for foo in l %}
{{ forloop }}
{% if forloop.first %}
<p>{{ foo }}</p>
{% elif forloop.last %}
{% else %}
<p>{{ foo }}</p>
{% endif %}
{% empty %}
<p>档for循环的对象为空的时候走这个!</p>
{% endfor %}

模板语法的取值 只有一种方式 统一采用句点符 (.)

{{ comp_dic.hobby.2.2.age }}

<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()

			之后就可以利用register来自定义过滤器和标签
# 应用名下templatetag文件夹 mytag.py文件
from django.template import Library
register = Library()
# 自定义过滤器,跟默认的过滤器一样,最多只能接受两个参数
@register.filter(name='xxx') # 给过滤器起名字
def index(a,b):
return a+b

使用自定义的过滤器,需要先在html页面上 加载。

<!--test.html文件-->
{% load mytag %}
{{ 1|xxx:99 }}

自定义标签

# 应用名下templatetag文件夹 mytag.py文件

# 自定义标签   可以接受任意多个参数
@register.simple_tag(name='zzz')
def mytag(a,b,c,d):
return '%s?%s?%s?%s'%(a,b,c,d)
<!--test.html文件-->
{% load mytag %}
{% zzz 'a' 'b' 'c' 'd' %}
<!--test.html文件-->
<p>自定义的过滤器可以在逻辑语句使用 而自定义的标签不可以</p>
{% if 1|xxx:99 %}
<p>有值</p>
{% else %}
<p>无值</p>
{% endif %}

自定义inclusion_tag

是一个函数 能够接受外界传入的参数, 然后传递给一个html页面,页面上获取数据 渲染完成之后,将渲染好的页面放到调用inclusion_tag的地方

# 应用名下templatetag文件夹 mytag.py文件
# 自定义inclusion_tag
@register.inclusion_tag('mytag.html',name='xxx')
def index666(n):
l = []
for i in range(n):
l.append('第%s项'%i)
return locals() # 将l直接传递给mytag.html页面
<!--mytag.html文件-->
<!--只做临时渲染的页面,所以该页面的其他框架部分html代码就不需要了-->
<ul>
{% for foo in l %}
<li>{{ foo }}</li>
{% endfor %}
</ul>
<!--test.html文件-->
<p>自定义inclusion_tag的使用 当你需要使用一些页面组件的时候 并且该页面组件需要参数才能够正常渲染 你可以考虑使用inclusion_tag</p>
{% load mytag %}
{% xxx 5 %}

模板的继承

你需要事先在你想要使用的页面上划定区域,之后在继承的时候 ,你就可以使用你划定的区域,也就意味着,如果你不划定任何区域,那么你将无法修改页面内容。

<!--先在页面上利用block划定你以后可能想改的区域-->
{% block content %}
{% endblock %} <!--继承之后 就可以通过名字找到对应的区域进行修改-->
{% extends 'home.html' %} {% block content %}
<!--修改模板中content区域内容-->
{% endblock %}

模板上的block区域越多 页面的扩展性越强
建议你一个模板页面至少有三块区域:
css区域
html代码区域 可以设置多个block
js区域
有了这三块区域 就能够实现每一个页面都有自己独立的css和js代码

{% extends 'home.html' %} 子文件就可以通过这个方法继承猪文件的html代码的格式
{% block css %}
<style>
p {
color: green;
}
</style>
{% endblock %} {% block content %}
<p>login页面</p>
{% endblock %} {% block js %}
<script>
alert('login')
</script>
{% endblock %} 你还可以在子页面上继续沿用父页面的内容
{{ block.super }}

模板的继承

1.先在你想要继承的页面上通过block划定你将来可能要改的区域

2.在子页面上先继承extends

3.利用block自动提示 选择你想要修改的内容区域

模板的导入

将html页面当做模块的直接导入使用
{% include 'bform.html' %}

下一篇:django之模型层

最新文章

  1. Qt - 错误总结 - QObject::connect: Cannot queue arguments of type &#39;PVCI_CAN_OBJ&#39; (Make sure &#39;PVCI_CAN_OBJ&#39; is registered using qRegisterMetaType().)
  2. Java中普通代码块,构造代码块,静态代码块执行顺序
  3. Xamarin.iOS Unified API 注意要点
  4. Eclipse调试时Application XXX is waiting for the debugger to attach的提示
  5. Mac 加密软件
  6. ASP.NET内置对象二
  7. JavaScript高级程序设计(第三版)第五章 引用类型
  8. Linux命令zip和unzip
  9. java中的包装类
  10. 怎样在Word中插入代码并保持代码原始样式不变
  11. ExtJS 饼状图报表
  12. pro-engineer&amp;UG
  13. SDUTOJ 1298 活动选择
  14. Android Drawable绘图学习笔记(转)
  15. 蓝桥杯-凑算式-java
  16. java之servlet小记
  17. 【省带宽、压成本专题】从产品架构来看,PCDN如何节流50%
  18. 20_Android中apk安装器,通过WebView来load进一个页面,Android通知,程序退出自动杀死进程,通过输入包名的方式杀死进程
  19. StringTokenizer 的性能看来真的不用担心
  20. Socket.io各个发送消息的含义【发送对象范围】

热门文章

  1. KVM虚拟迁移(5)
  2. Microsoft Visual Studio 中工具箱不显示DevExpress控件的解决办法
  3. Centos7 安装多版本php 并添加swoole拓展
  4. MSF魔鬼训练营-3.5.3 MSF中常用的关于数据库的命令
  5. 阿里EMR原理
  6. CDH6.2的配置
  7. CSS3鼠标滑过图片3D旋转动画
  8. sql server lower函数
  9. springboot(十六)-swagger2
  10. Maven中setting.xml 配置详解