Day63 CVB 与模板层

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

Day63 CVB 与模板层

1. 内部如何实现?CBV源码剖析

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

  • 读源码,看到了@classonlymethod,所以as_view()是一个类方法
  • as_view 是一个闭包函数,返回一个 view。会立刻变形成 views.view。

url(r'^login/', views.view) # FBV一模一样

  • 所以两个本质上是一样的,都是路由对应函数内存地址。
  • cls是我们自己写的类。

注意

  • 不要自己去修改源码,除了bug没法找。
@classonlymethod
def as_view(cls, **initkwargs):
    """
    Main entry point for a request-response process.
    """
    for key in initkwargs:
        if key in cls.http_method_names:
            raise TypeError("You tried to pass in the %s method name as a "
                            "keyword argument to %s(). Don't do that."
                            % (key, cls.__name__))
        if not hasattr(cls, key):
            raise TypeError("%s() received an invalid keyword %r. as_view "
                            "only accepts arguments that are already "
                            "attributes of the class." % (cls.__name__, key))

    def view(request, *args, **kwargs):
        self = cls(**initkwargs)
        if hasattr(self, 'get') and not hasattr(self, 'head'):
            self.head = self.get
        self.request = request
        self.args = args
        self.kwargs = kwargs
        return self.dispatch(request, *args, **kwargs)
    view.view_class = cls
    view.view_initkwargs = initkwargs

    # take name and docstring from class
    update_wrapper(view, cls, updated=())

    # and possible attributes set by decorators
    # like csrf_exempt from dispatch
    update_wrapper(view, cls.dispatch, assigned=())
    return view

最后一步 return self.dispatch(request, *args, **kwargs)

注意

只要看到了 self.东西,一定要问自己,self是谁。
一定要时刻提醒自己,面向对象属性方法查找顺序。

  1. 先从对象自己找
  2. 再去类里面找
  3. 之后去爹中找。

dispatch方法是整个cbv的精髓所在。

def dispatch(self, request, *args, **kwargs):
    # Try to dispatch to the right method; if a method doesn't exist,
    # defer to the error handler. Also defer to the error handler if the
    # request method isn't on the approved list.
    if request.method.lower() in self.http_method_names:
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
        handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs)
  1. 获取请求的小写格式,然后在8个请求方法中,比对当前请求是否合法。
    如果不再8个之中,就会报错。
  2. 如果有,getattr,反射,通过字符串来操作对象的属性或者方法。
    这个handler变成了我们自己写的类里面的方法
  3. 自动调用get方法。

要求:
掌握到不看源码,也能够描述出cbv的内部执行流程。


2. 模板层

模板语法传值(locals方法,返回所有的名字)

def index(request):
    # 模板语法可以传递的后端python数据类型
    n = 123
    f = 11.11
    ...


    def func():
        print('我被执行了')
        return '你的另一半在等你'
    
    
    class MyClass(object):
        def get_self(self):
            return 'self'
    
        @staticmethod
        def get_func():
            return 'func'
    
        @classmethod
        def get_class(cls):
            return 'cls'
        def __str__(self):
            return '你到底会不会?'


    obj=MyClass()

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

总结:

  1. 《花括号》与《百分号》含义

    1. {{ }} 变量相关
    2. {% %} 逻辑相关
  2. 传递变量:

    1. { n }} 或 {{ f }} 或 {{ s }}
    2. 等等各种类型全部都可以传
  3. 传递函数

    1. {{ func }}
    2. 函数自动帮你加括号调用,传的是返回值。
    3. 切记,不支持给函数传参数,会给你报错。
  4. 传递类

    1. 类 {{ MyClass }}

    2. 对象 {{ obj }}

    3. 传类名的时候,也会自动加括号调用(实例化)

    4. {{ obj.get_self }}
      {{ obj.get_func }}
      {{ obj.get_class }}

  5. 总结:

    1. 内部能够自动判断出当前的变量名是否可以加括号调用,
    2. 如果可以就自动执行(针对函数名和类名)
  6. 列表和字典取值

    1. 只能用句点符 . ,哪怕字典列表嵌套
    2. d.info.3.hobby

3. 模板语法过滤器

  • 类似于一些简单的内置方法
  • 后端传来一个变量,前端展示关于变量的信息
  • Django内置 60+ 过滤器,我们了解10个左右,差不多了。
  • 后面碰到了再去记忆

{{ 变量名|过滤器:'参数' }}

## 下面都可以包含在 <p></p> 标签中
--- --- --- --- ---
## 统计长度:
{{ s|length }}

## 默认值:
{{ b|default: '啥也不是' }}

## 文件大小(自动帮你和1024做计算。)
<!-- 后端 -->
file_size = 123421
<!-- 前端 -->
{{ file_size|filesizeformat }}

## 日期格式化
<!-- 后端 -->
import datetime
current_time = datetime.datetime.now()
<!-- 前端 -->
{{ current_time|date:'Y-m-d H:i:s' }}

## 切片操作:
{{ l|slice:'0:4:2' }}

## 切取字符(例如文章摘要,加上三个点):
info = 'aeioajflvnaowenvzbonod'
{{ info|truncatechars:9 }}

## 切取单词(不包含三个点了,只认空格):
egl = 'My name is jason, and my ...'
{{ egl|truncatedwords:9 }}
msg = 'I Love You and you?'

## 移除字符
{{ l|cut:' ' }}
## 拼接操作:
{{ l|join:'$' }}
## 拼接操作(加法):
{{ n|add:10 }}
## 拼接操作(加法):
{{ s|add:msg }}

## safe:取消转义
hhh = '<h1>敏敏</h1>'
不转义:{{ hhh }}
转义:{{ hhh|safe }}

后端转义

from django.utils.safestring import mark_safe
hhhh = '<h1>新新</h1>'
res = marksafe(hhhh)

以后你在写全栈项目的时候,前端代码也可以在后端写好,传递给前端。


4. 模板语法标签

一堆逻辑,包括for循环等等来展示变量

# 列表变量,在前端展示
def index(request):
    l = ['小王', '小李', '敏敏', '帅帅', '张三', '月月', '静静', ]
    return render(request, 'index.html', locals())

注意的关键字:

  1. endif / endfor
  2. forloop (for)
  3. empty (for)
  4. with 起别名
  5. 字典元素可以用句点符

for 循环

  • 有 first,有last
{% for foo in l %}
    <!--  <p>{{ forloop }}</p>-->
    <p>{{ foo }}</p>
{% endfor %}

{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 7, 'revcounter0': 6, 'first': True, 'last': False}

if 判断

  • 有elif,有else
{% if b %}
    <p>baby</p>
{% elif s %}
    <p>都来吧</p>
{% else %}
    <p>老baby</p>
{% endif %}

混合使用

{% for foo in l %}
    {% if forloop.first %}
        <p>这是我的第一次</p>
    {% elif forloop.last %}
        <p>这是最后一次</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
    {% empty %}
        <p>都跑了</p>
{% endfor %}

字典方法都可以。

for foo in d.keys
for foo in d.values
for foo in d.items

起别名

  • 解决:字典列表嵌套太多,名字太长
{{% with d.hobby.3.inf as nb %}}
    <p>{ nb }</p>
{{% endwith %}}

5. 模板语法自定义过滤、标签、inclusion_tag

作用

  1. 局部页面
  2. 触发函数,把结果传到前端

必须要有的三个条件

  1. templatetags 文件夹
  2. 任意名称 py 文件
  3. 书写下面两句话

templatetags/mytag.py

# templatetags/mytag.py 必须包含两行代码
from django import template
register = template.Library()


# 自定义过滤器
@register.filter(name='baby')
def my_sum(v1, v2):
    return v1 + v2


# 自定义标签
@register.simple_tag(name='plus')
def index(a, b, c, d):
    return '%s-%s-%s-%s'%(a, b, c, d)


@register.inclusion_tag('left.html')
def left(n):
    data = ['第{}项'.format(i) for i in range(n)]
    # 第一种传值
    # return {'data': data}
    # 第二种传值,更方便
    return locals()

index.html

<h1>自定义过滤器的使用(过滤器最多两个参数)</h1>
{% load mytag %}
花括号花括号
<p>{{ n|baby:666 }}</p>


<h1>自定义标签的使用</h1>
类似自定义函数
多个参数用空格隔开
花括号百分号
<p>{% plus 'jason' 123 123 123 %}</p>


<h1>自定义inclusion_tag</h1>
一般不是一个完整的页面,是一个局部页面
{% left 10 %}

left.html

<ul>
    {% for foo in data %}
        <li>{{ foo }}</li>
    {% endfor %}
</ul>

6. 模板继承

一些网站,几乎不变,就是局部在跳转

步骤

  1. 先要划定被修改的区域
  2. 子板中继承,然后可以根据名字修改
  3. 除了自己写,也可以继承爹的模板:{{ block.super }} 名字
<div class="col-md-3">
  <div class="list-group">
    <a href="/app02/home/" class="list-group-item">首页</a>
    <a href="/app02/login/" class="list-group-item">登录</a>
    <a href="/app02/reg/" class="list-group-item">注册</a>
  </div>
</div>
<!--...-->
{% block content %}
    <h1>Hello world</h1>
    Panel content
    <div class="jumbotron">
      <div class="container">
        ...
      </div>
    </div>
{% endblock %}
<!--...-->

lgoin.html

{% extends 'home.html' %}

{% block content %}
<h1 class="text-center">注册页面</h1>
<form action="" >
    <p>username:</p>
    <p>password:</p>
    <input type="submit" class="btn btn-success" name="" id="">

</form>
{% endblock %}

一般来说,至少有三款会被修改的区域

  1. html
  2. css
  3. js
<!--css 区域-->
{% block css %}
    <!--什么都不写    -->
{% endblock %}

<!--文本区域-->
{% block content %}
    <!--什么都不写    -->
{% endblock %}

<!--js区域-->
{% block js %}
    <!--什么都不写    -->
{% endblock %}
{% extends 'home.html' %}
{% block js %}
    <!--写我单独的js    -->
{% endblock %}

一般情况下,划定的区域越多,可扩展性越强
但是太多了,不如自己写。

模板语法导入

页面的某一个局部,当成模块的形式,哪里需要导哪里

<p>模板的导入</p>
{% include 'wasai.html' %}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值