zoukankan      html  css  js  c++  java
  • 9_18视图层某内部原理(fbv和cbv)与模板层

    一。render内部原理。

      在render中往往需要返回三个参数,request,模板和一些键值对。

      键值对中存储的是需要对模板渲染的值。

      如果手动实现可以如下:

    from django.template import Template,Context
    def index(request):
        temp = Template('<h1>{{ user }}</h1>')
        con = Context({"user":{"name":'jason',"password":'123'}})
        res = temp.render(con)
        print(res)
        return HttpResponse(res)

       首先拿到模板,再用render对模板进行渲染,最后使用字符串的形式返回。

    二。FBV和CBV

      FBV(function base view)

      CBV(class base view)

      一个是基于函数编写的视图,一个是基于类编写的视图。

      对于基于函数编写的就是运行其返回的值,也就是三个渲染模板函数产生的值。

      而基于类编写的,需要运行视图函数中的一个内置类函数产生的函数,本质是一个闭包函数。

      编写类函数:

    from django.views import View
    class MyLogin(View):
        def get(self,request):
                print("from MyLogin get方法")
            return render(request,'login.html')
        def post(self,request):
            return HttpResponse("from MyLogin post方法")        

      编写url:

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

      可以看到其中需要调用mylogin中运行自己编写的类中的as_view函数。然而这个函数是继承的VIew中的函数。

      as_view

      as_view是一个绑定类方法的函数。除了正常的异常处理之外,其内部有一个闭包函数,也就是说调用这个函数之后产生的结果就是这个view函数的返回值。

      当url匹配成功后,会调用view方法,在view内部返回的是一个使用自定义函数产生的的对象中的dispatch方法(继承父类View的方法)。

      也就说dispatch产生的值就是最终返回的值。也就是渲染的页面。dispatch中会首先判断你的请求是否是属于8个基本请求之一。如果是就通过这个字符串和自身定义的类产生的对象,getattr获取对应的函数,最后通过这个函数运行得到渲染的模板返回。

    八种请求:
    http_method_names =
    ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    三。django中settings源码。

      对于django中的settings是提供给我们配置文件用的,除了大写的变量之外,其他变量都没有效果,所以其内部会经过独特的处理。

      其实,在django框架中有一个全局的配置文件,暴露给用户的settings是很小的一部分,其调用方法如下:

    from django.conf import settings

      首先介绍os.environ。这相当于一个全局的字典,可以支持字典取值设置值的任何方法。其次介绍dir方法,dir可以将一个模块中的所有变量名取出。

      在django启动时,会直接运行manage.py文件,这个文件会先将暴露给用户的settings路径,以变量名:DJANGO_SETTINGS_MODULE为键,加入全局字典中。

      在settings方法内部就是一个单例模式,每当调用settings时,会返回一个对象LazySettings()

      在LazySettings()内部,首先从全局字典中获取暴露给用户的settings的字符串,将其传给settings方法进行配置。

      settings方法首先使用dir方法和for循环获取全局设置中的所有配置,如果是大写就添加到他产生的对象中,也就是调用模块时。

      接着再调用用户配置的settings,使用字符串调用模块。同样使用for循环。如果本来的设置中存在就覆盖其值,没有则新建。

      也就是说会优先使用用户的设置。

    四。模板层之传递值。

      当我们使用视图函数向模板传值时,一般都使用字典的方式。

    def index(request):
        return render(requset,'html',{'名字‘:’数据‘})

      然而当有多个值的时侯,单个传值显然很麻烦,通过locals()方法,可以将该函数中的所有参数传递给前端:

    def index(request):
      return render(request,'reg.html',locals())

      虽然locals()方法可以一劳永逸,但是会浪费资源,会传递前端不要的参数。

      传入的值如果数python的数据类型几乎都可以被渲染,但是也有特殊的:

      1.函数。

      如果传函数名,会自动加括号调用该函数,前端展示的是函数调用之后的返回值。

      注意:如果函数需要参数的话 那么模板语法不支持。

      2.类。

      如果将类实例化对象传给前端,会将该对象的内存地址传入,前端页面可以通过该对象名点出其中的函数方法和变量。

      其中的函数也不支持传参。

      模板语法:

      {{}} 变量相关。

      {%%}语法相关。

    五。模板语法过滤器。

      过滤器的固定语法是:

    {{ 变量名|过滤器名 }}

      其内部原理是,将|前面的变量名当成过滤器的第一个参数传入。

    @register.filter(is_safe=False)
    def length(value):
        """Returns the length of the value - useful for lists."""
        try:
            return len(value)
        except (ValueError, TypeError):
            return 0

      如果不支持该过滤器,会返回0

     1。{{ l|length }}

      统计l的长度。

      2。{{ ss|default:'当|左边的变量为空就会返回|右边的值' }}

      如果ss存在,则返回ss,如果为空则返回default,如果ss不存在也返回他,和get很像。

      3。{{ file_size|filesizeformat }}

      将file_size转换成文件大小。

      4。{{ info|truncatewords:3 }}

      按照空格将info文字进行截断,3是截断的个数。

      5。{{ info|truncatechars:6 }}

      按照字符截取info,点也算,也就是至少传入3。

      6。{{ xxx|safe }}

      一般的,xxx字符串传入前端后,直接以字符串的形式传入,但是加上safe之后,就会将xxx按照原来的意思进行输入,如果该字符是页面元素,会显示页面元素。

      后端可以取消这个机制:

    from django.utils.safestring import mark_safe
    zzz=make_safe('内容')

      7.{{ ctime|date:'Y-m-d H-i-s' }}

      如果后端传来的ctime是一个时间类型的数据,那么可以通过过滤器date进行渲染。

      8.{{ n|add:100 }}

      将n数字加100,如果是字符串,则拼接字符串。

      9.{{ l|slice:'0:5:2' }}

      将1切片,故头不顾尾,支持步长

    六。模板层之标签。

      标签也就是逻辑相关的操作,使用{% %}

      1.forloop。

      在for循环中,这个标签可以记录for循环的一些值:

    {% for foo in l %}
        <p>{{ forloop }}</p>
    {% endfor %}

      如图:

       2.{%empty%}

      当for 循环为空,则执行这个标签下的方法。

      3.if判断:

    {% if '' %}
    <p>xxx条件为true</p>
        {% else %}
        <p>xxx条件为false</p>
    {% endif %}

      4.点。

      django模板语法在取值的时候 统一使用句点符。如:

    { l.6.3.name }

      5.{%with 数据 as 别名%}

      可以通过这个标签给数据取别名,这样可以方便操作。在with中就可以使用该别名。

        {% with l.6.3.name as ttt %}  
            {{ ttt }}
            {{ l.6.3.name }}
        {% endwith %}

      6.for循环中字典的三个方法:

    {% for foo in d.keys %}
        <p>{{ foo }}</p>
    {% endfor %}
    {% for foo in d.values %}
        <p>{{ foo }}</p>
    {% endfor %}
    {% for foo in d.items %}
        <p>{{ foo }}</p>
    {% endfor %}

    七。自定义过滤器与标签。

      自定义的东西需要遵循下面三个步骤:

      1.必须在你的应用下新建一个名为templatetags文件夹

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

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

        from django import template

        register = template.Library()

      然后就可以在这个文件下面编写字节的过滤器了:

    @register.filter(name='baby')
    def index(a,b):
        # 该过滤器只做一个加法运算  是|add简易版本
        return a + b

      定义的时候需要给它取个别名,然后要阿紫网页中调用该过滤器。

    {% load mytag %}
    {{ 123|baby:1}}

      其中mytag是template下的文件名,baby是起的名字。

      注意,自定义guolq只能指定两个形参,但是第二个参数可以是一个列表。

      自定义标签

      标签的定义方法和guolvq差不多:

    @register.simple_tag(name='jason')
    def xxx(a,b,c,year):
        return '%s?%s|%s{%s'%(a,b,c,year)

      但是标签支持传入多个参数,标签的使用:

    支持传多个参数  参数与参数之间 空格隔开即可、
    {% load mytag %}
    {% jason 1 2 3 year=2 %}

      也支持关键字传参。

      自定义inclusion_tag

      这个工作原理是接受用户传入的参数,然后根据参数渲染出一个页面,再返回到调用inclusion_tag的地方。

      定义方法:

    # 自定义inclusion_tag
    @register.inclusion_tag('bigplus.html')
    def bigplus(n):
        l = []
        for i in range(n):
            l.append('第%s项'%i)
        return {'l':l}

      它需要指定一个页面,这个页面是要被调用的页面,会接受这个函数返回的值。

       调用:

    {% load mytag %}
    {% bigplus 5 %}

      应用场景:

      可以定义一个多次运用的页面,可以反复调用。

    八。模板的继承和导入。

      继承:

      当多个页面整体的样式都大差不差的情况下 可以设置一个模板文件。

      在该模板文件中 使用block块划分多个预期。

      之后子版在使用模板的时候 可以通过block块的名字 来选定到底需要修改哪一部分区域

      也就是说,母模板中可以将需要改变的地方通过{% block css%}  {% endblock%}划分页面。

    {% block css %}
        子页面自己的css代码
    {% endblock %}            
    {% block content %}
        子页面自己的html代码
    {% endblock %}
    {% block js %}
        子页面自己的js代码
    {% endblock %}

      这个名字是自己定义的。

      在其他页面可以继承这个母模板进行复用:

    # 模板的继承  使用方式
    {% extends 'home.html' %}
    
    {% block css %}
        <style>
            h1 {
                color: red;
            }
        </style>
    {% endblock %}

      通过{{ block.super}} 也可以获得目标签该区域的元素

      一般情况下 模板上的block越多 页面的可扩展性就越强。

      模板的导入:

    {% include 'beautiful.html' %}

      将一个静态的页面,通过导入的方式加入模板。

     九。模型层。

      1.单表操作。

      create_time = models.DateField()

      创建时间的这个参数有关键性的参数。

    1.auto_now:每次操作数据 都会自动刷新当前操作的时间
    2.auto_now_add:在创建数据的时候 会自动将创建时间记录下来 后续的修改不会影响该字段

      增:

      方法1:

    book_obj = models.Book.objects.
    create(title='三国',price=19.99,create_time='2019-11-11')

       方法2:

        方式2:对象点save()方法
        from datetime import datetime
        ctime = datetime.now()
        book_obj = models.Book(title='',price=96.66,create_time=ctime)
        book_obj.save()

      查:

    models.Book.objects.all()
    #查询所有的数据
    models.Book.objects.get(id=1)
    #按照id查询
    models.Book.objects.get(pk=1)
    #自动按照主键查询

      改:

        1.update
        models.Book.objects.filter(pk=1).update(title='三国演义')
        2.对象.save()
        book_obj = models.Book.objects.get(pk=1)
        book_obj.price = 666.66
        book_obj.save()

      删:

     删除  delete()
     models.Book.objects.filter(pk=2).delete()

      其他的函数方法:

      (1) all():

       查询所有结果

      (2)filter(**kwargs): 它包含了与所给筛选条件相匹配的对象

      (3)get(**kwargs):

      返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象)

      (4)exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象

    print(models.Book.objects.exclude(pk=1)) 
    # 只要pk不是1的数据全部查询出来

      (5) order_by(*field): 对查询结果排序('-id') / ('price')

    print(models.Book.objects.order_by('price'))
     # 默认是升序
    print(models.Book.objects.order_by('-price')) 
    # 加负号就是降序

      (6) reverse(): 对查询结果反向排序 >> > 前面要先有排序才能反向

    print(models.Book.objects.order_by('price').reverse())

      (7) count(): 返回数据库中匹配查询(QuerySet)

    print(models.Book.objects.count()) 
    # 对查询出来的结果进行一个计数的对象数量。

      (8) first(): 返回第一条记录print(models.Book.objects.filter(pk=1).first())

      (9) last(): 返回最后一条记录

    print(models.Book.objects.all())
    
    print(models.Book.objects.all().last())

       (10) exists(): 如果QuerySet包含数据,就返回True,否则返回False

    print(models.Book.objects.filter(pk=1000))
    
    print(models.Book.objects.filter(pk=1000).exists())

    补充:

      1.如果一个类中的函数时绑定类方法,而使用对象调用,会获取对象的类,当成第一个参数传入。

      2。通过字符串导入模块的方法:

    import importlib
    mod = importlib.import_module(从哪个模块中,’所调用的模块的字符串‘)

       3.在django中可以写一个单独的test模块进行测试。:

    import os
    import sys
    
    if __name__ == "__main__":
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day54.settings")
        import django
        django.setup()
    #下面导入模块进行测试。
  • 相关阅读:
    简单的远程控制软件
    VS集成环境中的JavaScript脚本语法检查
    vs2022安装
    有关httpContext.Current.Session[值] 取值的问题
    【python3.7】文件操作
    148. 排序链表
    11. 盛最多水的容器
    23. 合并K个升序链表
    147. 对链表进行插入排序
    146. LRU 缓存机制
  • 原文地址:https://www.cnblogs.com/LZXlzmmddtm/p/11545993.html
Copyright © 2011-2022 走看看