• 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": "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 %}
    
  • 相关阅读:
    ASP.NET面试题2
    [转]深入.NET DataTable
    C#操作Excel (转)
    XML操作大全
    j2sdk 好用了
    我对“重构(refector)”的看法
    成功执行
    java属性类(Properties类)
    Sharpdevelop下载
    POJ 1753 Flip Game(翻转棋盘+枚举+dfs)
  • 原文地址:https://www.cnblogs.com/zqfzqf/p/11939158.html
Copyright © 2020-2023  润新知