• Django-视图层


    视图层

    视图层之 HttpResponse 对象

    响应对象主要由三种形式

    HttpResponse()
    redirect()
    render()
    

    小白必备三板斧
    HttpResponse # 返回字符串

    ​ redirect # 返回

    ​ render # 返回 html 文件

    ​ render() 不仅可以返回 html 文件,还可以给模板传值,通过字典给该页面传递数据,并返回一个渲染后的HttpResponse对象

    from django.template import Template, Context
    
    def index(request):
        res = Template("<h1> {{ user}} </h1>")  # 参数表示要渲染的模板样式及对象
        con = Context({"user": {'username': 'jason','password': 123}}) # 被渲染对象具体对应的内容
        ret = res.render(con)
        print(ret)
        return HttpResponse(ret)  #{'username': 'jason', 'password': 123}
    

    1. JsonResponse

      返回 json格式数据

    为什么要给前端返回 json格式字符串:前后端分离,就是基于 json格式传输数据,后端就专门写接口,前端调用你这个接口,就能拿到一个 json 格式的字符串,然后利用序列化反序列化转换成前端对应的数据类型

    ​ js 常用数据类型:
    ​ 数值类型
    ​ 字符类型
    ​ 数组 []

    ​ 自定义对象 {}
    ​ undefined 与 null
    ​ 布尔值 true, false
    ​ symbol 标志

    前端的 json

    JSON.stringify()  序列化 >>> json.dumps
    JSON.parse()   反序列化 >>> json.loads
    

    python后端的 json

    json.dumps
    json.loads
    
    import json
    from django.http import JsonResponse
    
    def index(request):
        user = {'username': 'jason你很帅', 'pwd': 123}
        # 1.HttpResponse,使用json转换数据格式
        json_str = json.dumps(user, ensure_ascii=False) # 取消中文转换,默认为True
        # return HttpResponse(json_str) #{"username": "jason", "pwd": 123}
    
        # 2.使用JsonResponse转换数据格式
        return JsonResponse(user, json_dumps_params={'ensure_ascii': False}) # 取消中文转换
    
        # l = [1,2,3,4,5,6]
        # return JsonResponse(l, safe=False) #对非字典类型,需要修改 safe参数为 False
    

    总结:HttpResponse序列化数据 需要导入 json模块, 而 JsonResponse可直接对字典类型数据进行序列化操作,对于非字典类型数据需要修改 安全参数 safe=False 后才能转换,而且也是返回给页面,

    form 表单上传文件
    注意事项

    1. 提交方式必须是post
    
    1. enctype参数必须由默认的 urlencode 变成 formdata,修改后才能上传文件
    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="myfile">
        <input type="text" name="password">
        <input type="submit" value="提交">
    </form>
    
    def up(request):
        if request.method == 'POST':
            file_obj = request.FILES.get('myfile')
            print(file_obj.name) #考试内容.txt
            with open(file_obj.name, 'wb') as f:
                # for line in file_obj: # file_obj你可以之前看成文件句柄f
                for chunk in file_obj.chunks():
                    f.write(chunk)
        return render(request, 'up.html')
    

    注意:form表单上传文件,后端需要在 request.FILES 中获取文件数据,而不再是 POST里面

    FBV(Function Based View)基于函数的视图,面向函数式编程

    ​ CBV(Class Based View) 基于类的视图,面向对象式编程

    基于 CBV 的视图(get请求来就会走类里面的 get方法,post请求来就走类里面的 post方法)

    ​ 需要注意的几点设置:

    1. urls.py
    
    url(r'^login/', views.MyLogin.as_view())
    
    1. views.py(get请求就走get方法,post请求就走post方法)
    # CBV 基于类的视图
    from django.views import View
    
    class MyReg(View):
        def get(self, request):
            return render(request, 'reg.html')
    
        def post(self, request):
            return HttpResponse('我是MyReg类中的post方法')
    
    
    

    模板层

    模板层就是 html 页面,Django系统中的(template)

    html 内 接收 views.py 内函数传入的变量, 用 {{ }}接收

    模板传值

    方式一:通过键值对的形式传参,指名道姓的传参

    n = 123
    m = [1,2,3]
    return render(request, 'login.html', {'n':n, 'm': m}) # 前面的n是参数名, 后面n才是具体的值
    

    方式二:使用 locals()传全部的值

    def login(request):
        n = 123
        f = 12.3
        s = '你妹的'
        l = [1,2,3,4,5]
        d = {'name': 'jason', 'pwd': 123}
        t =(1,2,3,4,5,)
        se = {1,2,3,4,5}
        b = True
        
        def func():
            return '你妹的'
        
        class MyClass(object):
            @classmethod
            def get_cls(cls):
                return 'cls'
        obj = MyClass()
        return render(request, 'login.html', locals())
    
    <body>
    <p>{{ n }}</p>
    <p>{{ f }}</p>
    <p>{{ s }}</p>
    <p>{{ l }}</p>
    <p>{{ d }}</p>
    <p>{{ t }}</p>
    <p>{{ se }}</p>
    <p>{{ b }}</p>
    <p>
        {{
        obj.get_cls
        }}
        </p>
    </body>
    

    ​ 注意事项:
    ​ 1.传函数给前端的时候,只要再模板层写函数名{{login}},传函数名会自动加()调用用函数,将函数的返回值展示在 html 页面上
    ​ 2.django 模板语法不支持函数传参
    ​ 3.django 模板语法在获取容器类型内部元素的值的时候,统一只采用 句点符(.),就是只能通过 ‘点取值’
    ​ 4.对象也可以传递:{{ 0bj.方法名 }}

    模板层的变量

    模板语法:分为两大类

    {{变量名}} 变量相关
    {{% %}}   逻辑相关
    
    <p>字符串:{{ name }}</p>   # 相当于print(name)
    <p>数字:{{ age }}</p>   # 相当于print(age)
    <p>列表:{{ ll }}</p>  # 相当于print(ll)
    <p>元祖:{{ tu }}</p>  # 相当于print(tu)
    <p>字典:{{ dic }}</p>   # 相当于print(dic)
    {#只写函数名:相当于函数名(),执行该函数#}
    <p>函数:{{ test }}</p>     # 相当于print(test())  前端展示函数调用的返回值
    {#对象内存地址#}
    <p>对象:{{ lxx }}</p>    # 相当于print(lxx)
    <p>列表套对象:{{ person_list }}</p>
    <p>字典套对象:{{ person_dic }}</p>
    

    模板查询,统一使用句点符 ‘.‘

    <p>列表第0个值:{{ ll.0 }}</p>
    <p>列表第3个值:{{ ll.3 }}</p>
    <p>字典取值:{{ dic.name }}</p>
    <p>字典取列表值:{{ dic.ll }}</p>
    {#再继续取值,继续点#}
    <p>对象取数据属性:{{ lxx.name }}</p>
    <p>对象取绑定给对象的函数属性:{{ lxx.get_name }}</p>
    <p>对象取绑定给类的函数属性:{{ lxx.cls_test }}</p>
    <p>对象取静态方法:{{ lxx.static_test }}</p>
    <p>把对象列表中egon年龄取出来:{{ person_list.1.age }}</p>
    {#拓展:不能调有参数的方法#}
    <p>字符串的方法:{{ name.upper }}</p>
    

    过滤器 (|) :类似于小的方法

    过滤器是对 后端 传到 html页面前端的变量进行处理操作,是在 html文件中处理

    过滤器的语法:{{ value|filter_name:参数}}

    使用管道符 '|' 来应用过滤器

    {{需要过滤的数据|过滤器的名字:过滤参数}}
    

    常用的过滤器

    1. default 如果一个变量是 false或者为空,使用给定的默认值。否则,使用变量的值
    <p>
        {{value|default:'123'}}
    </p>
    

    2.length 返回值的长度,作用于统计字符串和列表的长度

    {{value|length}}
    

    3.filesizeformat 将值格式化为一个可读的文件尺寸(例如'13kb','4.1MB',等等)

    {{ value|filesizeformat }}
    

    如果 value 是 123456789,输出将会是 117.7 MB

    4.slice 切片

    {{value|slice:'2:-1'}}  前闭后开区间支持设置步长{{name|slice:'0:3:3'}}
    

    5.date 时间格式化

    from datetime import datetime
    ctime = datetime.now()
    {{ ctime|date:"Y-m-d H:i:s"}}
    

    6.safe 取消转义

    前端取消转义可以用 |safe (正常显示出html,js标签样式)

    视图层    
    xxx='<h1>波波棋牌室</h1>'
    
    模板层
    {{xxx|safe}}   #取消转义h1标签就会起作用
    

    后端取消转义

    from django.utils.safestring import make_safe
    zzz = make_safe(''<h1>啊啊啊啊</h1>')
                    
    模板层,直接写
    {{zzz}}
    

    7.truncatechars 按照指定字符截取内容,截断的字符串以省略号(...)结尾(省略号算3个字符数量)

    参数:指定截断的字符数

    {{ info|truncatechars:6 }}
    

    8.truncatewords 按空格截取(数字显示的是截取的空格数,三个点不包含)

    {{ info|truncatewords:3 }}
    

    9.cut 移除value中所有的与给出的变量相同的字符串

    {{ value|cut:' ' }}  #移除 ' '
    

    如果value为'i love you',那么将输出'iloveyou'.

    9.add 拼接(数字就相加,字符串就是拼接)

    {{ n|add:100 }}
    {{ s|add:'hahah 翻车啦' }}
    

    其他过滤器

    过滤器 描述 示例
    upper 以大写方式输出 {{ user.name | upper }}
    add 给value加上一个数值 {{ user.age | add:”5” }}
    addslashes 单引号加上转义号
    capfirst 第一个字母大写 {{ ‘good’| capfirst }} 返回”Good”
    center 输出指定长度的字符串,把变量居中 {{ “abcd”| center:”50” }}
    cut 删除指定字符串 {{ “You are not a Englishman” | cut:”not” }}
    date 格式化日期
    default 如果值不存在,则使用默认值代替 {{ value | default:”(N/A)” }}
    default_if_none 如果值为None, 则使用默认值代替
    dictsort 按某字段排序,变量必须是一个dictionary {% for moment in moments | dictsort:”id” %}
    dictsortreversed 按某字段倒序排序,变量必须是dictionary
    divisibleby 判断是否可以被数字整除 `{{ 224
    escape 按HTML转义,比如将”<”转换为”&lt”
    filesizeformat 增加数字的可读性,转换结果为13KB,89MB,3Bytes等 `{{ 1024
    first 返回列表的第1个元素,变量必须是一个列表
    floatformat 转换为指定精度的小数,默认保留1位小数 {{ 3.1415926 | floatformat:3 }} 返回 3.142 四舍五入
    get_digit 从个位数开始截取指定位置的数字 {{ 123456 | get_digit:’1’}}
    join 用指定分隔符连接列表 {{ [‘abc’,’45’] | join:’’ }} 返回 abc45
    length 返回列表中元素的个数或字符串长度
    length_is 检查列表,字符串长度是否符合指定的值 {{ ‘hello’| length_is:’3’ }}
    linebreaks 用或 标签包裹变量 {{ “Hi David”|linebreaks }} 返回HiDavid
    linebreaksbr 用 标签代替换行符
    linenumbers 为变量中的每一行加上行号
    ljust 输出指定长度的字符串,变量左对齐 {{‘ab’|ljust:5}}返回 ‘ab ’
    lower 字符串变小写
    make_list 将字符串转换为列表
    pluralize 根据数字确定是否输出英文复数符号
    random 返回列表的随机一项
    removetags 删除字符串中指定的HTML标记 {{value | removetags: “h1 h2”}}
    rjust 输出指定长度的字符串,变量右对齐
    slice 切片操作, 返回列表 {{[3,9,1] | slice:’:2’}} 返回 [3,9] `{{ 'asdikfjhihgie'
    slugify 在字符串中留下减号和下划线,其它符号删除,空格用减号替换 `{{ '5-2=3and5 2=3'
    stringformat 字符串格式化,语法同python
    time 返回日期的时间部分
    timesince 以“到现在为止过了多长时间”显示时间变量 结果可能为 45days, 3 hours
    timeuntil 以“从现在开始到时间变量”还有多长时间显示时间变量
    title 每个单词首字母大写
    truncatewords 将字符串转换为省略表达方式 `{{ 'This is a pen'
    truncatewords_html 同上,但保留其中的HTML标签 `{{ 'This is a pen'
    urlencode 将字符串中的特殊字符转换为url兼容表达方式 {{ ‘http://www.aaa.com/foo?a=b&b=c’ | urlencode}}
    urlize 将变量字符串中的url由纯文本变为链接
    wordcount 返回变量字符串中的单词数
    yesno 将布尔变量转换为字符串yes, no 或maybe `{{ True

    特点:会将 | 左边的当做过滤器的第一个参数, |右边的当做第二个参数

    ​ 在 Django的模板语法中,通过过滤器来改变变量在页面的显示

    ​ 前端代码并不一定非要写在前端,也可以在后端写好,传递给前端页面

    ​ 前后端取消转义
    ​ 前端: |safe

    ​ 后端:from django.utils.safestring import make_safe

    标签

    基本用法:遍历每个元素

    for循环标签

    视图层:
    def test(request):
        l=[1,2,3,4,5]
        return render(request,'login.html',locals())
    
    模板层:
    {% for foo in l %}
      {{ foo }}  # 1,2,3,4,5
    {% endfor %}
    
    
    forloop对象,打印forloop可以得到所有循环后的各种信息值
    % for foo in l %}
        {{forloop  }}
    {% endfor %}
    
    % for foo in l %}
        {% if forloop.first %}
            <p>这是我的第一次</p>
        {% elif forloop.last %}
            <p>这是最后一次了啊</p>
        {% else %}
            <p>嗨起来 大宝贝~</p>
        {% endif %}
    {% endfor %}
    
    
    for...empty
    for标签带有一个可选的{% empty %}从句,在给出的循环对象是空或者没有被找到时执行
    % for foo in l %}
        <p>{{ forloop.counter }}:{{ foo }} </p>  # 给循环的值编号
        {% empty %}  # 在对象为空或者找不到时被执行
        <p>对象为空,不能循环</p>
    {% endfor %}
    
    

    If 标签

    if/elif/else

    {% if user_list %}
      用户人数:{{ user_list|length }}
    {% elif black_list %}
      黑名单数:{{ black_list|length }}
    {% else %}
      没有用户
    {% endif %}
    
    {% if user_list|length > 5 %}
      七座豪华SUV
    {% else %}
        黄包车
    {% endif %}
    

    for循环和判断一起使用

    {% for foo in l %}
      {% if forloop.first %}
        这是第一次
        {% elif forloop.last %}
          这是最后一次
        {% else %}
        来啊来啊
      {% endif %}
    {% endfor %}
    

    自定义 过滤器

    ​ 步骤:
    ​ 1.在应用名下面新建一个templatetags 文件夹(必须交这个名字)
    ​ 2.在该文件夹下 创建一个任意名称的 py文件
    ​ 3.在该 py 文件内固定先写两行代码

    from django.template import Library
    
    register = Library()
    
    1. 写一个函数,用@register.filter(name='yyy')装饰一下(可以指定别名)
    @register.filter(name='yyy')
    def str_add(x,y):
        return x+y
    
    在模板里:(新定定义的标签,过滤器,都要重启程序)
        {% load mytag %}
        {{'lqz'|str_add:'nb'}}
    

    自定义标签

    1.在应用名下面新建一个templatetags 文件夹(必须交这个名字)
    2.在该文件夹下 创建一个任意名称的 py文件
    3.在该 py 文件内固定先写两行代码

    from django.template import Library
    
    register = Library()
    

    写一个函数,用@register.simple_tag()装饰(可以指定别名)

    @register.simple_tag()
    def add_nb(value):
        return value+'nb'
    
    模板中:(多个参数,以空格区分)
    {% load mytag %}
    {% add_nb 'lqz'%}
    

    模板的继承

    当多个页面整体的样式都大差不差的情况下,可以设置一个模板文件,在该母板文件中,使用block块划分多个预期,相当于用block占位,之后子版在使用模板的时候,可以通过block的名字,来区分需要修改哪一部分区域。

    模板一般情况下,应该至少有三个被修改的区域:css,子页面的html代码,js

    1.使用模板的继承

    写一个母版,需要留一个或多个可以扩展的区域。母版中主要是使用空的block完成页面的搭建

    {%block 名字 %}
      可以修改的内容
    {%endblock%}
    
    母版页面
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="x-ua-compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>Title</title>
      {% block css %}   #母版的css 内容
      
      {% endblock %}
    </head>
    <body>
    
    <h1>这是母板的标题</h1>
    
    {% block content %}  #母版的content内容
    
    {% endblock %}
    <h1>母板底部内容</h1>
    {% block js %}      #母版js内容
    
    {% endblock %}
    </body>
    </html>
    

    在子模板中使用,子模板主要内容是填空母版中空的block

    # extends 告诉模板引擎,这个模板继承了另一个模板
    {% extends "base.html" %}
    
    {% block 名字 %}
        子模板的内容
    {% endblock 名字 %}
    
    {% extends 'home.html' %}
    {% block css %}
        <style>
            h1 {
                color: red;
            }
        </style>
    {% endblock %}
    
    {% block content %}
    
        {% include 'beautiful.html' %}
    <h1>登陆页面</h1>
        <form action="">
            <p>username:<input type="text" class="form-control"></p>
            <p>password:<input type="text" class="form-control"></p>
            <input type="submit" class="btn btn-danger">
        </form>
    {% endblock %}
    
    {% block js %}
    
    {% endblock %}
    

    强调(注意点)

    • 如果母版的block中写了内容,子模板页面没有重写,那么就会使用母版的内容,所以我们在设置母版的block时,一般都是设置空内容。
    • 一旦子模板页面重写了母版的block,往里面写值了,那么就会覆盖掉母版中block的内容
    • 不能在一个模板中定义多个相同的block标签

    模板的导入

    要反复的使用一个组件,可以将该组件写在一个文件中,在使用的时候导入就可以,在模板中使用

    语法

    {% include '模板名字' %}
    {% include 'beautiful.html' %}
    
  • 相关阅读:
    你不是真正的快乐
    春天里
    一生有你
    故乡
    第一天
    直来直往
    恋恋风尘
    烦恼歌
    because of you
    从头再来
  • 原文地址:https://www.cnblogs.com/chmily/p/11738804.html
Copyright © 2020-2023  润新知