• 视图层,模板层


    一、视图层(view)

    视图函数,本质上就是一个python函数,他接受web请求并返回响应。响应内容可以是HTML网页、重定向、404错误等任何东西,但本质都是返回一个HttpResponse对象。视图函数约定俗成写在view.py文件内

    二、请求对象-HttpRequest

    request对象 部分常用属性

    当一个页面被请求时, django将请求报文中的请求行、首部信息、内容主题封装成HttpRequest类中的属性 。
    Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。

    1. request.method           #方式,返回的是纯大写的字符串。
    
    2. request.GET              #获取用户提交的get请求数据,返回的是列表套对象。
    3. request.GET.get()        #获取列表中的最后一个
    4. request.GET.getlist()    #获取列表类型的数据
    
    5. request.POST             #获取用户提交的post请求数据
    6. request.POST.get()       #获取列表中的最后一个
    7. request.POST.getlist()   #获取列表类型的数据
    
    8. request.FILES            #包含所有的上传文件信息。
    

    注意:FILES 只有在请求的方法为POST 且提交的from表单带有enctype="multipart/form-data"的情况下才会包含数据。否则,FILES 将为一个空的类似于字典的对象。

    三、响应对象-HttpResponse

    响应形式多种多样,可以是HTML网页、重定向、404错误等任何东西,但本质都是返回一个HttpResponse对象。具体的说响应对象主要有三种形式:HttpResponse、render、redirect

    3-1. HttpResponse()

    HttpResponse()括号内直接跟一个具体的字符串作为响应体。 即返回字符串

    3-2. render()

    render(request,template_name,[context])
    

    参数:

    • request:用于生成响应的请求对象。
    • template_name:要使用的模板名称。
    • context:添加到模板上下文的一个字典。默认空字典,如果字典中某个值是可调用的,视图将在渲染模板前调用它。

    render方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面作为响应体。

    3-3. redirect()

    传递要重定向的一个硬编码的URL,即本地的URL文件

    def my_view(request):
        ...
        return redirect('some/url')
    

    也可以是一个完整的URL:

    def my_view(request):
        ...
        return redirect('http://www.baidu.com')
    

    四、JsonResponse

    向前端返回一个json格式字符串的两种方式

    # 第一种方式
    import json
    def my_view(request):
        data=['xxx','yyy']
        return HttpResponse(json.dumps(data))
    
    # 第二种方式
    from django.http import JsonResponse
    def my_view(request):
        data = ['xxx', 'yyy']
        return JsonResponse(data1,safe=False)
    # 默认safe=True代表 只能序列化字典,safe=False代表可以序列化其他数据类型
    

    五、FBV与CBV

    FBV基于函数的视图(Function base view)

    CBV是基于类的视图(Class base view)

    # FBV
    # FBV视图层书写方式
    def login(request):
        print('我是login函数')
        return render(request,'login.html')
    
    
    # FBV路由层的书写
    url(r'^index/',views.index),
    
    
    
    # CBV
    # 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路由层的书写
    url(r'^login/',views.MyLogin.as_view())
    

    六、 给CBV加装饰器

    # 第一种方法:直接书写
    class MyLogin(View):
        @outter  # 1.直接写
        def get(self,request):
            print('我是MyLogin里面的get方法')
            return render(request,'login.html')
        @outter  # 1.直接写
        def post(self,request):
            print('我是MyLogin里面的post方法')
            time.sleep(1)
            return HttpResponse('post')
    
    
    # 第二种使用内置函数,推荐方法
    from django.utils.decorators import method_decorator
    
    # 1-1. 内置函数也可以在外面写,并且可以指定给谁装
    @method_decorator(outter,name='post')
    class MyLogin(View):
        @method_decorator(outter)  # 1-2. 推荐写法
        def get(self,request):
            print('我是MyLogin里面的get方法')
            return render(request,'login.html')
    
        def post(self,request):
            print('我是MyLogin里面的post方法')
            time.sleep(1)
            return HttpResponse('post')
    
    
    # 第三种内置函数联合重写dispatch方法
    
    from django.utils.decorators import method_decorator
    
    class MyLogin(View):
        @method_decorator(outter)
        def dispatch(self, request, *args, **kwargs):  
            # 如果你想在视图函数执行之前 做一些操作 你可以在你的CBV中定义dispatch方法来拦截
            return super().dispatch(request,*args,**kwargs)
      
        def get(self,request):
            print('我是MyLogin里面的get方法')
            return render(request,'login.html')
        def post(self,request):
            print('我是MyLogin里面的post方法')
            time.sleep(1)
            return HttpResponse('post')
    

    ----------------------------------------------------------

    一、模板层(template)

    存放在template文件夹下的html文件称之为模板文件,利用模板语法可以在html中展示动态数据,简单来说Django的模板=HTML代码+模板语法

    二、模板语法之注释

    {# this won't be rendered #}  单行注释
    
    注释多行使用comment标签
    

    三、模板语法之变量

    在django模板中遍历复杂数据结构的关键是句点字符,语法:{{ 变量名 }}。变量类似于python中的变量。

    变量的命名包括任何字母数字以及下划线("_")的组合。点(".")也有可能会在变量名中出现,不过它有特殊的含义。注意:最重要的是,变量名称中不能有空格或标点符号。

    views.py:

    name='abc'
    age=18
    li=[1,2,'3','4']
    dic={'name':'abc','age':18,''li:[1,2,4]}
    def test():   #函数
        print('abc')
        return 'abchahahah'
    class Person():
        def __init__(self,name,age)
            self.name=name
            self.age=age
        def get_name(self):
            return self.name
        @classmethod
        def cls_test(cls):
            return 'cls'
        @staticmethod
        def static_test():
            return 'static'
        ---------
        # 模板里不支持带参数
        def get_name_cs(self,ttt):
            return self.name
        ----------
        
    xxx=Person('xxx',18)
    yyy=Person('yyy',28)
    person_list=[xxx,yyy]
    

    html:

    相当于print了该变量

    <p>字符串:{{ name }}</p>
    <p>数字:{{ age }}</p>
    <p>列表:{{ li }}</p>
    <p>元祖:{{ tu }}</p>
    <p>字典:{{ dic }}</p>
    <p>函数:{{ test }}</p>  {#只写函数名:相当于函数名(),返回函数执行结果#}
    <p>对象:{{ xxx }}</p>   {#对象内存地址#}
    

    深度查询:

    <p>列表第1个值:{{ ll.0 }}</p>
    <p>列表第4个值:{{ ll.3 }}</p>
    <p>字典取值:{{ dic.name }}</p>
    <p>字典取列表值:{{ dic.li }}</p>
    <p>对象取数据属性:{{ xxx.name }}</p>
    <p>对象取绑定给对象的函数属性:{{ xxx.get_name }}</p>
    <p>对象取绑定给类的函数属性:{{ xxx.cls_test }}</p>
    <p>对象取静态方法:{{ xxx.static_test }}</p>
    

    四、模板语法之标签

    一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 语法为{% tagname %}

    模板语法的取值 只有一种方式 统一采用句点符 (.)

    4-1. for循环

    # 遍历每一个元素
    {% for person in person_list %}
        <p>{{ person }}</p>
    {% end for%}
    
    
    # 遍历一个字典:
    {% for k,v in dic.items %}
        <p>{{ k }}:{{ v }}</p>
    

    下面是Django为for标签内置的一些属性,可以当作变量一样使用{{ }}在模版中使用。

    • forloop.counter:循环的当前索引值,从1开始计数;常用于生成一个表格或者列表的序号
    • forloop.counter0:循环的当前索引值,从0开始计数;
    • forloop.revcounter: 循环结束的次数(从1开始)
    • forloop.revcounter0 循环结束的次数(从0开始)
    • forloop.first:判断当前是否循环的第一次,是的话,该变量的值为True。我们经常要为第一行加点特殊的对待,就用得上这个判断了,结合if。
    • forloop.last:如果这是最后一次循环,则为真
    • forloop.parentloop:对于嵌套循环,返回父循环所在的循环次数

    4-2. for...empty

    for标签带有一个可选的{% empty %}从句,在给出的组是空的或者没有被找到时执行的操作

    注:循环的对象是空,才会走到empty,而不是对象里面的东西为空

    {% for person in person_list %}
        <p>{{ person.name }}</p>
        {% empty %}
        <p>sorry,no person here</p>
    {% endfor %}
    

    4-3. if判断

    {% if %}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。

    {% if num > 100 or num < 0 %}
        <p>无效</p>
    {% elif num > 80 and num < 100 %}
        <p>优秀</p>
    {% else %}
        <p>良好</p>
    {% endif %}
    

    注:在if标签中使用括号是错误的语法,这点不同于Pythonif语句支持 ,优先级可以使用if嵌套。if支持and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。

    4-4. 标签实例

    # 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 %}
            
        
    # 模板语法的取值 只有一种方式  统一采用句点符  (.)
    comp_dic = {'username':'jason','hobby':['read','study',['run','rap',{'age':18}]]}
    # 获取字典嵌套中的age
    <p>{{ comp_dic.hobby.2.2.age }}</p>
    

    五、模板语法之过滤器

    在Django的模板语言中,通过使用过滤器来改变变量的显示。过滤器的语法: {{ value|filter_name:参数 }}

    注意事项

    1. 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
    2. 过滤器可以接受参数,只能接受一个参数
    3. 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:', ' }}
    4. '|'左右没有空格

    常用过滤器

    1. default

    <!-- 如果变量是false或者为空,则使用给定的默认值。-->
    {{ value|default:'nothing'}}
    

    2. length

    <!-- 返回值的长度,对字符串和列表都起作用-->
    value=[1,2,3,4]  
    {{ value|length}}   输出是4
    

    3. filesizeformat

    <!-- 将值格式化成'人类可读的'文件尺寸。-->
    {{1024|filesizeformat}}  输出为1kb
    

    4. safe

    <!-- Django模板为了安全默认会对HTML标签和js等语法标签进行转义,有时候我们不希望这些元素被转义,可以通过设置过滤器。-->
    script="'<script>alert(111)</script>"
    {{ script|safe }}
    
    
    
    # 补充:后端也可以利用模块取消转义
    from django.utils.safestring import mark_safe
    sss2 = "<h2>我的h2标签</h2>"
    res = mark_safe(sss2)
    

    5.slice

    <!-- 切片,不支持负数 -->
    {{ name|slice:'0:3:3' }}
    

    6.truncatechars

    <!-- 如果字符串多余指定字符数量,多余会被截断,替换成("...")结尾。 -->
    {{ value|truncatechars:9}}
    

    7.truncatewords

    <!-- 在一定数量的字后截断字符串。-->
    {{ value|truncatewords:9}}
    

    六、自定义标签和过滤器

    6-1. 自定义前置准备

    1. 在应用名(app文件夹)下新建一个templatetags包(名字固定),与views.py、models.py等文件在同一目录

    2. 在该文件夹内 新建一个任意名称的.py文件, 如:my_tags.py

    3. 在该.py文件中 必须先写下面两句代码

      from django.template import Library
      register = Library()
      

    6-2. 自定义过滤器

    自定义过滤器实际就是一个带有一个或两个参数的python函数

    注:函数的第一个参数是要过滤的对象,第二个是自定义参数,函数一共只能有两个参数。

    • 变量的值:不一定是字符串形式
    • 可以有一个初始值,或者不需要这个参数
    # 自定义过滤器  跟默认的过滤器一样 最多只能接受两个参数
    # 利用register.filter注册并给该过滤器起别名
    @register.filter(name='baby')
    def index(a,b):
        return a + b
    
    
    # 自定义过滤器的使用
    # 在要使用自定义过滤器的模板文件中导入创建的py文件。语法:{% load 文件名 %}
    {% load mytag %}
    {{ 1|baby:1  }}
    {{ 1|baby:100  }}
    
    # 自定义的过滤器可以在逻辑语句使用 而自定义的标签不可以
    {% if mytag '1' '2' '3' '4' %}
        <p>有值</p>
    {% else %}
        <p>无值</p>
    {% endif %}#
    

    6-3. 自定义标签

    除了装饰器,其它步骤与自定义过滤器相似。

    过滤器只能有两个参数,自定义标签可以传多个值,空格传值。

    注:过滤器可以用在if判断中,标签不能

    # 自定义标签   可以接受任意多个参数
    # 利用register.simple_tag()注册并给该标签起别名
    
    @register.simple_tag(name='mytag')
    def mytag(a,b,c,d):
        return '%s?%s?%s?%s'%(a,b,c,d)
    
    # 自定义标签的使用 可以接受多个参数 参数与参数之间必须空格隔开
    {% load mytag %}
        {% mytag 'a' 'b' 'c' 'd' %}
    

    6-4. 自定义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页面
        
    # 自定义inclusion_tag的使用  当你需要使用一些页面组件的时候 并且该页面组件需要参数才能够正常渲染 你可以考虑使用inclusion_tag</p>
    {% load mytag %}
        {% xxx 5 %}
    

    七、模板的继承

    模版继承可以创建一个基本的“骨架”模版,它包含站点中的全部元素,并且可以定义能够被子模版覆盖的 blocks

    注意:

    1. 模板上的block区域越多 页面的扩展性越强,一个模板页面最好有三块区域:css区域、html代码区域、js区域 html区域可以设置多个block。有了这三块区域,就能够实现每一个页面都有自己独立的css和js代码
    2. 不能在一个模板中定义多个相同名字的block标签
    3. 如果在模板中使用{% extends %}标签,它必须是模板中的第一个标签
    # 子模板login.html继承index.html文件模板,全部继承的情况下无法修改内容
    # 即login.html中只需要写一句代码
    {% extends 'home.html' %}
    
    
    # 如果子模板需要修改部分,就需要用到 block
    # 母模板 index.html
    ...
    <body>
    <div id="sidebar">
        # 划定这块区域可以修改,并取别名sidebar
        {% block sidebar %}
            <ul>
                <li><a href="/">Home</a></li>
                <li><a href="/blog/">Blog</a></li>
            </ul>
        {% endblock %}
    </div>
    <div id="content">
        # 划定这块区域可以修改,并取别名content
        {% block content %}{% endblock %}
    </div>
    
    
    
    # 子模板 login.html
    {% extends 'home.html' %}
    
    # 使用block,pycharm会自动提示有哪些区域
    {% block sidebar %}
        ...修改内容
    </style>
    {% endblock %}
    
    {% block content %}
        ...修改内容
    {% endblock %}
    

    八、模板的导入

    用简单的模板语句解决了重复组件的代码冗余

    语法:{% include '模板名称' %}

    # 做好注册前提准备,简单的代码可以直接运行imp路径
    # imp.html文件内容
    {% include 'fr.html' %}
    
    # fr.html文件内容
    <p>这是一个特别好看的form表单</p>
    
  • 相关阅读:
    在线教程-Qt参考文档
    利用QT中Qpainter画点,直线,弧线等简单图形
    Office2013下载地址
    Linux下声卡的安装(ALSA)
    聆听自由的声音----Linux下声卡驱动软件ALSA的安装与配置
    linux找回root密码
    删除排序数组中重复的元素【数组专题】
    类模板派生出新的类模板
    TCP的拥塞控制
    linux运行级别
  • 原文地址:https://www.cnblogs.com/shin09/p/11939557.html
Copyright © 2020-2023  润新知