Flask中truncate过滤器无效,不起作用的问题,truncate详解

10 篇文章 6 订阅
1 篇文章 0 订阅

昨天写flask模板,在使用过滤器truncate的时候发现并没有截断字符串,多次尝试都没用,还以为是jinja2模板的一个bug,百度了一下也没有找到解决的方法,于是就只好看一下源码,终于被我解决了,发出来分享,如果文中有错误的地方,还望各位大佬多多指教!

先上结果:其实不是没用,只是没有达到长度!!!!!

解决办法很简单,增加一个参数:leeway=0

truncate(6, killwords=True, leeway=0)

现在你马上就能看到效果了。 

如果只是解决问题的话,到这就可以了。下面来讲一下原理

 

首先看一下官方源码:

@environmentfilter
def do_truncate(env, s, length=255, killwords=False, end='...', leeway=None):
    """Return a truncated copy of the string. The length is specified
    with the first parameter which defaults to ``255``. If the second
    parameter is ``true`` the filter will cut the text at length. Otherwise
    it will discard the last word. If the text was in fact
    truncated it will append an ellipsis sign (``"..."``). If you want a
    different ellipsis sign than ``"..."`` you can specify it using the
    third parameter. Strings that only exceed the length by the tolerance
    margin given in the fourth parameter will not be truncated.

    .. sourcecode:: jinja

        {{ "foo bar baz qux"|truncate(9) }}
            -> "foo..."
        {{ "foo bar baz qux"|truncate(9, True) }}
            -> "foo ba..."
        {{ "foo bar baz qux"|truncate(11) }}
            -> "foo bar baz qux"
        {{ "foo bar baz qux"|truncate(11, False, '...', 0) }}
            -> "foo bar..."

    The default leeway on newer Jinja2 versions is 5 and was 0 before but
    can be reconfigured globally.
    """
    if leeway is None:
        leeway = env.policies['truncate.leeway']
    assert length >= len(end), 'expected length >= %s, got %s' % (len(end), length)
    assert leeway >= 0, 'expected leeway >= 0, got %s' % leeway
    if len(s) <= length + leeway:
        return s
    if killwords:
        return s[:length - len(end)] + end
    result = s[:length - len(end)].rsplit(' ', 1)[0]
    return result + end

 

注释写的挺好的,就不翻译了,有需要的可以直接复制,然后到翻译软件上面去翻译

重点来看一下参数:

 

  1. env        系统默认的环境变量,不管它
  2. s            传入的字符串
  3. length         截断后字符串想要保留的长度
  4. killwords     是否截断单词(当然了,对我们博大精深的中文是没用的,毕竟也不能把中文拆成两半啊)
  5. end             结束的符号,默认是
  6. leeway        容差(自己翻译的【手动滑稽】翻译软件的结果是“留有余地”),这个是重点!!!

下面来看一下功能(直接逐行翻译吧):

def do_truncate(env, s, length=255, killwords=False, end='...', leeway=None):
    # 判断是否传入leeway,如果没有,默认是为None
    if leeway is None:
        # 使用系统环境里面的leeway配置
        leeway = env.policies['truncate.leeway']
    # 断言:限制的长度必须大于末尾的字符串的长度,否则提示后面的信息
    assert length >= len(end), 'expected length >= %s, got %s' % (len(end), length)
    # 断言:容差必须是大于0的正数,如果为负数,则提示后面的信息
    assert leeway >= 0, 'expected leeway >= 0, got %s' % leeway
    # 上面是准备工作,配置好环境,符合条件才能开始正常工作嘛

    # 下面是对传入的字符串的操作
    # 如果字符串长度小于限制的长度 + 容差值,直接返回传入的字符串
    if len(s) <= length + leeway:
        return s
    # 到达这里就是长度大于限制长度 + 容差值了,那就需要对字符串进行处理了
    # 如果killwords=True
    if killwords:
        # 返回的字符串为:长度为(指定长度 - 结束符长度)的字符串 + 结束符。
        return s[:length - len(end)] + end
    # 到这里就是killwords=False,就是截断字符串了
    # 先截取(指定长度 - 结束符长度)的字符串,用rsplit(从右往左切割)切割,以空格为分隔符,切割一次,取前面部分
    # 示例:"How are you?" 截取10个长度为"How are yo"
    # 按空格从右往左切割一次后得到列表["How are", "yo"]
    # 最后取列表的第一个值,就是"How are"
    result = s[:length - len(end)].rsplit(' ', 1)[0]
    # 最后将字符串"How are"和结束符"..."拼接在一起后返回
    return result + end

这就是原理了,我们来检验一下是否正确吧!

结果和我们预料的一样 

注意,我这里指定了参数leeway=0,如果不指定的话,结果肯定会不一样的,在源码中作者注释里面有说明;

leeway参数默认值在新版本中是:5,在以前的版本中是:0

我用的版本是django2.1,新版本,所以默认值是5,如果不指定的话,那么在指定长度的基础上,超出5个长度都是不会被截断的,这点一定要注意,这也是为什么有时候我们明明设置了指定长度但是却没有截断效果的原因。

来看看不指定leeway=0的效果:

 我们指定的字符串长度为10,可是这都已经12了,但是还是没有截断,因为这个时候,实际上允许的长度已经是15(我们指定的10 + 系统默认的leeway=5)

 

好了!!!终于解决这个问题了!不是django模板有缺陷,而是我们的操作不对。有时候还是要看看源码才行啊!

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值