目录css
路由:视图函数的内存地址html
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是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模块能序列化的)了
咱们以前写过的都是基于函数的view,就叫FBV。还能够把view写成基于类的。
FBV:基于函数的视图
CBV:基于类的视图python
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方法
使用装饰器装饰FBV
FBV自己就是一个函数,因此和给普通的函数加装饰器无差:jquery
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
类中的方法与独立函数不彻底相同,所以不能直接将函数装饰器应用于类中的方法 ,咱们须要先将其转换为方法装饰器。json
Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器bootstrap
#使用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)
注意事项:
# 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>
模板语法也给你提供了一些内置的方法 帮你快速的处理数据
过滤器的语法: {{ 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 %}
模板语法的取值 只有一种方式 统一采用句点符 (.)
<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()
以后就能够利用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 %}
是一个函数 可以接受外界传入的参数, 而后传递给一个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' %}