day52 django 视图层 模板层

视图层

小白必备三板斧

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": "jason\u597d\u5e05", "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": "jason\u597d\u5e05", "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 %}

猜你喜欢

转载自www.cnblogs.com/zqfzqf/p/11939158.html