zoukankan      html  css  js  c++  java
  • Django视图层进阶、模板层

    Django视图层进阶、模板层

    一、视图层

    三板斧:

    HttpResponnse、redirect、render视图函数返回都是一个HttpResponse对象

    JasonResponse

    可以试着阅读以下方法的源码(jsonresponse)

    import json
    json.dumps({'username':'你好啊'},ensure_ascii=False)  # 不会转码
    
    from django.http import JsonResponse
    user_dict = {'username':'你好啊'}
    return JsonResponse(user_dict)
    

    参数

    1.json_dumps_params  字典
    JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
    
    2.safe
    该方法默认只用来序列化字典
    l = [1,2,3,4]
    JsonResponse(l,safe=False)
    

    form表单上传文件

    1. 必须做的事

      method必须是post

      enctype必须是formdata

    2. 暂时需要做的事

      提交post请求需要将中间件里面的一个csrfmiddleware注释掉(权限认证)

    后端获取用户上传的文件

    file_obj = request.FILES.get('前端input框name属性值')
    file_obj.name  # 文件名
    for line in file_obj:
        print(line)
    
    # django中推荐以下写法
    for chunk in file_obj.chunks():
        print(chunk)
    

    render简单实现原理

    def ab_render(request):
        temp = Template("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>")
        user_dict = Context({'user_dict':{'username':'jason','password':123}})
        res = temp.render(user_dict)
        return HttpResponse(res)
    

    视图函数并不一定是函数,也可以是类

    FBV:基于函数的视图

    CBV:基于类的视图

    CBV基本写法

    from django.views import view
    
    class MyLogin(view):
        def get(self,request):
            return render(request,'login.html')
        def post(self,request):
            return HttpResponse('我是类里面的post方法')
    url(r'^login/',views.MyLogin.as_view())
    
    朝login提交get请求会自动执行MyLogin里面的get方法
    而提交post请求也会自动执行MyLogin里面的post方法
    为什么MyLogin针对不同的请求方法能够自动执行对应的方法
    

    CBV源码

    url(r'^login/',views.MyLogin.as_view())
    

    猜想
    as_view要么是类里面定义的普通函数 @staticmethod
    要么是类里面定义的绑定给类的方法 @classmethod
    看源码发现是绑定给类的方法(看源码不需要每一句都看懂 只看自己能够看得懂)

    二、模板层

    {{}}	变量相关
    {%%}	逻辑相关
    

    模板语法传值

    python基本数据类型全部支持传递给HTML文件

    类:

    1. 函数和对象会自动加括号
    2. 模板语法不支持传参

    对象:

    后端给HTML文件传递数据的两种方式

    1. 指名道姓

      return render(request,'index.html',{'n':n,'f':f})
      
    2. locals() #会将当前名称空间所有的变量名全部传递给HTML页面

      return render(request,'index.html',locals())
      

    html页面上,获取到后端传递过来的数据

    {{ 变量名 }}
    

    取值:

    django模板语法取值,只有一种方式—句点符。

    点索引、点键

    <p>{{ l.2 }}</p>
    <p>{{ d.username }}</p>
    <p>{{ d.password }}</p>
    <p>{{ d.hobby.1.username.1 }}</p>
    

    过滤器

    |length
    |add
    |default
    |truncatechars
    |truncatewords
    |filesizeformat
    |slice
    |date
    |safe
    
    #验证之前先定义好|左边的变量
    <p>过滤器  |左边的会当做过滤器的第一个参数 过滤器名右边的会当做过滤器的第二个参数</p>
    1. <p>求数据长度:{{ s|length }}</p>
    2. <p>加法运算:{{ n|add:10 }}{{ s|add:13132 }}{{ s|add:'DSB' }}</p>
    3. <p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}{{ ff|default:'这个ff布尔值是Flase' }}</p>
    4. <p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}</p>
    5. <p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}{{ sss|truncatewords:4 }}</p>
    6. <p>文件大小:{{ file_size|filesizeformat }}</p>
    7. <p>切片操作:{{ s|slice:'0:2' }}{{ s|slice:"0:8:2" }}</p>
    8. <p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}</p>
    9. <p>转义:{{ res|safe }}{{ res1 }}、后端直接标识安全:{{ res2 }}</p>
    

    前后端取消转义

    前端:

    |safe
    

    后端:

    取消转义模块,告诉前端界面字符串内的标签正常显示在页面上,否则就是一串普通字符。

    from django.utils.safestring import mark_safe
    mark_safe('<h1>安全滴</h1>')
    

    总结:前端代码不一定非要在前端页面写,可以在后端写好后传递给前端页面使用,这样的话,你就可以利用到后端更加多的逻辑语法。

    模板语法之标签(逻辑相关)

    {% for foo in l %}  <!--l = [1,2,3,4,5,6]-->
    		{% if forloop.first %}
    			<p>这是我的第一次</p>
    		{% elif forloop.last %}
    			<p>这是最后一次了啊~</p>
    		{% else %}
    			<p>{{ foo }}</p>
    		{% endif %}
    		{% empty %}
            <p>for循环的对象内部没有值</p>
    {% endfor %}
    
    #first代表第一个,last代表最后一个执行结果为:
    这是我的第一次
    2
    3
    4
    5
    这是最后一次了啊~
    

    自定义过滤器及标签 inclusion_tag

    先完成一下前期准备工作

    1. 在应用名下新建一个名字必须叫templatetags文件夹

    2. 在该文件夹内新建一个任意名称的py文件(eg:mytag)

    3. 在该文件内,必须先写以下两句代码

      from django.template import Library
      
      register = Library()
      

    自定义过滤器

    @register.filter(name='my_sum')
    def index(a,b):
        return a + b
    
    <p>自定义过滤器的使用</p>
    {% load mytag %}
    <p>{{ 10|my_sum:90 }}</p>
    
    <p>自定义的过滤器可以在逻辑语句中而自定义的标签不可以</p>
    {% if 10|my_sum:100 %}
    <p>条件成立</p>
    {% endif %}
    

    自定义标签

    @register.simple_tag(name='my_baby')
    def xxx(a,b,c,d):
        return '%s?%s?%s?%s'%(a,b,c,d)
    
    <p>自定义标签的使用</p>
    {% load mytag %}
    <p>{% my_baby 1 2 3 'hello world' %}</p>
    
    {% if my_baby 1 2 3 4 %}
    <p>条件成立</p>
    {% endif %}
    

    自定义inclusion_tag

    @register.inclusion_tag('demo.html',name='myin')
    def index1(n):
        l = []
        for i in range(n):
            l.append(i)
            # 将列表传递给demo.html
            # return locals()
            return {'l':l}
        
    <p>自定义inclusion_tag的使用</p>
    {% load mytag %}
    {% myin 5 %}
    

    使用 总结 页面上使用他们 统一先导入

    {% load mytag %}
    

    模板的继承

    某一个页面大部分区域是公用的,那这个页面就可以作为模板页面,当别人继承这个页面之后,如何修改对应的区域

    先在模板页面上通过block实现划定区域

    {% block content %}
    模板页面内容
    {% endblock %}
    

    子页面中先导入整个模板

    {% extends '模板页面.html'%}
    修改特定的区域  通过实现划定好的区域名称
    {% block content %}
    子页面内容
    {% endblock %}
    

    通常情况下,模板页面应该起码有三块区域

    {% block css %}
    模板页面内容
    {% endblock %}
    
    {% block content %}
    模板页面内容
    {% endblock %}
    
    {% block js %}
    模板页面内容
    {% endblock %}
    

    模板的block块越多,可扩展性越高,还支持子页面调用父页面对应区域的内容,并且可以无限次调用。

    {{ block.super }}
    

    模板的导入

    将HTML页面当作模块使用,哪里需要就导哪里,这个HTML页面通常都不是完整的,只是一个局部样式

    {% include 'left.html' %}
    

    基于django settings源码实现项目配置文件的,插拔设计

    我把月亮戳到天上 天就是我的 我把脚踩入地里 地就是我的 我亲吻你 你就是我的
  • 相关阅读:
    使用watch定时执行命令并显示结果
    LVS配置
    myeclipse通过查询源码查询方法
    导入struts2框架项目无法运行tomcat
    解决eclipse/myeclipse导入项目时出现红色叹号的方法
    my/eclipse中的debug调试
    导入项目后servlet报错
    转到Servlet出现500型错误
    关于快捷键导包失败
    关于jsp找不到servlet
  • 原文地址:https://www.cnblogs.com/zhulipeng-1998/p/12863880.html
Copyright © 2011-2022 走看看