小白必会三板斧css
HttpResponsehtml
render前端
redirectpython
视图函数必须有一个返回值 而且返回值的数据类型必须是HttpResponse对象django
JsonResponsejson
先后端分离后端
先后端数据交互 该如何进行?浏览器
一般状况下先后端的数据交互采用的都是json的字符串(字典)前端工程师
后端只须要写好相应的url接口 前端访问你这个接口闭包
你只须要返回一个大字典便可+开发文档
用来告诉前端工程师 你这个接口可以返回那些数据
先后端序列化都用哪些方法
python后端 js
json.dumps JSON.stringify
json.loads JSON.parse
def index(request): user_dic = {'name':'jason好帅哦 我好喜欢~','password':'123'} # 如何让json不自动帮你对中文进行转码,把ensure_ascii设置为false,默认的是true # json_str = json.dumps(user_dic,ensure_ascii=False) # return HttpResponse(json_str) # return JsonResponse(user_dic,json_dumps_params={'ensure_ascii':False}) l = [1,2,3,4,5,6,7,] #若是容器类型数据为空的时候 不执行任何语句 # 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') # 路由的书写 与CBV有点不一样 # FBV写法 路由 >>> 视图函数内存地址 url(r'^index/',views.index), # CBV写法 url(r'^login/',views.MyLogin.as_view())
CBV的源码
为何CBV可以根据请求的不一样 自动执行不一样的方法?
访问属性和方法
方法就是函数(函数名加括号执行优先级最高)url(r'^login/',views.MyLogin.as_view()
)
项目一启动 会自动执行as_view
方法
CBV在路由上匹配 其实本质就是FBV 路由 >>>>视图函数内存地址
# CBV写法 url(r'^login/',views.MyLogin.as_view()), # url(r'^login/',views.view) # 访问属性和方法 # 方法就是函数(函数名加括号执行优先级最高) # 项目一启动 会自动执行as_view方法 # views.test和上面登陆的views.view本质上写法是同样的,CBV在路由匹配上 其实本质仍是FBV 路由 >>> 视图函数内存地址 url(r'^test/',views.test), url(r'^index/',views.index),#index在匹配上路由的时候触发 url(r'^login/',views.MyLogin.as_view()),#在浏览器上出入login就会触发 # 若是在urls中设置url(r'',home),会截获全部的url,若是放在文件的下面不截获 #网站首页可使用url(r'^$',home) #访问网站404页面的设计 url(r'',error)
@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 #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加装饰器 推荐使用内置模块 from django.utils.decorators import method_decorator ======2.能够指定给谁装====== #@method_decorator(outter,name='post') #@method_decorator(outter,name='dispatch') class MyLogin(View): @method_decorator(outter) 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基本数据类型所有支持传值
<p> 传函数名{{index}} 给html页面传递函数名的时候 模板语法会自动加括号调用函数 而且将函数的返回值当作展现依据 模板语法不支持函数传参 也就意味着 你传给html页面的只能是不须要传参调用的函数 </p> <p>传类名:{{MyClass}} </p> <p>{{ obj.get_self }}</p> <p>{{ obj.get_cls }}</p> <p>{{ obj.get_func }}</p> <p>只要是可以加括号调用的 传递到html页面上的都会自动的加货号调用</p1> 给html页面传值的两种方式 第一种 指名道姓 当须要传递的变量名特别多的状况下 有点麻烦 return render(request,'test.html',{'n':n}) 第二种 locals() 会将当前所在的名称空间中全部的名字 所有传递给html页面 return render(request,'test.html',locals())
过滤器
语法结构
模板语法也给你提供了一些的内置的方法 帮你快速的提供处理数据的能力
最可能是两个参数
前端的取消转义
|false
后端
from django.utils.safestring import mark_safe
sss2 = "<h2>个人h2标签</h2>"
res = mark_safe(sss2)
<p> 模板语法之过滤器 会自动将|左边的数据当前过滤器的第一个参数 传入 :右边的当作第二个参数</p> {<p>统计长度(若是没法统计默认返回0):{{s|length}}</p>} {<p>加法运算(内部异常捕获 支持数字相加 字符串拼接 都不符合返回空):{{n|add:f}}</p>} {<p>切片操做 顾头不顾尾 也支持步长 :{{l|slice:'0:5:3'}}</p>} {<p>判断是否有值 (有值展现值的自己 没有值展现默认的值):{{ is_value|default:'is_value变量名指向的值为空' }}</p>} {<p>自动转成文件大小的格式:{{file_size |filtesizeformat}}</p>} {<p>截取文件的内容(字符) 截取五个字符 后面的三个点也算:{{ s|truncatechars:8 }}</p>} {<p>截取文本的内容(按照空格计算) 截取五个单词 三个点不算:{{s1|truncatewords:5}}</p>} {<p>默认状况下 是不会自动帮你转换成前端的html标签的 防止恶意攻击</p>} {<p>展现带有标签的文本:{{sss|safe}}</p>} {<p>展现带有标签的文本:{{sss1|safe}}</p>}
标签
逻辑相关的
if
for循环
for if联合使用 {% 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> 当你的数据是经过比较复杂的点点点获取到的后续又须要常用 你能够给该数据起别名 别名只能在with内部使用 {% with comp_dic.hoby.2.2.age as age %} <p>{{age}}</p> <p>{{ comp_dic.hoby.2.2.age}}</p> {% endwith%}
自定义过滤器和标签
django支持用户自定义
必需要先有三步准备
1.在应用名下新建一个名字必须是templatetags文件夹
2.在该文件夹内 新建一个任意名称的py文件
3.在该文件中 必须先写下面的两句代码
from django.template import Library
register = Library()
以后就能够利用register来自定义过滤器和标签
使用自定义的过滤器
须要先在html页面上 加载
自定义过滤器 跟默认的过滤器同样 最多只能接受两个参数
@register.filter(name='baby') def index(a,b) return a+b
自定义标签
自定义的标签能够接受任意多个参数
@register.simple_tag(name='mytag') def mytag(a,b,c,d): return '%s?%s?%s?%s?'%(a,b,c,d)
自定义inclusion_tag
是一个函数 可以接受外界传入的参数 而后传递给一个html页面
页面上获取的数据 渲染 完成以后
将渲染好的页面 放到调用inclusion_tag 的地方
自定义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页面 {#<p>自定义过滤器的使用</p>#} {#{% load mytag %}#} {#{{ 1|baby:1 }}#} {#{{ 1|baby:100 }}#} 自定义标签的使用 能够接受多个参数 参数之间必须空格隔开 {#{% load mytag %}#} {#{% mytag 'a' 'b' 'c' 'd' %}#} {#{% load mytag %}#} 自定义的过滤器能够在逻辑语句使用 而自定义的标签不能够 {#{% if mytag '1' '2' '3' '4' %}#} {# <p>有值</p>#} {# {% else %}#} {# <p>无值</p>#} {#{% endif %}#} 自定义inclusion_tag 的使用 当你须要使用一些页面组件的时候 而且该页面组件须要参数才可以正常渲染 你能够考虑使用inclusion_tag {% load mytag %} {% xxx 5 %} 标签 逻辑相关 索引:'counter0':0 计数:'counter':1 可以判断for循环的开始:'first':True 可以判断for循环的结束:'last':True
模板继承
你须要事先在你想要使用的页面上 划定区域 以后在继承的时候 你就可使用你划定的区域
也就意味着 若是你不划定任何区域 那么你就将没法修改页面上的内容
{% block content %} {% endlock %} 先在页面上利用block划定你之后可能想改的区域 继承以后 就能够经过名字找到对应的区域进行修改 {% extends 'home.html'%} {% block content %} 修改模板中content区域内容 {% endblock %} 模板上的block区域越多 页面的扩展性越高 建议你一个模板页面至少有三块区域 css区域 html代码区域 能够设置多个block js区域 有了这三块区域 就能实现每个页面都有本身独立的css和js代码 {% extends 'home.html' %} {% block css %} <style> p { color: green; } </style> {% endblock %} {% block content %} <p>login页面</p> {% endblock %} {% block js %} <script> alert('login') </script> {% endblock %} 你还能够在子页面上继续沿着父页面的内容 {{ block.super }} 模板的继承 先在你想要继承的页面上经过block划定你将要改动的区域 在子页面上先继承extends 利用block自动提示 选择你想要修改的内容的区域
模板导入
将html页面当作模块的直接导入使用
{% include 'bform.html' %}
静态文件目录路径
STATICFILES_DIRS = [os.path.join(BASE_DIR,'static')]