jinja2.filters
Built-in template filters used with the | operator.
1"""Built-in template filters used with the ``|`` operator.""" 2import math 3import random 4import re 5import typing 6import typing as t 7from collections import abc 8from itertools import chain 9from itertools import groupby 10 11from markupsafe import escape 12from markupsafe import Markup 13from markupsafe import soft_str 14 15from .async_utils import async_variant 16from .async_utils import auto_aiter 17from .async_utils import auto_await 18from .async_utils import auto_to_list 19from .exceptions import FilterArgumentError 20from .runtime import Undefined 21from .utils import htmlsafe_json_dumps 22from .utils import pass_context 23from .utils import pass_environment 24from .utils import pass_eval_context 25from .utils import pformat 26from .utils import url_quote 27from .utils import urlize 28 29if t.TYPE_CHECKING: 30 import typing_extensions as te 31 from .environment import Environment 32 from .nodes import EvalContext 33 from .runtime import Context 34 from .sandbox import SandboxedEnvironment # noqa: F401 35 36 class HasHTML(te.Protocol): 37 def __html__(self) -> str: 38 pass 39 40 41F = t.TypeVar("F", bound=t.Callable[..., t.Any]) 42K = t.TypeVar("K") 43V = t.TypeVar("V") 44 45 46def ignore_case(value: V) -> V: 47 """For use as a postprocessor for :func:`make_attrgetter`. Converts strings 48 to lowercase and returns other types as-is.""" 49 if isinstance(value, str): 50 return t.cast(V, value.lower()) 51 52 return value 53 54 55def make_attrgetter( 56 environment: "Environment", 57 attribute: t.Optional[t.Union[str, int]], 58 postprocess: t.Optional[t.Callable[[t.Any], t.Any]] = None, 59 default: t.Optional[t.Any] = None, 60) -> t.Callable[[t.Any], t.Any]: 61 """Returns a callable that looks up the given attribute from a 62 passed object with the rules of the environment. Dots are allowed 63 to access attributes of attributes. Integer parts in paths are 64 looked up as integers. 65 """ 66 parts = _prepare_attribute_parts(attribute) 67 68 def attrgetter(item: t.Any) -> t.Any: 69 for part in parts: 70 item = environment.getitem(item, part) 71 72 if default is not None and isinstance(item, Undefined): 73 item = default 74 75 if postprocess is not None: 76 item = postprocess(item) 77 78 return item 79 80 return attrgetter 81 82 83def make_multi_attrgetter( 84 environment: "Environment", 85 attribute: t.Optional[t.Union[str, int]], 86 postprocess: t.Optional[t.Callable[[t.Any], t.Any]] = None, 87) -> t.Callable[[t.Any], t.List[t.Any]]: 88 """Returns a callable that looks up the given comma separated 89 attributes from a passed object with the rules of the environment. 90 Dots are allowed to access attributes of each attribute. Integer 91 parts in paths are looked up as integers. 92 93 The value returned by the returned callable is a list of extracted 94 attribute values. 95 96 Examples of attribute: "attr1,attr2", "attr1.inner1.0,attr2.inner2.0", etc. 97 """ 98 if isinstance(attribute, str): 99 split: t.Sequence[t.Union[str, int, None]] = attribute.split(",") 100 else: 101 split = [attribute] 102 103 parts = [_prepare_attribute_parts(item) for item in split] 104 105 def attrgetter(item: t.Any) -> t.List[t.Any]: 106 items = [None] * len(parts) 107 108 for i, attribute_part in enumerate(parts): 109 item_i = item 110 111 for part in attribute_part: 112 item_i = environment.getitem(item_i, part) 113 114 if postprocess is not None: 115 item_i = postprocess(item_i) 116 117 items[i] = item_i 118 119 return items 120 121 return attrgetter 122 123 124def _prepare_attribute_parts( 125 attr: t.Optional[t.Union[str, int]] 126) -> t.List[t.Union[str, int]]: 127 if attr is None: 128 return [] 129 130 if isinstance(attr, str): 131 return [int(x) if x.isdigit() else x for x in attr.split(".")] 132 133 return [attr] 134 135 136def do_forceescape(value: "t.Union[str, HasHTML]") -> Markup: 137 """Enforce HTML escaping. This will probably double escape variables.""" 138 if hasattr(value, "__html__"): 139 value = t.cast("HasHTML", value).__html__() 140 141 return escape(str(value)) 142 143 144def do_urlencode( 145 value: t.Union[str, t.Mapping[str, t.Any], t.Iterable[t.Tuple[str, t.Any]]] 146) -> str: 147 """Quote data for use in a URL path or query using UTF-8. 148 149 Basic wrapper around :func:`urllib.parse.quote` when given a 150 string, or :func:`urllib.parse.urlencode` for a dict or iterable. 151 152 :param value: Data to quote. A string will be quoted directly. A 153 dict or iterable of ``(key, value)`` pairs will be joined as a 154 query string. 155 156 When given a string, "/" is not quoted. HTTP servers treat "/" and 157 "%2F" equivalently in paths. If you need quoted slashes, use the 158 ``|replace("/", "%2F")`` filter. 159 160 .. versionadded:: 2.7 161 """ 162 if isinstance(value, str) or not isinstance(value, abc.Iterable): 163 return url_quote(value) 164 165 if isinstance(value, dict): 166 items: t.Iterable[t.Tuple[str, t.Any]] = value.items() 167 else: 168 items = value # type: ignore 169 170 return "&".join( 171 f"{url_quote(k, for_qs=True)}={url_quote(v, for_qs=True)}" for k, v in items 172 ) 173 174 175@pass_eval_context 176def do_replace( 177 eval_ctx: "EvalContext", s: str, old: str, new: str, count: t.Optional[int] = None 178) -> str: 179 """Return a copy of the value with all occurrences of a substring 180 replaced with a new one. The first argument is the substring 181 that should be replaced, the second is the replacement string. 182 If the optional third argument ``count`` is given, only the first 183 ``count`` occurrences are replaced: 184 185 .. sourcecode:: jinja 186 187 {{ "Hello World"|replace("Hello", "Goodbye") }} 188 -> Goodbye World 189 190 {{ "aaaaargh"|replace("a", "d'oh, ", 2) }} 191 -> d'oh, d'oh, aaargh 192 """ 193 if count is None: 194 count = -1 195 196 if not eval_ctx.autoescape: 197 return str(s).replace(str(old), str(new), count) 198 199 if ( 200 hasattr(old, "__html__") 201 or hasattr(new, "__html__") 202 and not hasattr(s, "__html__") 203 ): 204 s = escape(s) 205 else: 206 s = soft_str(s) 207 208 return s.replace(soft_str(old), soft_str(new), count) 209 210 211def do_upper(s: str) -> str: 212 """Convert a value to uppercase.""" 213 return soft_str(s).upper() 214 215 216def do_lower(s: str) -> str: 217 """Convert a value to lowercase.""" 218 return soft_str(s).lower() 219 220 221def do_items(value: t.Union[t.Mapping[K, V], Undefined]) -> t.Iterator[t.Tuple[K, V]]: 222 """Return an iterator over the ``(key, value)`` items of a mapping. 223 224 ``x|items`` is the same as ``x.items()``, except if ``x`` is 225 undefined an empty iterator is returned. 226 227 This filter is useful if you expect the template to be rendered with 228 an implementation of Jinja in another programming language that does 229 not have a ``.items()`` method on its mapping type. 230 231 .. code-block:: html+jinja 232 233 <dl> 234 {% for key, value in my_dict|items %} 235 <dt>{{ key }} 236 <dd>{{ value }} 237 {% endfor %} 238 </dl> 239 240 .. versionadded:: 3.1 241 """ 242 if isinstance(value, Undefined): 243 return 244 245 if not isinstance(value, abc.Mapping): 246 raise TypeError("Can only get item pairs from a mapping.") 247 248 yield from value.items() 249 250 251_space_re = re.compile(r"\s", flags=re.ASCII) 252 253 254@pass_eval_context 255def do_xmlattr( 256 eval_ctx: "EvalContext", d: t.Mapping[str, t.Any], autospace: bool = True 257) -> str: 258 """Create an SGML/XML attribute string based on the items in a dict. 259 260 If any key contains a space, this fails with a ``ValueError``. Values that 261 are neither ``none`` nor ``undefined`` are automatically escaped. 262 263 .. sourcecode:: html+jinja 264 265 <ul{{ {'class': 'my_list', 'missing': none, 266 'id': 'list-%d'|format(variable)}|xmlattr }}> 267 ... 268 </ul> 269 270 Results in something like this: 271 272 .. sourcecode:: html 273 274 <ul class="my_list" id="list-42"> 275 ... 276 </ul> 277 278 As you can see it automatically prepends a space in front of the item 279 if the filter returned something unless the second parameter is false. 280 281 .. versionchanged:: 3.1.3 282 Keys with spaces are not allowed. 283 """ 284 items = [] 285 286 for key, value in d.items(): 287 if value is None or isinstance(value, Undefined): 288 continue 289 290 if _space_re.search(key) is not None: 291 raise ValueError(f"Spaces are not allowed in attributes: '{key}'") 292 293 items.append(f'{escape(key)}="{escape(value)}"') 294 295 rv = " ".join(items) 296 297 if autospace and rv: 298 rv = " " + rv 299 300 if eval_ctx.autoescape: 301 rv = Markup(rv) 302 303 return rv 304 305 306def do_capitalize(s: str) -> str: 307 """Capitalize a value. The first character will be uppercase, all others 308 lowercase. 309 """ 310 return soft_str(s).capitalize() 311 312 313_word_beginning_split_re = re.compile(r"([-\s({\[<]+)") 314 315 316def do_title(s: str) -> str: 317 """Return a titlecased version of the value. I.e. words will start with 318 uppercase letters, all remaining characters are lowercase. 319 """ 320 return "".join( 321 [ 322 item[0].upper() + item[1:].lower() 323 for item in _word_beginning_split_re.split(soft_str(s)) 324 if item 325 ] 326 ) 327 328 329def do_dictsort( 330 value: t.Mapping[K, V], 331 case_sensitive: bool = False, 332 by: 'te.Literal["key", "value"]' = "key", 333 reverse: bool = False, 334) -> t.List[t.Tuple[K, V]]: 335 """Sort a dict and yield (key, value) pairs. Python dicts may not 336 be in the order you want to display them in, so sort them first. 337 338 .. sourcecode:: jinja 339 340 {% for key, value in mydict|dictsort %} 341 sort the dict by key, case insensitive 342 343 {% for key, value in mydict|dictsort(reverse=true) %} 344 sort the dict by key, case insensitive, reverse order 345 346 {% for key, value in mydict|dictsort(true) %} 347 sort the dict by key, case sensitive 348 349 {% for key, value in mydict|dictsort(false, 'value') %} 350 sort the dict by value, case insensitive 351 """ 352 if by == "key": 353 pos = 0 354 elif by == "value": 355 pos = 1 356 else: 357 raise FilterArgumentError('You can only sort by either "key" or "value"') 358 359 def sort_func(item: t.Tuple[t.Any, t.Any]) -> t.Any: 360 value = item[pos] 361 362 if not case_sensitive: 363 value = ignore_case(value) 364 365 return value 366 367 return sorted(value.items(), key=sort_func, reverse=reverse) 368 369 370@pass_environment 371def do_sort( 372 environment: "Environment", 373 value: "t.Iterable[V]", 374 reverse: bool = False, 375 case_sensitive: bool = False, 376 attribute: t.Optional[t.Union[str, int]] = None, 377) -> "t.List[V]": 378 """Sort an iterable using Python's :func:`sorted`. 379 380 .. sourcecode:: jinja 381 382 {% for city in cities|sort %} 383 ... 384 {% endfor %} 385 386 :param reverse: Sort descending instead of ascending. 387 :param case_sensitive: When sorting strings, sort upper and lower 388 case separately. 389 :param attribute: When sorting objects or dicts, an attribute or 390 key to sort by. Can use dot notation like ``"address.city"``. 391 Can be a list of attributes like ``"age,name"``. 392 393 The sort is stable, it does not change the relative order of 394 elements that compare equal. This makes it is possible to chain 395 sorts on different attributes and ordering. 396 397 .. sourcecode:: jinja 398 399 {% for user in users|sort(attribute="name") 400 |sort(reverse=true, attribute="age") %} 401 ... 402 {% endfor %} 403 404 As a shortcut to chaining when the direction is the same for all 405 attributes, pass a comma separate list of attributes. 406 407 .. sourcecode:: jinja 408 409 {% for user in users|sort(attribute="age,name") %} 410 ... 411 {% endfor %} 412 413 .. versionchanged:: 2.11.0 414 The ``attribute`` parameter can be a comma separated list of 415 attributes, e.g. ``"age,name"``. 416 417 .. versionchanged:: 2.6 418 The ``attribute`` parameter was added. 419 """ 420 key_func = make_multi_attrgetter( 421 environment, attribute, postprocess=ignore_case if not case_sensitive else None 422 ) 423 return sorted(value, key=key_func, reverse=reverse) 424 425 426@pass_environment 427def do_unique( 428 environment: "Environment", 429 value: "t.Iterable[V]", 430 case_sensitive: bool = False, 431 attribute: t.Optional[t.Union[str, int]] = None, 432) -> "t.Iterator[V]": 433 """Returns a list of unique items from the given iterable. 434 435 .. sourcecode:: jinja 436 437 {{ ['foo', 'bar', 'foobar', 'FooBar']|unique|list }} 438 -> ['foo', 'bar', 'foobar'] 439 440 The unique items are yielded in the same order as their first occurrence in 441 the iterable passed to the filter. 442 443 :param case_sensitive: Treat upper and lower case strings as distinct. 444 :param attribute: Filter objects with unique values for this attribute. 445 """ 446 getter = make_attrgetter( 447 environment, attribute, postprocess=ignore_case if not case_sensitive else None 448 ) 449 seen = set() 450 451 for item in value: 452 key = getter(item) 453 454 if key not in seen: 455 seen.add(key) 456 yield item 457 458 459def _min_or_max( 460 environment: "Environment", 461 value: "t.Iterable[V]", 462 func: "t.Callable[..., V]", 463 case_sensitive: bool, 464 attribute: t.Optional[t.Union[str, int]], 465) -> "t.Union[V, Undefined]": 466 it = iter(value) 467 468 try: 469 first = next(it) 470 except StopIteration: 471 return environment.undefined("No aggregated item, sequence was empty.") 472 473 key_func = make_attrgetter( 474 environment, attribute, postprocess=ignore_case if not case_sensitive else None 475 ) 476 return func(chain([first], it), key=key_func) 477 478 479@pass_environment 480def do_min( 481 environment: "Environment", 482 value: "t.Iterable[V]", 483 case_sensitive: bool = False, 484 attribute: t.Optional[t.Union[str, int]] = None, 485) -> "t.Union[V, Undefined]": 486 """Return the smallest item from the sequence. 487 488 .. sourcecode:: jinja 489 490 {{ [1, 2, 3]|min }} 491 -> 1 492 493 :param case_sensitive: Treat upper and lower case strings as distinct. 494 :param attribute: Get the object with the min value of this attribute. 495 """ 496 return _min_or_max(environment, value, min, case_sensitive, attribute) 497 498 499@pass_environment 500def do_max( 501 environment: "Environment", 502 value: "t.Iterable[V]", 503 case_sensitive: bool = False, 504 attribute: t.Optional[t.Union[str, int]] = None, 505) -> "t.Union[V, Undefined]": 506 """Return the largest item from the sequence. 507 508 .. sourcecode:: jinja 509 510 {{ [1, 2, 3]|max }} 511 -> 3 512 513 :param case_sensitive: Treat upper and lower case strings as distinct. 514 :param attribute: Get the object with the max value of this attribute. 515 """ 516 return _min_or_max(environment, value, max, case_sensitive, attribute) 517 518 519def do_default( 520 value: V, 521 default_value: V = "", # type: ignore 522 boolean: bool = False, 523) -> V: 524 """If the value is undefined it will return the passed default value, 525 otherwise the value of the variable: 526 527 .. sourcecode:: jinja 528 529 {{ my_variable|default('my_variable is not defined') }} 530 531 This will output the value of ``my_variable`` if the variable was 532 defined, otherwise ``'my_variable is not defined'``. If you want 533 to use default with variables that evaluate to false you have to 534 set the second parameter to `true`: 535 536 .. sourcecode:: jinja 537 538 {{ ''|default('the string was empty', true) }} 539 540 .. versionchanged:: 2.11 541 It's now possible to configure the :class:`~jinja2.Environment` with 542 :class:`~jinja2.ChainableUndefined` to make the `default` filter work 543 on nested elements and attributes that may contain undefined values 544 in the chain without getting an :exc:`~jinja2.UndefinedError`. 545 """ 546 if isinstance(value, Undefined) or (boolean and not value): 547 return default_value 548 549 return value 550 551 552@pass_eval_context 553def sync_do_join( 554 eval_ctx: "EvalContext", 555 value: t.Iterable, 556 d: str = "", 557 attribute: t.Optional[t.Union[str, int]] = None, 558) -> str: 559 """Return a string which is the concatenation of the strings in the 560 sequence. The separator between elements is an empty string per 561 default, you can define it with the optional parameter: 562 563 .. sourcecode:: jinja 564 565 {{ [1, 2, 3]|join('|') }} 566 -> 1|2|3 567 568 {{ [1, 2, 3]|join }} 569 -> 123 570 571 It is also possible to join certain attributes of an object: 572 573 .. sourcecode:: jinja 574 575 {{ users|join(', ', attribute='username') }} 576 577 .. versionadded:: 2.6 578 The `attribute` parameter was added. 579 """ 580 if attribute is not None: 581 value = map(make_attrgetter(eval_ctx.environment, attribute), value) 582 583 # no automatic escaping? joining is a lot easier then 584 if not eval_ctx.autoescape: 585 return str(d).join(map(str, value)) 586 587 # if the delimiter doesn't have an html representation we check 588 # if any of the items has. If yes we do a coercion to Markup 589 if not hasattr(d, "__html__"): 590 value = list(value) 591 do_escape = False 592 593 for idx, item in enumerate(value): 594 if hasattr(item, "__html__"): 595 do_escape = True 596 else: 597 value[idx] = str(item) 598 599 if do_escape: 600 d = escape(d) 601 else: 602 d = str(d) 603 604 return d.join(value) 605 606 # no html involved, to normal joining 607 return soft_str(d).join(map(soft_str, value)) 608 609 610@async_variant(sync_do_join) # type: ignore 611async def do_join( 612 eval_ctx: "EvalContext", 613 value: t.Union[t.AsyncIterable, t.Iterable], 614 d: str = "", 615 attribute: t.Optional[t.Union[str, int]] = None, 616) -> str: 617 return sync_do_join(eval_ctx, await auto_to_list(value), d, attribute) 618 619 620def do_center(value: str, width: int = 80) -> str: 621 """Centers the value in a field of a given width.""" 622 return soft_str(value).center(width) 623 624 625@pass_environment 626def sync_do_first( 627 environment: "Environment", seq: "t.Iterable[V]" 628) -> "t.Union[V, Undefined]": 629 """Return the first item of a sequence.""" 630 try: 631 return next(iter(seq)) 632 except StopIteration: 633 return environment.undefined("No first item, sequence was empty.") 634 635 636@async_variant(sync_do_first) # type: ignore 637async def do_first( 638 environment: "Environment", seq: "t.Union[t.AsyncIterable[V], t.Iterable[V]]" 639) -> "t.Union[V, Undefined]": 640 try: 641 return await auto_aiter(seq).__anext__() 642 except StopAsyncIteration: 643 return environment.undefined("No first item, sequence was empty.") 644 645 646@pass_environment 647def do_last( 648 environment: "Environment", seq: "t.Reversible[V]" 649) -> "t.Union[V, Undefined]": 650 """Return the last item of a sequence. 651 652 Note: Does not work with generators. You may want to explicitly 653 convert it to a list: 654 655 .. sourcecode:: jinja 656 657 {{ data | selectattr('name', '==', 'Jinja') | list | last }} 658 """ 659 try: 660 return next(iter(reversed(seq))) 661 except StopIteration: 662 return environment.undefined("No last item, sequence was empty.") 663 664 665# No async do_last, it may not be safe in async mode. 666 667 668@pass_context 669def do_random(context: "Context", seq: "t.Sequence[V]") -> "t.Union[V, Undefined]": 670 """Return a random item from the sequence.""" 671 try: 672 return random.choice(seq) 673 except IndexError: 674 return context.environment.undefined("No random item, sequence was empty.") 675 676 677def do_filesizeformat(value: t.Union[str, float, int], binary: bool = False) -> str: 678 """Format the value like a 'human-readable' file size (i.e. 13 kB, 679 4.1 MB, 102 Bytes, etc). Per default decimal prefixes are used (Mega, 680 Giga, etc.), if the second parameter is set to `True` the binary 681 prefixes are used (Mebi, Gibi). 682 """ 683 bytes = float(value) 684 base = 1024 if binary else 1000 685 prefixes = [ 686 ("KiB" if binary else "kB"), 687 ("MiB" if binary else "MB"), 688 ("GiB" if binary else "GB"), 689 ("TiB" if binary else "TB"), 690 ("PiB" if binary else "PB"), 691 ("EiB" if binary else "EB"), 692 ("ZiB" if binary else "ZB"), 693 ("YiB" if binary else "YB"), 694 ] 695 696 if bytes == 1: 697 return "1 Byte" 698 elif bytes < base: 699 return f"{int(bytes)} Bytes" 700 else: 701 for i, prefix in enumerate(prefixes): 702 unit = base ** (i + 2) 703 704 if bytes < unit: 705 return f"{base * bytes / unit:.1f} {prefix}" 706 707 return f"{base * bytes / unit:.1f} {prefix}" 708 709 710def do_pprint(value: t.Any) -> str: 711 """Pretty print a variable. Useful for debugging.""" 712 return pformat(value) 713 714 715_uri_scheme_re = re.compile(r"^([\w.+-]{2,}:(/){0,2})$") 716 717 718@pass_eval_context 719def do_urlize( 720 eval_ctx: "EvalContext", 721 value: str, 722 trim_url_limit: t.Optional[int] = None, 723 nofollow: bool = False, 724 target: t.Optional[str] = None, 725 rel: t.Optional[str] = None, 726 extra_schemes: t.Optional[t.Iterable[str]] = None, 727) -> str: 728 """Convert URLs in text into clickable links. 729 730 This may not recognize links in some situations. Usually, a more 731 comprehensive formatter, such as a Markdown library, is a better 732 choice. 733 734 Works on ``http://``, ``https://``, ``www.``, ``mailto:``, and email 735 addresses. Links with trailing punctuation (periods, commas, closing 736 parentheses) and leading punctuation (opening parentheses) are 737 recognized excluding the punctuation. Email addresses that include 738 header fields are not recognized (for example, 739 ``mailto:address@example.com?cc=copy@example.com``). 740 741 :param value: Original text containing URLs to link. 742 :param trim_url_limit: Shorten displayed URL values to this length. 743 :param nofollow: Add the ``rel=nofollow`` attribute to links. 744 :param target: Add the ``target`` attribute to links. 745 :param rel: Add the ``rel`` attribute to links. 746 :param extra_schemes: Recognize URLs that start with these schemes 747 in addition to the default behavior. Defaults to 748 ``env.policies["urlize.extra_schemes"]``, which defaults to no 749 extra schemes. 750 751 .. versionchanged:: 3.0 752 The ``extra_schemes`` parameter was added. 753 754 .. versionchanged:: 3.0 755 Generate ``https://`` links for URLs without a scheme. 756 757 .. versionchanged:: 3.0 758 The parsing rules were updated. Recognize email addresses with 759 or without the ``mailto:`` scheme. Validate IP addresses. Ignore 760 parentheses and brackets in more cases. 761 762 .. versionchanged:: 2.8 763 The ``target`` parameter was added. 764 """ 765 policies = eval_ctx.environment.policies 766 rel_parts = set((rel or "").split()) 767 768 if nofollow: 769 rel_parts.add("nofollow") 770 771 rel_parts.update((policies["urlize.rel"] or "").split()) 772 rel = " ".join(sorted(rel_parts)) or None 773 774 if target is None: 775 target = policies["urlize.target"] 776 777 if extra_schemes is None: 778 extra_schemes = policies["urlize.extra_schemes"] or () 779 780 for scheme in extra_schemes: 781 if _uri_scheme_re.fullmatch(scheme) is None: 782 raise FilterArgumentError(f"{scheme!r} is not a valid URI scheme prefix.") 783 784 rv = urlize( 785 value, 786 trim_url_limit=trim_url_limit, 787 rel=rel, 788 target=target, 789 extra_schemes=extra_schemes, 790 ) 791 792 if eval_ctx.autoescape: 793 rv = Markup(rv) 794 795 return rv 796 797 798def do_indent( 799 s: str, width: t.Union[int, str] = 4, first: bool = False, blank: bool = False 800) -> str: 801 """Return a copy of the string with each line indented by 4 spaces. The 802 first line and blank lines are not indented by default. 803 804 :param width: Number of spaces, or a string, to indent by. 805 :param first: Don't skip indenting the first line. 806 :param blank: Don't skip indenting empty lines. 807 808 .. versionchanged:: 3.0 809 ``width`` can be a string. 810 811 .. versionchanged:: 2.10 812 Blank lines are not indented by default. 813 814 Rename the ``indentfirst`` argument to ``first``. 815 """ 816 if isinstance(width, str): 817 indention = width 818 else: 819 indention = " " * width 820 821 newline = "\n" 822 823 if isinstance(s, Markup): 824 indention = Markup(indention) 825 newline = Markup(newline) 826 827 s += newline # this quirk is necessary for splitlines method 828 829 if blank: 830 rv = (newline + indention).join(s.splitlines()) 831 else: 832 lines = s.splitlines() 833 rv = lines.pop(0) 834 835 if lines: 836 rv += newline + newline.join( 837 indention + line if line else line for line in lines 838 ) 839 840 if first: 841 rv = indention + rv 842 843 return rv 844 845 846@pass_environment 847def do_truncate( 848 env: "Environment", 849 s: str, 850 length: int = 255, 851 killwords: bool = False, 852 end: str = "...", 853 leeway: t.Optional[int] = None, 854) -> str: 855 """Return a truncated copy of the string. The length is specified 856 with the first parameter which defaults to ``255``. If the second 857 parameter is ``true`` the filter will cut the text at length. Otherwise 858 it will discard the last word. If the text was in fact 859 truncated it will append an ellipsis sign (``"..."``). If you want a 860 different ellipsis sign than ``"..."`` you can specify it using the 861 third parameter. Strings that only exceed the length by the tolerance 862 margin given in the fourth parameter will not be truncated. 863 864 .. sourcecode:: jinja 865 866 {{ "foo bar baz qux"|truncate(9) }} 867 -> "foo..." 868 {{ "foo bar baz qux"|truncate(9, True) }} 869 -> "foo ba..." 870 {{ "foo bar baz qux"|truncate(11) }} 871 -> "foo bar baz qux" 872 {{ "foo bar baz qux"|truncate(11, False, '...', 0) }} 873 -> "foo bar..." 874 875 The default leeway on newer Jinja versions is 5 and was 0 before but 876 can be reconfigured globally. 877 """ 878 if leeway is None: 879 leeway = env.policies["truncate.leeway"] 880 881 assert length >= len(end), f"expected length >= {len(end)}, got {length}" 882 assert leeway >= 0, f"expected leeway >= 0, got {leeway}" 883 884 if len(s) <= length + leeway: 885 return s 886 887 if killwords: 888 return s[: length - len(end)] + end 889 890 result = s[: length - len(end)].rsplit(" ", 1)[0] 891 return result + end 892 893 894@pass_environment 895def do_wordwrap( 896 environment: "Environment", 897 s: str, 898 width: int = 79, 899 break_long_words: bool = True, 900 wrapstring: t.Optional[str] = None, 901 break_on_hyphens: bool = True, 902) -> str: 903 """Wrap a string to the given width. Existing newlines are treated 904 as paragraphs to be wrapped separately. 905 906 :param s: Original text to wrap. 907 :param width: Maximum length of wrapped lines. 908 :param break_long_words: If a word is longer than ``width``, break 909 it across lines. 910 :param break_on_hyphens: If a word contains hyphens, it may be split 911 across lines. 912 :param wrapstring: String to join each wrapped line. Defaults to 913 :attr:`Environment.newline_sequence`. 914 915 .. versionchanged:: 2.11 916 Existing newlines are treated as paragraphs wrapped separately. 917 918 .. versionchanged:: 2.11 919 Added the ``break_on_hyphens`` parameter. 920 921 .. versionchanged:: 2.7 922 Added the ``wrapstring`` parameter. 923 """ 924 import textwrap 925 926 if wrapstring is None: 927 wrapstring = environment.newline_sequence 928 929 # textwrap.wrap doesn't consider existing newlines when wrapping. 930 # If the string has a newline before width, wrap will still insert 931 # a newline at width, resulting in a short line. Instead, split and 932 # wrap each paragraph individually. 933 return wrapstring.join( 934 [ 935 wrapstring.join( 936 textwrap.wrap( 937 line, 938 width=width, 939 expand_tabs=False, 940 replace_whitespace=False, 941 break_long_words=break_long_words, 942 break_on_hyphens=break_on_hyphens, 943 ) 944 ) 945 for line in s.splitlines() 946 ] 947 ) 948 949 950_word_re = re.compile(r"\w+") 951 952 953def do_wordcount(s: str) -> int: 954 """Count the words in that string.""" 955 return len(_word_re.findall(soft_str(s))) 956 957 958def do_int(value: t.Any, default: int = 0, base: int = 10) -> int: 959 """Convert the value into an integer. If the 960 conversion doesn't work it will return ``0``. You can 961 override this default using the first parameter. You 962 can also override the default base (10) in the second 963 parameter, which handles input with prefixes such as 964 0b, 0o and 0x for bases 2, 8 and 16 respectively. 965 The base is ignored for decimal numbers and non-string values. 966 """ 967 try: 968 if isinstance(value, str): 969 return int(value, base) 970 971 return int(value) 972 except (TypeError, ValueError): 973 # this quirk is necessary so that "42.23"|int gives 42. 974 try: 975 return int(float(value)) 976 except (TypeError, ValueError): 977 return default 978 979 980def do_float(value: t.Any, default: float = 0.0) -> float: 981 """Convert the value into a floating point number. If the 982 conversion doesn't work it will return ``0.0``. You can 983 override this default using the first parameter. 984 """ 985 try: 986 return float(value) 987 except (TypeError, ValueError): 988 return default 989 990 991def do_format(value: str, *args: t.Any, **kwargs: t.Any) -> str: 992 """Apply the given values to a `printf-style`_ format string, like 993 ``string % values``. 994 995 .. sourcecode:: jinja 996 997 {{ "%s, %s!"|format(greeting, name) }} 998 Hello, World! 999 1000 In most cases it should be more convenient and efficient to use the 1001 ``%`` operator or :meth:`str.format`. 1002 1003 .. code-block:: text 1004 1005 {{ "%s, %s!" % (greeting, name) }} 1006 {{ "{}, {}!".format(greeting, name) }} 1007 1008 .. _printf-style: https://docs.python.org/library/stdtypes.html 1009 #printf-style-string-formatting 1010 """ 1011 if args and kwargs: 1012 raise FilterArgumentError( 1013 "can't handle positional and keyword arguments at the same time" 1014 ) 1015 1016 return soft_str(value) % (kwargs or args) 1017 1018 1019def do_trim(value: str, chars: t.Optional[str] = None) -> str: 1020 """Strip leading and trailing characters, by default whitespace.""" 1021 return soft_str(value).strip(chars) 1022 1023 1024def do_striptags(value: "t.Union[str, HasHTML]") -> str: 1025 """Strip SGML/XML tags and replace adjacent whitespace by one space.""" 1026 if hasattr(value, "__html__"): 1027 value = t.cast("HasHTML", value).__html__() 1028 1029 return Markup(str(value)).striptags() 1030 1031 1032def sync_do_slice( 1033 value: "t.Collection[V]", slices: int, fill_with: "t.Optional[V]" = None 1034) -> "t.Iterator[t.List[V]]": 1035 """Slice an iterator and return a list of lists containing 1036 those items. Useful if you want to create a div containing 1037 three ul tags that represent columns: 1038 1039 .. sourcecode:: html+jinja 1040 1041 <div class="columnwrapper"> 1042 {%- for column in items|slice(3) %} 1043 <ul class="column-{{ loop.index }}"> 1044 {%- for item in column %} 1045 <li>{{ item }}</li> 1046 {%- endfor %} 1047 </ul> 1048 {%- endfor %} 1049 </div> 1050 1051 If you pass it a second argument it's used to fill missing 1052 values on the last iteration. 1053 """ 1054 seq = list(value) 1055 length = len(seq) 1056 items_per_slice = length // slices 1057 slices_with_extra = length % slices 1058 offset = 0 1059 1060 for slice_number in range(slices): 1061 start = offset + slice_number * items_per_slice 1062 1063 if slice_number < slices_with_extra: 1064 offset += 1 1065 1066 end = offset + (slice_number + 1) * items_per_slice 1067 tmp = seq[start:end] 1068 1069 if fill_with is not None and slice_number >= slices_with_extra: 1070 tmp.append(fill_with) 1071 1072 yield tmp 1073 1074 1075@async_variant(sync_do_slice) # type: ignore 1076async def do_slice( 1077 value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", 1078 slices: int, 1079 fill_with: t.Optional[t.Any] = None, 1080) -> "t.Iterator[t.List[V]]": 1081 return sync_do_slice(await auto_to_list(value), slices, fill_with) 1082 1083 1084def do_batch( 1085 value: "t.Iterable[V]", linecount: int, fill_with: "t.Optional[V]" = None 1086) -> "t.Iterator[t.List[V]]": 1087 """ 1088 A filter that batches items. It works pretty much like `slice` 1089 just the other way round. It returns a list of lists with the 1090 given number of items. If you provide a second parameter this 1091 is used to fill up missing items. See this example: 1092 1093 .. sourcecode:: html+jinja 1094 1095 <table> 1096 {%- for row in items|batch(3, ' ') %} 1097 <tr> 1098 {%- for column in row %} 1099 <td>{{ column }}</td> 1100 {%- endfor %} 1101 </tr> 1102 {%- endfor %} 1103 </table> 1104 """ 1105 tmp: "t.List[V]" = [] 1106 1107 for item in value: 1108 if len(tmp) == linecount: 1109 yield tmp 1110 tmp = [] 1111 1112 tmp.append(item) 1113 1114 if tmp: 1115 if fill_with is not None and len(tmp) < linecount: 1116 tmp += [fill_with] * (linecount - len(tmp)) 1117 1118 yield tmp 1119 1120 1121def do_round( 1122 value: float, 1123 precision: int = 0, 1124 method: 'te.Literal["common", "ceil", "floor"]' = "common", 1125) -> float: 1126 """Round the number to a given precision. The first 1127 parameter specifies the precision (default is ``0``), the 1128 second the rounding method: 1129 1130 - ``'common'`` rounds either up or down 1131 - ``'ceil'`` always rounds up 1132 - ``'floor'`` always rounds down 1133 1134 If you don't specify a method ``'common'`` is used. 1135 1136 .. sourcecode:: jinja 1137 1138 {{ 42.55|round }} 1139 -> 43.0 1140 {{ 42.55|round(1, 'floor') }} 1141 -> 42.5 1142 1143 Note that even if rounded to 0 precision, a float is returned. If 1144 you need a real integer, pipe it through `int`: 1145 1146 .. sourcecode:: jinja 1147 1148 {{ 42.55|round|int }} 1149 -> 43 1150 """ 1151 if method not in {"common", "ceil", "floor"}: 1152 raise FilterArgumentError("method must be common, ceil or floor") 1153 1154 if method == "common": 1155 return round(value, precision) 1156 1157 func = getattr(math, method) 1158 return t.cast(float, func(value * (10**precision)) / (10**precision)) 1159 1160 1161class _GroupTuple(t.NamedTuple): 1162 grouper: t.Any 1163 list: t.List 1164 1165 # Use the regular tuple repr to hide this subclass if users print 1166 # out the value during debugging. 1167 def __repr__(self) -> str: 1168 return tuple.__repr__(self) 1169 1170 def __str__(self) -> str: 1171 return tuple.__str__(self) 1172 1173 1174@pass_environment 1175def sync_do_groupby( 1176 environment: "Environment", 1177 value: "t.Iterable[V]", 1178 attribute: t.Union[str, int], 1179 default: t.Optional[t.Any] = None, 1180 case_sensitive: bool = False, 1181) -> "t.List[_GroupTuple]": 1182 """Group a sequence of objects by an attribute using Python's 1183 :func:`itertools.groupby`. The attribute can use dot notation for 1184 nested access, like ``"address.city"``. Unlike Python's ``groupby``, 1185 the values are sorted first so only one group is returned for each 1186 unique value. 1187 1188 For example, a list of ``User`` objects with a ``city`` attribute 1189 can be rendered in groups. In this example, ``grouper`` refers to 1190 the ``city`` value of the group. 1191 1192 .. sourcecode:: html+jinja 1193 1194 <ul>{% for city, items in users|groupby("city") %} 1195 <li>{{ city }} 1196 <ul>{% for user in items %} 1197 <li>{{ user.name }} 1198 {% endfor %}</ul> 1199 </li> 1200 {% endfor %}</ul> 1201 1202 ``groupby`` yields namedtuples of ``(grouper, list)``, which 1203 can be used instead of the tuple unpacking above. ``grouper`` is the 1204 value of the attribute, and ``list`` is the items with that value. 1205 1206 .. sourcecode:: html+jinja 1207 1208 <ul>{% for group in users|groupby("city") %} 1209 <li>{{ group.grouper }}: {{ group.list|join(", ") }} 1210 {% endfor %}</ul> 1211 1212 You can specify a ``default`` value to use if an object in the list 1213 does not have the given attribute. 1214 1215 .. sourcecode:: jinja 1216 1217 <ul>{% for city, items in users|groupby("city", default="NY") %} 1218 <li>{{ city }}: {{ items|map(attribute="name")|join(", ") }}</li> 1219 {% endfor %}</ul> 1220 1221 Like the :func:`~jinja-filters.sort` filter, sorting and grouping is 1222 case-insensitive by default. The ``key`` for each group will have 1223 the case of the first item in that group of values. For example, if 1224 a list of users has cities ``["CA", "NY", "ca"]``, the "CA" group 1225 will have two values. This can be disabled by passing 1226 ``case_sensitive=True``. 1227 1228 .. versionchanged:: 3.1 1229 Added the ``case_sensitive`` parameter. Sorting and grouping is 1230 case-insensitive by default, matching other filters that do 1231 comparisons. 1232 1233 .. versionchanged:: 3.0 1234 Added the ``default`` parameter. 1235 1236 .. versionchanged:: 2.6 1237 The attribute supports dot notation for nested access. 1238 """ 1239 expr = make_attrgetter( 1240 environment, 1241 attribute, 1242 postprocess=ignore_case if not case_sensitive else None, 1243 default=default, 1244 ) 1245 out = [ 1246 _GroupTuple(key, list(values)) 1247 for key, values in groupby(sorted(value, key=expr), expr) 1248 ] 1249 1250 if not case_sensitive: 1251 # Return the real key from the first value instead of the lowercase key. 1252 output_expr = make_attrgetter(environment, attribute, default=default) 1253 out = [_GroupTuple(output_expr(values[0]), values) for _, values in out] 1254 1255 return out 1256 1257 1258@async_variant(sync_do_groupby) # type: ignore 1259async def do_groupby( 1260 environment: "Environment", 1261 value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", 1262 attribute: t.Union[str, int], 1263 default: t.Optional[t.Any] = None, 1264 case_sensitive: bool = False, 1265) -> "t.List[_GroupTuple]": 1266 expr = make_attrgetter( 1267 environment, 1268 attribute, 1269 postprocess=ignore_case if not case_sensitive else None, 1270 default=default, 1271 ) 1272 out = [ 1273 _GroupTuple(key, await auto_to_list(values)) 1274 for key, values in groupby(sorted(await auto_to_list(value), key=expr), expr) 1275 ] 1276 1277 if not case_sensitive: 1278 # Return the real key from the first value instead of the lowercase key. 1279 output_expr = make_attrgetter(environment, attribute, default=default) 1280 out = [_GroupTuple(output_expr(values[0]), values) for _, values in out] 1281 1282 return out 1283 1284 1285@pass_environment 1286def sync_do_sum( 1287 environment: "Environment", 1288 iterable: "t.Iterable[V]", 1289 attribute: t.Optional[t.Union[str, int]] = None, 1290 start: V = 0, # type: ignore 1291) -> V: 1292 """Returns the sum of a sequence of numbers plus the value of parameter 1293 'start' (which defaults to 0). When the sequence is empty it returns 1294 start. 1295 1296 It is also possible to sum up only certain attributes: 1297 1298 .. sourcecode:: jinja 1299 1300 Total: {{ items|sum(attribute='price') }} 1301 1302 .. versionchanged:: 2.6 1303 The ``attribute`` parameter was added to allow summing up over 1304 attributes. Also the ``start`` parameter was moved on to the right. 1305 """ 1306 if attribute is not None: 1307 iterable = map(make_attrgetter(environment, attribute), iterable) 1308 1309 return sum(iterable, start) # type: ignore[no-any-return, call-overload] 1310 1311 1312@async_variant(sync_do_sum) # type: ignore 1313async def do_sum( 1314 environment: "Environment", 1315 iterable: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", 1316 attribute: t.Optional[t.Union[str, int]] = None, 1317 start: V = 0, # type: ignore 1318) -> V: 1319 rv = start 1320 1321 if attribute is not None: 1322 func = make_attrgetter(environment, attribute) 1323 else: 1324 1325 def func(x: V) -> V: 1326 return x 1327 1328 async for item in auto_aiter(iterable): 1329 rv += func(item) 1330 1331 return rv 1332 1333 1334def sync_do_list(value: "t.Iterable[V]") -> "t.List[V]": 1335 """Convert the value into a list. If it was a string the returned list 1336 will be a list of characters. 1337 """ 1338 return list(value) 1339 1340 1341@async_variant(sync_do_list) # type: ignore 1342async def do_list(value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]") -> "t.List[V]": 1343 return await auto_to_list(value) 1344 1345 1346def do_mark_safe(value: str) -> Markup: 1347 """Mark the value as safe which means that in an environment with automatic 1348 escaping enabled this variable will not be escaped. 1349 """ 1350 return Markup(value) 1351 1352 1353def do_mark_unsafe(value: str) -> str: 1354 """Mark a value as unsafe. This is the reverse operation for :func:`safe`.""" 1355 return str(value) 1356 1357 1358@typing.overload 1359def do_reverse(value: str) -> str: 1360 ... 1361 1362 1363@typing.overload 1364def do_reverse(value: "t.Iterable[V]") -> "t.Iterable[V]": 1365 ... 1366 1367 1368def do_reverse(value: t.Union[str, t.Iterable[V]]) -> t.Union[str, t.Iterable[V]]: 1369 """Reverse the object or return an iterator that iterates over it the other 1370 way round. 1371 """ 1372 if isinstance(value, str): 1373 return value[::-1] 1374 1375 try: 1376 return reversed(value) # type: ignore 1377 except TypeError: 1378 try: 1379 rv = list(value) 1380 rv.reverse() 1381 return rv 1382 except TypeError as e: 1383 raise FilterArgumentError("argument must be iterable") from e 1384 1385 1386@pass_environment 1387def do_attr( 1388 environment: "Environment", obj: t.Any, name: str 1389) -> t.Union[Undefined, t.Any]: 1390 """Get an attribute of an object. ``foo|attr("bar")`` works like 1391 ``foo.bar`` just that always an attribute is returned and items are not 1392 looked up. 1393 1394 See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details. 1395 """ 1396 try: 1397 name = str(name) 1398 except UnicodeError: 1399 pass 1400 else: 1401 try: 1402 value = getattr(obj, name) 1403 except AttributeError: 1404 pass 1405 else: 1406 if environment.sandboxed: 1407 environment = t.cast("SandboxedEnvironment", environment) 1408 1409 if not environment.is_safe_attribute(obj, name, value): 1410 return environment.unsafe_undefined(obj, name) 1411 1412 return value 1413 1414 return environment.undefined(obj=obj, name=name) 1415 1416 1417@typing.overload 1418def sync_do_map( 1419 context: "Context", value: t.Iterable, name: str, *args: t.Any, **kwargs: t.Any 1420) -> t.Iterable: 1421 ... 1422 1423 1424@typing.overload 1425def sync_do_map( 1426 context: "Context", 1427 value: t.Iterable, 1428 *, 1429 attribute: str = ..., 1430 default: t.Optional[t.Any] = None, 1431) -> t.Iterable: 1432 ... 1433 1434 1435@pass_context 1436def sync_do_map( 1437 context: "Context", value: t.Iterable, *args: t.Any, **kwargs: t.Any 1438) -> t.Iterable: 1439 """Applies a filter on a sequence of objects or looks up an attribute. 1440 This is useful when dealing with lists of objects but you are really 1441 only interested in a certain value of it. 1442 1443 The basic usage is mapping on an attribute. Imagine you have a list 1444 of users but you are only interested in a list of usernames: 1445 1446 .. sourcecode:: jinja 1447 1448 Users on this page: {{ users|map(attribute='username')|join(', ') }} 1449 1450 You can specify a ``default`` value to use if an object in the list 1451 does not have the given attribute. 1452 1453 .. sourcecode:: jinja 1454 1455 {{ users|map(attribute="username", default="Anonymous")|join(", ") }} 1456 1457 Alternatively you can let it invoke a filter by passing the name of the 1458 filter and the arguments afterwards. A good example would be applying a 1459 text conversion filter on a sequence: 1460 1461 .. sourcecode:: jinja 1462 1463 Users on this page: {{ titles|map('lower')|join(', ') }} 1464 1465 Similar to a generator comprehension such as: 1466 1467 .. code-block:: python 1468 1469 (u.username for u in users) 1470 (getattr(u, "username", "Anonymous") for u in users) 1471 (do_lower(x) for x in titles) 1472 1473 .. versionchanged:: 2.11.0 1474 Added the ``default`` parameter. 1475 1476 .. versionadded:: 2.7 1477 """ 1478 if value: 1479 func = prepare_map(context, args, kwargs) 1480 1481 for item in value: 1482 yield func(item) 1483 1484 1485@typing.overload 1486def do_map( 1487 context: "Context", 1488 value: t.Union[t.AsyncIterable, t.Iterable], 1489 name: str, 1490 *args: t.Any, 1491 **kwargs: t.Any, 1492) -> t.Iterable: 1493 ... 1494 1495 1496@typing.overload 1497def do_map( 1498 context: "Context", 1499 value: t.Union[t.AsyncIterable, t.Iterable], 1500 *, 1501 attribute: str = ..., 1502 default: t.Optional[t.Any] = None, 1503) -> t.Iterable: 1504 ... 1505 1506 1507@async_variant(sync_do_map) # type: ignore 1508async def do_map( 1509 context: "Context", 1510 value: t.Union[t.AsyncIterable, t.Iterable], 1511 *args: t.Any, 1512 **kwargs: t.Any, 1513) -> t.AsyncIterable: 1514 if value: 1515 func = prepare_map(context, args, kwargs) 1516 1517 async for item in auto_aiter(value): 1518 yield await auto_await(func(item)) 1519 1520 1521@pass_context 1522def sync_do_select( 1523 context: "Context", value: "t.Iterable[V]", *args: t.Any, **kwargs: t.Any 1524) -> "t.Iterator[V]": 1525 """Filters a sequence of objects by applying a test to each object, 1526 and only selecting the objects with the test succeeding. 1527 1528 If no test is specified, each object will be evaluated as a boolean. 1529 1530 Example usage: 1531 1532 .. sourcecode:: jinja 1533 1534 {{ numbers|select("odd") }} 1535 {{ numbers|select("odd") }} 1536 {{ numbers|select("divisibleby", 3) }} 1537 {{ numbers|select("lessthan", 42) }} 1538 {{ strings|select("equalto", "mystring") }} 1539 1540 Similar to a generator comprehension such as: 1541 1542 .. code-block:: python 1543 1544 (n for n in numbers if test_odd(n)) 1545 (n for n in numbers if test_divisibleby(n, 3)) 1546 1547 .. versionadded:: 2.7 1548 """ 1549 return select_or_reject(context, value, args, kwargs, lambda x: x, False) 1550 1551 1552@async_variant(sync_do_select) # type: ignore 1553async def do_select( 1554 context: "Context", 1555 value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", 1556 *args: t.Any, 1557 **kwargs: t.Any, 1558) -> "t.AsyncIterator[V]": 1559 return async_select_or_reject(context, value, args, kwargs, lambda x: x, False) 1560 1561 1562@pass_context 1563def sync_do_reject( 1564 context: "Context", value: "t.Iterable[V]", *args: t.Any, **kwargs: t.Any 1565) -> "t.Iterator[V]": 1566 """Filters a sequence of objects by applying a test to each object, 1567 and rejecting the objects with the test succeeding. 1568 1569 If no test is specified, each object will be evaluated as a boolean. 1570 1571 Example usage: 1572 1573 .. sourcecode:: jinja 1574 1575 {{ numbers|reject("odd") }} 1576 1577 Similar to a generator comprehension such as: 1578 1579 .. code-block:: python 1580 1581 (n for n in numbers if not test_odd(n)) 1582 1583 .. versionadded:: 2.7 1584 """ 1585 return select_or_reject(context, value, args, kwargs, lambda x: not x, False) 1586 1587 1588@async_variant(sync_do_reject) # type: ignore 1589async def do_reject( 1590 context: "Context", 1591 value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", 1592 *args: t.Any, 1593 **kwargs: t.Any, 1594) -> "t.AsyncIterator[V]": 1595 return async_select_or_reject(context, value, args, kwargs, lambda x: not x, False) 1596 1597 1598@pass_context 1599def sync_do_selectattr( 1600 context: "Context", value: "t.Iterable[V]", *args: t.Any, **kwargs: t.Any 1601) -> "t.Iterator[V]": 1602 """Filters a sequence of objects by applying a test to the specified 1603 attribute of each object, and only selecting the objects with the 1604 test succeeding. 1605 1606 If no test is specified, the attribute's value will be evaluated as 1607 a boolean. 1608 1609 Example usage: 1610 1611 .. sourcecode:: jinja 1612 1613 {{ users|selectattr("is_active") }} 1614 {{ users|selectattr("email", "none") }} 1615 1616 Similar to a generator comprehension such as: 1617 1618 .. code-block:: python 1619 1620 (u for user in users if user.is_active) 1621 (u for user in users if test_none(user.email)) 1622 1623 .. versionadded:: 2.7 1624 """ 1625 return select_or_reject(context, value, args, kwargs, lambda x: x, True) 1626 1627 1628@async_variant(sync_do_selectattr) # type: ignore 1629async def do_selectattr( 1630 context: "Context", 1631 value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", 1632 *args: t.Any, 1633 **kwargs: t.Any, 1634) -> "t.AsyncIterator[V]": 1635 return async_select_or_reject(context, value, args, kwargs, lambda x: x, True) 1636 1637 1638@pass_context 1639def sync_do_rejectattr( 1640 context: "Context", value: "t.Iterable[V]", *args: t.Any, **kwargs: t.Any 1641) -> "t.Iterator[V]": 1642 """Filters a sequence of objects by applying a test to the specified 1643 attribute of each object, and rejecting the objects with the test 1644 succeeding. 1645 1646 If no test is specified, the attribute's value will be evaluated as 1647 a boolean. 1648 1649 .. sourcecode:: jinja 1650 1651 {{ users|rejectattr("is_active") }} 1652 {{ users|rejectattr("email", "none") }} 1653 1654 Similar to a generator comprehension such as: 1655 1656 .. code-block:: python 1657 1658 (u for user in users if not user.is_active) 1659 (u for user in users if not test_none(user.email)) 1660 1661 .. versionadded:: 2.7 1662 """ 1663 return select_or_reject(context, value, args, kwargs, lambda x: not x, True) 1664 1665 1666@async_variant(sync_do_rejectattr) # type: ignore 1667async def do_rejectattr( 1668 context: "Context", 1669 value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", 1670 *args: t.Any, 1671 **kwargs: t.Any, 1672) -> "t.AsyncIterator[V]": 1673 return async_select_or_reject(context, value, args, kwargs, lambda x: not x, True) 1674 1675 1676@pass_eval_context 1677def do_tojson( 1678 eval_ctx: "EvalContext", value: t.Any, indent: t.Optional[int] = None 1679) -> Markup: 1680 """Serialize an object to a string of JSON, and mark it safe to 1681 render in HTML. This filter is only for use in HTML documents. 1682 1683 The returned string is safe to render in HTML documents and 1684 ``<script>`` tags. The exception is in HTML attributes that are 1685 double quoted; either use single quotes or the ``|forceescape`` 1686 filter. 1687 1688 :param value: The object to serialize to JSON. 1689 :param indent: The ``indent`` parameter passed to ``dumps``, for 1690 pretty-printing the value. 1691 1692 .. versionadded:: 2.9 1693 """ 1694 policies = eval_ctx.environment.policies 1695 dumps = policies["json.dumps_function"] 1696 kwargs = policies["json.dumps_kwargs"] 1697 1698 if indent is not None: 1699 kwargs = kwargs.copy() 1700 kwargs["indent"] = indent 1701 1702 return htmlsafe_json_dumps(value, dumps=dumps, **kwargs) 1703 1704 1705def prepare_map( 1706 context: "Context", args: t.Tuple, kwargs: t.Dict[str, t.Any] 1707) -> t.Callable[[t.Any], t.Any]: 1708 if not args and "attribute" in kwargs: 1709 attribute = kwargs.pop("attribute") 1710 default = kwargs.pop("default", None) 1711 1712 if kwargs: 1713 raise FilterArgumentError( 1714 f"Unexpected keyword argument {next(iter(kwargs))!r}" 1715 ) 1716 1717 func = make_attrgetter(context.environment, attribute, default=default) 1718 else: 1719 try: 1720 name = args[0] 1721 args = args[1:] 1722 except LookupError: 1723 raise FilterArgumentError("map requires a filter argument") from None 1724 1725 def func(item: t.Any) -> t.Any: 1726 return context.environment.call_filter( 1727 name, item, args, kwargs, context=context 1728 ) 1729 1730 return func 1731 1732 1733def prepare_select_or_reject( 1734 context: "Context", 1735 args: t.Tuple, 1736 kwargs: t.Dict[str, t.Any], 1737 modfunc: t.Callable[[t.Any], t.Any], 1738 lookup_attr: bool, 1739) -> t.Callable[[t.Any], t.Any]: 1740 if lookup_attr: 1741 try: 1742 attr = args[0] 1743 except LookupError: 1744 raise FilterArgumentError("Missing parameter for attribute name") from None 1745 1746 transfunc = make_attrgetter(context.environment, attr) 1747 off = 1 1748 else: 1749 off = 0 1750 1751 def transfunc(x: V) -> V: 1752 return x 1753 1754 try: 1755 name = args[off] 1756 args = args[1 + off :] 1757 1758 def func(item: t.Any) -> t.Any: 1759 return context.environment.call_test(name, item, args, kwargs) 1760 1761 except LookupError: 1762 func = bool # type: ignore 1763 1764 return lambda item: modfunc(func(transfunc(item))) 1765 1766 1767def select_or_reject( 1768 context: "Context", 1769 value: "t.Iterable[V]", 1770 args: t.Tuple, 1771 kwargs: t.Dict[str, t.Any], 1772 modfunc: t.Callable[[t.Any], t.Any], 1773 lookup_attr: bool, 1774) -> "t.Iterator[V]": 1775 if value: 1776 func = prepare_select_or_reject(context, args, kwargs, modfunc, lookup_attr) 1777 1778 for item in value: 1779 if func(item): 1780 yield item 1781 1782 1783async def async_select_or_reject( 1784 context: "Context", 1785 value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", 1786 args: t.Tuple, 1787 kwargs: t.Dict[str, t.Any], 1788 modfunc: t.Callable[[t.Any], t.Any], 1789 lookup_attr: bool, 1790) -> "t.AsyncIterator[V]": 1791 if value: 1792 func = prepare_select_or_reject(context, args, kwargs, modfunc, lookup_attr) 1793 1794 async for item in auto_aiter(value): 1795 if func(item): 1796 yield item 1797 1798 1799FILTERS = { 1800 "abs": abs, 1801 "attr": do_attr, 1802 "batch": do_batch, 1803 "capitalize": do_capitalize, 1804 "center": do_center, 1805 "count": len, 1806 "d": do_default, 1807 "default": do_default, 1808 "dictsort": do_dictsort, 1809 "e": escape, 1810 "escape": escape, 1811 "filesizeformat": do_filesizeformat, 1812 "first": do_first, 1813 "float": do_float, 1814 "forceescape": do_forceescape, 1815 "format": do_format, 1816 "groupby": do_groupby, 1817 "indent": do_indent, 1818 "int": do_int, 1819 "join": do_join, 1820 "last": do_last, 1821 "length": len, 1822 "list": do_list, 1823 "lower": do_lower, 1824 "items": do_items, 1825 "map": do_map, 1826 "min": do_min, 1827 "max": do_max, 1828 "pprint": do_pprint, 1829 "random": do_random, 1830 "reject": do_reject, 1831 "rejectattr": do_rejectattr, 1832 "replace": do_replace, 1833 "reverse": do_reverse, 1834 "round": do_round, 1835 "safe": do_mark_safe, 1836 "select": do_select, 1837 "selectattr": do_selectattr, 1838 "slice": do_slice, 1839 "sort": do_sort, 1840 "string": soft_str, 1841 "striptags": do_striptags, 1842 "sum": do_sum, 1843 "title": do_title, 1844 "trim": do_trim, 1845 "truncate": do_truncate, 1846 "unique": do_unique, 1847 "upper": do_upper, 1848 "urlencode": do_urlencode, 1849 "urlize": do_urlize, 1850 "wordcount": do_wordcount, 1851 "wordwrap": do_wordwrap, 1852 "xmlattr": do_xmlattr, 1853 "tojson": do_tojson, 1854}
47def ignore_case(value: V) -> V: 48 """For use as a postprocessor for :func:`make_attrgetter`. Converts strings 49 to lowercase and returns other types as-is.""" 50 if isinstance(value, str): 51 return t.cast(V, value.lower()) 52 53 return value
For use as a postprocessor for make_attrgetter(). Converts strings
to lowercase and returns other types as-is.
56def make_attrgetter( 57 environment: "Environment", 58 attribute: t.Optional[t.Union[str, int]], 59 postprocess: t.Optional[t.Callable[[t.Any], t.Any]] = None, 60 default: t.Optional[t.Any] = None, 61) -> t.Callable[[t.Any], t.Any]: 62 """Returns a callable that looks up the given attribute from a 63 passed object with the rules of the environment. Dots are allowed 64 to access attributes of attributes. Integer parts in paths are 65 looked up as integers. 66 """ 67 parts = _prepare_attribute_parts(attribute) 68 69 def attrgetter(item: t.Any) -> t.Any: 70 for part in parts: 71 item = environment.getitem(item, part) 72 73 if default is not None and isinstance(item, Undefined): 74 item = default 75 76 if postprocess is not None: 77 item = postprocess(item) 78 79 return item 80 81 return attrgetter
Returns a callable that looks up the given attribute from a passed object with the rules of the environment. Dots are allowed to access attributes of attributes. Integer parts in paths are looked up as integers.
84def make_multi_attrgetter( 85 environment: "Environment", 86 attribute: t.Optional[t.Union[str, int]], 87 postprocess: t.Optional[t.Callable[[t.Any], t.Any]] = None, 88) -> t.Callable[[t.Any], t.List[t.Any]]: 89 """Returns a callable that looks up the given comma separated 90 attributes from a passed object with the rules of the environment. 91 Dots are allowed to access attributes of each attribute. Integer 92 parts in paths are looked up as integers. 93 94 The value returned by the returned callable is a list of extracted 95 attribute values. 96 97 Examples of attribute: "attr1,attr2", "attr1.inner1.0,attr2.inner2.0", etc. 98 """ 99 if isinstance(attribute, str): 100 split: t.Sequence[t.Union[str, int, None]] = attribute.split(",") 101 else: 102 split = [attribute] 103 104 parts = [_prepare_attribute_parts(item) for item in split] 105 106 def attrgetter(item: t.Any) -> t.List[t.Any]: 107 items = [None] * len(parts) 108 109 for i, attribute_part in enumerate(parts): 110 item_i = item 111 112 for part in attribute_part: 113 item_i = environment.getitem(item_i, part) 114 115 if postprocess is not None: 116 item_i = postprocess(item_i) 117 118 items[i] = item_i 119 120 return items 121 122 return attrgetter
Returns a callable that looks up the given comma separated attributes from a passed object with the rules of the environment. Dots are allowed to access attributes of each attribute. Integer parts in paths are looked up as integers.
The value returned by the returned callable is a list of extracted attribute values.
Examples of attribute: "attr1,attr2", "attr1.inner1.0,attr2.inner2.0", etc.
137def do_forceescape(value: "t.Union[str, HasHTML]") -> Markup: 138 """Enforce HTML escaping. This will probably double escape variables.""" 139 if hasattr(value, "__html__"): 140 value = t.cast("HasHTML", value).__html__() 141 142 return escape(str(value))
Enforce HTML escaping. This will probably double escape variables.
145def do_urlencode( 146 value: t.Union[str, t.Mapping[str, t.Any], t.Iterable[t.Tuple[str, t.Any]]] 147) -> str: 148 """Quote data for use in a URL path or query using UTF-8. 149 150 Basic wrapper around :func:`urllib.parse.quote` when given a 151 string, or :func:`urllib.parse.urlencode` for a dict or iterable. 152 153 :param value: Data to quote. A string will be quoted directly. A 154 dict or iterable of ``(key, value)`` pairs will be joined as a 155 query string. 156 157 When given a string, "/" is not quoted. HTTP servers treat "/" and 158 "%2F" equivalently in paths. If you need quoted slashes, use the 159 ``|replace("/", "%2F")`` filter. 160 161 .. versionadded:: 2.7 162 """ 163 if isinstance(value, str) or not isinstance(value, abc.Iterable): 164 return url_quote(value) 165 166 if isinstance(value, dict): 167 items: t.Iterable[t.Tuple[str, t.Any]] = value.items() 168 else: 169 items = value # type: ignore 170 171 return "&".join( 172 f"{url_quote(k, for_qs=True)}={url_quote(v, for_qs=True)}" for k, v in items 173 )
Quote data for use in a URL path or query using UTF-8.
Basic wrapper around urllib.parse.quote() when given a
string, or urllib.parse.urlencode() for a dict or iterable.
Parameters
- value: Data to quote. A string will be quoted directly. A
dict or iterable of
(key, value)pairs will be joined as a query string.
When given a string, "/" is not quoted. HTTP servers treat "/" and
"%2F" equivalently in paths. If you need quoted slashes, use the
|replace("/", "%2F") filter.
New in version 2.7.
176@pass_eval_context 177def do_replace( 178 eval_ctx: "EvalContext", s: str, old: str, new: str, count: t.Optional[int] = None 179) -> str: 180 """Return a copy of the value with all occurrences of a substring 181 replaced with a new one. The first argument is the substring 182 that should be replaced, the second is the replacement string. 183 If the optional third argument ``count`` is given, only the first 184 ``count`` occurrences are replaced: 185 186 .. sourcecode:: jinja 187 188 {{ "Hello World"|replace("Hello", "Goodbye") }} 189 -> Goodbye World 190 191 {{ "aaaaargh"|replace("a", "d'oh, ", 2) }} 192 -> d'oh, d'oh, aaargh 193 """ 194 if count is None: 195 count = -1 196 197 if not eval_ctx.autoescape: 198 return str(s).replace(str(old), str(new), count) 199 200 if ( 201 hasattr(old, "__html__") 202 or hasattr(new, "__html__") 203 and not hasattr(s, "__html__") 204 ): 205 s = escape(s) 206 else: 207 s = soft_str(s) 208 209 return s.replace(soft_str(old), soft_str(new), count)
Return a copy of the value with all occurrences of a substring
replaced with a new one. The first argument is the substring
that should be replaced, the second is the replacement string.
If the optional third argument count is given, only the first
count occurrences are replaced:
.. sourcecode:: jinja
{{ "Hello World"|replace("Hello", "Goodbye") }}
-> Goodbye World
{{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
-> d'oh, d'oh, aaargh
212def do_upper(s: str) -> str: 213 """Convert a value to uppercase.""" 214 return soft_str(s).upper()
Convert a value to uppercase.
217def do_lower(s: str) -> str: 218 """Convert a value to lowercase.""" 219 return soft_str(s).lower()
Convert a value to lowercase.
222def do_items(value: t.Union[t.Mapping[K, V], Undefined]) -> t.Iterator[t.Tuple[K, V]]: 223 """Return an iterator over the ``(key, value)`` items of a mapping. 224 225 ``x|items`` is the same as ``x.items()``, except if ``x`` is 226 undefined an empty iterator is returned. 227 228 This filter is useful if you expect the template to be rendered with 229 an implementation of Jinja in another programming language that does 230 not have a ``.items()`` method on its mapping type. 231 232 .. code-block:: html+jinja 233 234 <dl> 235 {% for key, value in my_dict|items %} 236 <dt>{{ key }} 237 <dd>{{ value }} 238 {% endfor %} 239 </dl> 240 241 .. versionadded:: 3.1 242 """ 243 if isinstance(value, Undefined): 244 return 245 246 if not isinstance(value, abc.Mapping): 247 raise TypeError("Can only get item pairs from a mapping.") 248 249 yield from value.items()
Return an iterator over the (key, value) items of a mapping.
x|items is the same as x.items(), except if x is
undefined an empty iterator is returned.
This filter is useful if you expect the template to be rendered with
an implementation of Jinja in another programming language that does
not have a .items() method on its mapping type.
<dl>
{% for key, value in my_dict|items %}
<dt>{{ key }}
<dd>{{ value }}
{% endfor %}
</dl>
New in version 3.1.
255@pass_eval_context 256def do_xmlattr( 257 eval_ctx: "EvalContext", d: t.Mapping[str, t.Any], autospace: bool = True 258) -> str: 259 """Create an SGML/XML attribute string based on the items in a dict. 260 261 If any key contains a space, this fails with a ``ValueError``. Values that 262 are neither ``none`` nor ``undefined`` are automatically escaped. 263 264 .. sourcecode:: html+jinja 265 266 <ul{{ {'class': 'my_list', 'missing': none, 267 'id': 'list-%d'|format(variable)}|xmlattr }}> 268 ... 269 </ul> 270 271 Results in something like this: 272 273 .. sourcecode:: html 274 275 <ul class="my_list" id="list-42"> 276 ... 277 </ul> 278 279 As you can see it automatically prepends a space in front of the item 280 if the filter returned something unless the second parameter is false. 281 282 .. versionchanged:: 3.1.3 283 Keys with spaces are not allowed. 284 """ 285 items = [] 286 287 for key, value in d.items(): 288 if value is None or isinstance(value, Undefined): 289 continue 290 291 if _space_re.search(key) is not None: 292 raise ValueError(f"Spaces are not allowed in attributes: '{key}'") 293 294 items.append(f'{escape(key)}="{escape(value)}"') 295 296 rv = " ".join(items) 297 298 if autospace and rv: 299 rv = " " + rv 300 301 if eval_ctx.autoescape: 302 rv = Markup(rv) 303 304 return rv
Create an SGML/XML attribute string based on the items in a dict.
If any key contains a space, this fails with a ValueError. Values that
are neither none nor undefined are automatically escaped.
.. sourcecode:: html+jinja
<ul{{ {'class': 'my_list', 'missing': none,
'id': 'list-%d'|format(variable)}|xmlattr }}>
...
</ul>
Results in something like this:
.. sourcecode:: html
<ul class="my_list" id="list-42">
...
</ul>
As you can see it automatically prepends a space in front of the item if the filter returned something unless the second parameter is false.
Changed in version 3.1.3: Keys with spaces are not allowed.
307def do_capitalize(s: str) -> str: 308 """Capitalize a value. The first character will be uppercase, all others 309 lowercase. 310 """ 311 return soft_str(s).capitalize()
Capitalize a value. The first character will be uppercase, all others lowercase.
317def do_title(s: str) -> str: 318 """Return a titlecased version of the value. I.e. words will start with 319 uppercase letters, all remaining characters are lowercase. 320 """ 321 return "".join( 322 [ 323 item[0].upper() + item[1:].lower() 324 for item in _word_beginning_split_re.split(soft_str(s)) 325 if item 326 ] 327 )
Return a titlecased version of the value. I.e. words will start with uppercase letters, all remaining characters are lowercase.
330def do_dictsort( 331 value: t.Mapping[K, V], 332 case_sensitive: bool = False, 333 by: 'te.Literal["key", "value"]' = "key", 334 reverse: bool = False, 335) -> t.List[t.Tuple[K, V]]: 336 """Sort a dict and yield (key, value) pairs. Python dicts may not 337 be in the order you want to display them in, so sort them first. 338 339 .. sourcecode:: jinja 340 341 {% for key, value in mydict|dictsort %} 342 sort the dict by key, case insensitive 343 344 {% for key, value in mydict|dictsort(reverse=true) %} 345 sort the dict by key, case insensitive, reverse order 346 347 {% for key, value in mydict|dictsort(true) %} 348 sort the dict by key, case sensitive 349 350 {% for key, value in mydict|dictsort(false, 'value') %} 351 sort the dict by value, case insensitive 352 """ 353 if by == "key": 354 pos = 0 355 elif by == "value": 356 pos = 1 357 else: 358 raise FilterArgumentError('You can only sort by either "key" or "value"') 359 360 def sort_func(item: t.Tuple[t.Any, t.Any]) -> t.Any: 361 value = item[pos] 362 363 if not case_sensitive: 364 value = ignore_case(value) 365 366 return value 367 368 return sorted(value.items(), key=sort_func, reverse=reverse)
Sort a dict and yield (key, value) pairs. Python dicts may not be in the order you want to display them in, so sort them first.
.. sourcecode:: jinja
{% for key, value in mydict|dictsort %}
sort the dict by key, case insensitive
{% for key, value in mydict|dictsort(reverse=true) %}
sort the dict by key, case insensitive, reverse order
{% for key, value in mydict|dictsort(true) %}
sort the dict by key, case sensitive
{% for key, value in mydict|dictsort(false, 'value') %}
sort the dict by value, case insensitive
371@pass_environment 372def do_sort( 373 environment: "Environment", 374 value: "t.Iterable[V]", 375 reverse: bool = False, 376 case_sensitive: bool = False, 377 attribute: t.Optional[t.Union[str, int]] = None, 378) -> "t.List[V]": 379 """Sort an iterable using Python's :func:`sorted`. 380 381 .. sourcecode:: jinja 382 383 {% for city in cities|sort %} 384 ... 385 {% endfor %} 386 387 :param reverse: Sort descending instead of ascending. 388 :param case_sensitive: When sorting strings, sort upper and lower 389 case separately. 390 :param attribute: When sorting objects or dicts, an attribute or 391 key to sort by. Can use dot notation like ``"address.city"``. 392 Can be a list of attributes like ``"age,name"``. 393 394 The sort is stable, it does not change the relative order of 395 elements that compare equal. This makes it is possible to chain 396 sorts on different attributes and ordering. 397 398 .. sourcecode:: jinja 399 400 {% for user in users|sort(attribute="name") 401 |sort(reverse=true, attribute="age") %} 402 ... 403 {% endfor %} 404 405 As a shortcut to chaining when the direction is the same for all 406 attributes, pass a comma separate list of attributes. 407 408 .. sourcecode:: jinja 409 410 {% for user in users|sort(attribute="age,name") %} 411 ... 412 {% endfor %} 413 414 .. versionchanged:: 2.11.0 415 The ``attribute`` parameter can be a comma separated list of 416 attributes, e.g. ``"age,name"``. 417 418 .. versionchanged:: 2.6 419 The ``attribute`` parameter was added. 420 """ 421 key_func = make_multi_attrgetter( 422 environment, attribute, postprocess=ignore_case if not case_sensitive else None 423 ) 424 return sorted(value, key=key_func, reverse=reverse)
Sort an iterable using Python's sorted().
.. sourcecode:: jinja
{% for city in cities|sort %}
...
{% endfor %}
Parameters
- reverse: Sort descending instead of ascending.
- case_sensitive: When sorting strings, sort upper and lower case separately.
- attribute: When sorting objects or dicts, an attribute or
key to sort by. Can use dot notation like
"address.city". Can be a list of attributes like"age,name".
The sort is stable, it does not change the relative order of elements that compare equal. This makes it is possible to chain sorts on different attributes and ordering.
.. sourcecode:: jinja
{% for user in users|sort(attribute="name")
|sort(reverse=true, attribute="age") %}
...
{% endfor %}
As a shortcut to chaining when the direction is the same for all attributes, pass a comma separate list of attributes.
.. sourcecode:: jinja
{% for user in users|sort(attribute="age,name") %}
...
{% endfor %}
Changed in version 2.11.0:
The attribute parameter can be a comma separated list of
attributes, e.g. "age,name".
Changed in version 2.6:
The attribute parameter was added.
427@pass_environment 428def do_unique( 429 environment: "Environment", 430 value: "t.Iterable[V]", 431 case_sensitive: bool = False, 432 attribute: t.Optional[t.Union[str, int]] = None, 433) -> "t.Iterator[V]": 434 """Returns a list of unique items from the given iterable. 435 436 .. sourcecode:: jinja 437 438 {{ ['foo', 'bar', 'foobar', 'FooBar']|unique|list }} 439 -> ['foo', 'bar', 'foobar'] 440 441 The unique items are yielded in the same order as their first occurrence in 442 the iterable passed to the filter. 443 444 :param case_sensitive: Treat upper and lower case strings as distinct. 445 :param attribute: Filter objects with unique values for this attribute. 446 """ 447 getter = make_attrgetter( 448 environment, attribute, postprocess=ignore_case if not case_sensitive else None 449 ) 450 seen = set() 451 452 for item in value: 453 key = getter(item) 454 455 if key not in seen: 456 seen.add(key) 457 yield item
Returns a list of unique items from the given iterable.
.. sourcecode:: jinja
{{ ['foo', 'bar', 'foobar', 'FooBar']|unique|list }}
-> ['foo', 'bar', 'foobar']
The unique items are yielded in the same order as their first occurrence in the iterable passed to the filter.
Parameters
- case_sensitive: Treat upper and lower case strings as distinct.
- attribute: Filter objects with unique values for this attribute.
480@pass_environment 481def do_min( 482 environment: "Environment", 483 value: "t.Iterable[V]", 484 case_sensitive: bool = False, 485 attribute: t.Optional[t.Union[str, int]] = None, 486) -> "t.Union[V, Undefined]": 487 """Return the smallest item from the sequence. 488 489 .. sourcecode:: jinja 490 491 {{ [1, 2, 3]|min }} 492 -> 1 493 494 :param case_sensitive: Treat upper and lower case strings as distinct. 495 :param attribute: Get the object with the min value of this attribute. 496 """ 497 return _min_or_max(environment, value, min, case_sensitive, attribute)
Return the smallest item from the sequence.
.. sourcecode:: jinja
{{ [1, 2, 3]|min }}
-> 1
Parameters
- case_sensitive: Treat upper and lower case strings as distinct.
- attribute: Get the object with the min value of this attribute.
500@pass_environment 501def do_max( 502 environment: "Environment", 503 value: "t.Iterable[V]", 504 case_sensitive: bool = False, 505 attribute: t.Optional[t.Union[str, int]] = None, 506) -> "t.Union[V, Undefined]": 507 """Return the largest item from the sequence. 508 509 .. sourcecode:: jinja 510 511 {{ [1, 2, 3]|max }} 512 -> 3 513 514 :param case_sensitive: Treat upper and lower case strings as distinct. 515 :param attribute: Get the object with the max value of this attribute. 516 """ 517 return _min_or_max(environment, value, max, case_sensitive, attribute)
Return the largest item from the sequence.
.. sourcecode:: jinja
{{ [1, 2, 3]|max }}
-> 3
Parameters
- case_sensitive: Treat upper and lower case strings as distinct.
- attribute: Get the object with the max value of this attribute.
520def do_default( 521 value: V, 522 default_value: V = "", # type: ignore 523 boolean: bool = False, 524) -> V: 525 """If the value is undefined it will return the passed default value, 526 otherwise the value of the variable: 527 528 .. sourcecode:: jinja 529 530 {{ my_variable|default('my_variable is not defined') }} 531 532 This will output the value of ``my_variable`` if the variable was 533 defined, otherwise ``'my_variable is not defined'``. If you want 534 to use default with variables that evaluate to false you have to 535 set the second parameter to `true`: 536 537 .. sourcecode:: jinja 538 539 {{ ''|default('the string was empty', true) }} 540 541 .. versionchanged:: 2.11 542 It's now possible to configure the :class:`~jinja2.Environment` with 543 :class:`~jinja2.ChainableUndefined` to make the `default` filter work 544 on nested elements and attributes that may contain undefined values 545 in the chain without getting an :exc:`~jinja2.UndefinedError`. 546 """ 547 if isinstance(value, Undefined) or (boolean and not value): 548 return default_value 549 550 return value
If the value is undefined it will return the passed default value, otherwise the value of the variable:
.. sourcecode:: jinja
{{ my_variable|default('my_variable is not defined') }}
This will output the value of my_variable if the variable was
defined, otherwise 'my_variable is not defined'. If you want
to use default with variables that evaluate to false you have to
set the second parameter to true:
.. sourcecode:: jinja
{{ ''|default('the string was empty', true) }}
Changed in version 2.11:
It's now possible to configure the ~jinja2.Environment with
~jinja2.ChainableUndefined to make the default filter work
on nested elements and attributes that may contain undefined values
in the chain without getting an ~jinja2.UndefinedError.
553@pass_eval_context 554def sync_do_join( 555 eval_ctx: "EvalContext", 556 value: t.Iterable, 557 d: str = "", 558 attribute: t.Optional[t.Union[str, int]] = None, 559) -> str: 560 """Return a string which is the concatenation of the strings in the 561 sequence. The separator between elements is an empty string per 562 default, you can define it with the optional parameter: 563 564 .. sourcecode:: jinja 565 566 {{ [1, 2, 3]|join('|') }} 567 -> 1|2|3 568 569 {{ [1, 2, 3]|join }} 570 -> 123 571 572 It is also possible to join certain attributes of an object: 573 574 .. sourcecode:: jinja 575 576 {{ users|join(', ', attribute='username') }} 577 578 .. versionadded:: 2.6 579 The `attribute` parameter was added. 580 """ 581 if attribute is not None: 582 value = map(make_attrgetter(eval_ctx.environment, attribute), value) 583 584 # no automatic escaping? joining is a lot easier then 585 if not eval_ctx.autoescape: 586 return str(d).join(map(str, value)) 587 588 # if the delimiter doesn't have an html representation we check 589 # if any of the items has. If yes we do a coercion to Markup 590 if not hasattr(d, "__html__"): 591 value = list(value) 592 do_escape = False 593 594 for idx, item in enumerate(value): 595 if hasattr(item, "__html__"): 596 do_escape = True 597 else: 598 value[idx] = str(item) 599 600 if do_escape: 601 d = escape(d) 602 else: 603 d = str(d) 604 605 return d.join(value) 606 607 # no html involved, to normal joining 608 return soft_str(d).join(map(soft_str, value))
Return a string which is the concatenation of the strings in the sequence. The separator between elements is an empty string per default, you can define it with the optional parameter:
.. sourcecode:: jinja
{{ [1, 2, 3]|join('|') }}
-> 1|2|3
{{ [1, 2, 3]|join }}
-> 123
It is also possible to join certain attributes of an object:
.. sourcecode:: jinja
{{ users|join(', ', attribute='username') }}
New in version 2.6:
The attribute parameter was added.
553@pass_eval_context 554def sync_do_join( 555 eval_ctx: "EvalContext", 556 value: t.Iterable, 557 d: str = "", 558 attribute: t.Optional[t.Union[str, int]] = None, 559) -> str: 560 """Return a string which is the concatenation of the strings in the 561 sequence. The separator between elements is an empty string per 562 default, you can define it with the optional parameter: 563 564 .. sourcecode:: jinja 565 566 {{ [1, 2, 3]|join('|') }} 567 -> 1|2|3 568 569 {{ [1, 2, 3]|join }} 570 -> 123 571 572 It is also possible to join certain attributes of an object: 573 574 .. sourcecode:: jinja 575 576 {{ users|join(', ', attribute='username') }} 577 578 .. versionadded:: 2.6 579 The `attribute` parameter was added. 580 """ 581 if attribute is not None: 582 value = map(make_attrgetter(eval_ctx.environment, attribute), value) 583 584 # no automatic escaping? joining is a lot easier then 585 if not eval_ctx.autoescape: 586 return str(d).join(map(str, value)) 587 588 # if the delimiter doesn't have an html representation we check 589 # if any of the items has. If yes we do a coercion to Markup 590 if not hasattr(d, "__html__"): 591 value = list(value) 592 do_escape = False 593 594 for idx, item in enumerate(value): 595 if hasattr(item, "__html__"): 596 do_escape = True 597 else: 598 value[idx] = str(item) 599 600 if do_escape: 601 d = escape(d) 602 else: 603 d = str(d) 604 605 return d.join(value) 606 607 # no html involved, to normal joining 608 return soft_str(d).join(map(soft_str, value))
Return a string which is the concatenation of the strings in the sequence. The separator between elements is an empty string per default, you can define it with the optional parameter:
.. sourcecode:: jinja
{{ [1, 2, 3]|join('|') }}
-> 1|2|3
{{ [1, 2, 3]|join }}
-> 123
It is also possible to join certain attributes of an object:
.. sourcecode:: jinja
{{ users|join(', ', attribute='username') }}
New in version 2.6:
The attribute parameter was added.
621def do_center(value: str, width: int = 80) -> str: 622 """Centers the value in a field of a given width.""" 623 return soft_str(value).center(width)
Centers the value in a field of a given width.
626@pass_environment 627def sync_do_first( 628 environment: "Environment", seq: "t.Iterable[V]" 629) -> "t.Union[V, Undefined]": 630 """Return the first item of a sequence.""" 631 try: 632 return next(iter(seq)) 633 except StopIteration: 634 return environment.undefined("No first item, sequence was empty.")
Return the first item of a sequence.
626@pass_environment 627def sync_do_first( 628 environment: "Environment", seq: "t.Iterable[V]" 629) -> "t.Union[V, Undefined]": 630 """Return the first item of a sequence.""" 631 try: 632 return next(iter(seq)) 633 except StopIteration: 634 return environment.undefined("No first item, sequence was empty.")
Return the first item of a sequence.
647@pass_environment 648def do_last( 649 environment: "Environment", seq: "t.Reversible[V]" 650) -> "t.Union[V, Undefined]": 651 """Return the last item of a sequence. 652 653 Note: Does not work with generators. You may want to explicitly 654 convert it to a list: 655 656 .. sourcecode:: jinja 657 658 {{ data | selectattr('name', '==', 'Jinja') | list | last }} 659 """ 660 try: 661 return next(iter(reversed(seq))) 662 except StopIteration: 663 return environment.undefined("No last item, sequence was empty.")
Return the last item of a sequence.
Note: Does not work with generators. You may want to explicitly convert it to a list:
.. sourcecode:: jinja
{{ data | selectattr('name', '==', 'Jinja') | list | last }}
669@pass_context 670def do_random(context: "Context", seq: "t.Sequence[V]") -> "t.Union[V, Undefined]": 671 """Return a random item from the sequence.""" 672 try: 673 return random.choice(seq) 674 except IndexError: 675 return context.environment.undefined("No random item, sequence was empty.")
Return a random item from the sequence.
678def do_filesizeformat(value: t.Union[str, float, int], binary: bool = False) -> str: 679 """Format the value like a 'human-readable' file size (i.e. 13 kB, 680 4.1 MB, 102 Bytes, etc). Per default decimal prefixes are used (Mega, 681 Giga, etc.), if the second parameter is set to `True` the binary 682 prefixes are used (Mebi, Gibi). 683 """ 684 bytes = float(value) 685 base = 1024 if binary else 1000 686 prefixes = [ 687 ("KiB" if binary else "kB"), 688 ("MiB" if binary else "MB"), 689 ("GiB" if binary else "GB"), 690 ("TiB" if binary else "TB"), 691 ("PiB" if binary else "PB"), 692 ("EiB" if binary else "EB"), 693 ("ZiB" if binary else "ZB"), 694 ("YiB" if binary else "YB"), 695 ] 696 697 if bytes == 1: 698 return "1 Byte" 699 elif bytes < base: 700 return f"{int(bytes)} Bytes" 701 else: 702 for i, prefix in enumerate(prefixes): 703 unit = base ** (i + 2) 704 705 if bytes < unit: 706 return f"{base * bytes / unit:.1f} {prefix}" 707 708 return f"{base * bytes / unit:.1f} {prefix}"
Format the value like a 'human-readable' file size (i.e. 13 kB,
4.1 MB, 102 Bytes, etc). Per default decimal prefixes are used (Mega,
Giga, etc.), if the second parameter is set to True the binary
prefixes are used (Mebi, Gibi).
711def do_pprint(value: t.Any) -> str: 712 """Pretty print a variable. Useful for debugging.""" 713 return pformat(value)
Pretty print a variable. Useful for debugging.
719@pass_eval_context 720def do_urlize( 721 eval_ctx: "EvalContext", 722 value: str, 723 trim_url_limit: t.Optional[int] = None, 724 nofollow: bool = False, 725 target: t.Optional[str] = None, 726 rel: t.Optional[str] = None, 727 extra_schemes: t.Optional[t.Iterable[str]] = None, 728) -> str: 729 """Convert URLs in text into clickable links. 730 731 This may not recognize links in some situations. Usually, a more 732 comprehensive formatter, such as a Markdown library, is a better 733 choice. 734 735 Works on ``http://``, ``https://``, ``www.``, ``mailto:``, and email 736 addresses. Links with trailing punctuation (periods, commas, closing 737 parentheses) and leading punctuation (opening parentheses) are 738 recognized excluding the punctuation. Email addresses that include 739 header fields are not recognized (for example, 740 ``mailto:address@example.com?cc=copy@example.com``). 741 742 :param value: Original text containing URLs to link. 743 :param trim_url_limit: Shorten displayed URL values to this length. 744 :param nofollow: Add the ``rel=nofollow`` attribute to links. 745 :param target: Add the ``target`` attribute to links. 746 :param rel: Add the ``rel`` attribute to links. 747 :param extra_schemes: Recognize URLs that start with these schemes 748 in addition to the default behavior. Defaults to 749 ``env.policies["urlize.extra_schemes"]``, which defaults to no 750 extra schemes. 751 752 .. versionchanged:: 3.0 753 The ``extra_schemes`` parameter was added. 754 755 .. versionchanged:: 3.0 756 Generate ``https://`` links for URLs without a scheme. 757 758 .. versionchanged:: 3.0 759 The parsing rules were updated. Recognize email addresses with 760 or without the ``mailto:`` scheme. Validate IP addresses. Ignore 761 parentheses and brackets in more cases. 762 763 .. versionchanged:: 2.8 764 The ``target`` parameter was added. 765 """ 766 policies = eval_ctx.environment.policies 767 rel_parts = set((rel or "").split()) 768 769 if nofollow: 770 rel_parts.add("nofollow") 771 772 rel_parts.update((policies["urlize.rel"] or "").split()) 773 rel = " ".join(sorted(rel_parts)) or None 774 775 if target is None: 776 target = policies["urlize.target"] 777 778 if extra_schemes is None: 779 extra_schemes = policies["urlize.extra_schemes"] or () 780 781 for scheme in extra_schemes: 782 if _uri_scheme_re.fullmatch(scheme) is None: 783 raise FilterArgumentError(f"{scheme!r} is not a valid URI scheme prefix.") 784 785 rv = urlize( 786 value, 787 trim_url_limit=trim_url_limit, 788 rel=rel, 789 target=target, 790 extra_schemes=extra_schemes, 791 ) 792 793 if eval_ctx.autoescape: 794 rv = Markup(rv) 795 796 return rv
Convert URLs in text into clickable links.
This may not recognize links in some situations. Usually, a more comprehensive formatter, such as a Markdown library, is a better choice.
Works on http://, https://, www., mailto:, and email
addresses. Links with trailing punctuation (periods, commas, closing
parentheses) and leading punctuation (opening parentheses) are
recognized excluding the punctuation. Email addresses that include
header fields are not recognized (for example,
mailto:address@example.com?cc=copy@example.com).
Parameters
- value: Original text containing URLs to link.
- trim_url_limit: Shorten displayed URL values to this length.
- nofollow: Add the
rel=nofollowattribute to links. - target: Add the
targetattribute to links. - rel: Add the
relattribute to links. - extra_schemes: Recognize URLs that start with these schemes
in addition to the default behavior. Defaults to
env.policies["urlize.extra_schemes"], which defaults to no extra schemes.
Changed in version 3.0:
The extra_schemes parameter was added.
Changed in version 3.0:
Generate https:// links for URLs without a scheme.
Changed in version 3.0:
The parsing rules were updated. Recognize email addresses with
or without the mailto: scheme. Validate IP addresses. Ignore
parentheses and brackets in more cases.
Changed in version 2.8:
The target parameter was added.
799def do_indent( 800 s: str, width: t.Union[int, str] = 4, first: bool = False, blank: bool = False 801) -> str: 802 """Return a copy of the string with each line indented by 4 spaces. The 803 first line and blank lines are not indented by default. 804 805 :param width: Number of spaces, or a string, to indent by. 806 :param first: Don't skip indenting the first line. 807 :param blank: Don't skip indenting empty lines. 808 809 .. versionchanged:: 3.0 810 ``width`` can be a string. 811 812 .. versionchanged:: 2.10 813 Blank lines are not indented by default. 814 815 Rename the ``indentfirst`` argument to ``first``. 816 """ 817 if isinstance(width, str): 818 indention = width 819 else: 820 indention = " " * width 821 822 newline = "\n" 823 824 if isinstance(s, Markup): 825 indention = Markup(indention) 826 newline = Markup(newline) 827 828 s += newline # this quirk is necessary for splitlines method 829 830 if blank: 831 rv = (newline + indention).join(s.splitlines()) 832 else: 833 lines = s.splitlines() 834 rv = lines.pop(0) 835 836 if lines: 837 rv += newline + newline.join( 838 indention + line if line else line for line in lines 839 ) 840 841 if first: 842 rv = indention + rv 843 844 return rv
Return a copy of the string with each line indented by 4 spaces. The first line and blank lines are not indented by default.
Parameters
- width: Number of spaces, or a string, to indent by.
- first: Don't skip indenting the first line.
- blank: Don't skip indenting empty lines.
Changed in version 3.0:
width can be a string.
Changed in version 2.10: Blank lines are not indented by default.
Rename the indentfirst argument to first.
847@pass_environment 848def do_truncate( 849 env: "Environment", 850 s: str, 851 length: int = 255, 852 killwords: bool = False, 853 end: str = "...", 854 leeway: t.Optional[int] = None, 855) -> str: 856 """Return a truncated copy of the string. The length is specified 857 with the first parameter which defaults to ``255``. If the second 858 parameter is ``true`` the filter will cut the text at length. Otherwise 859 it will discard the last word. If the text was in fact 860 truncated it will append an ellipsis sign (``"..."``). If you want a 861 different ellipsis sign than ``"..."`` you can specify it using the 862 third parameter. Strings that only exceed the length by the tolerance 863 margin given in the fourth parameter will not be truncated. 864 865 .. sourcecode:: jinja 866 867 {{ "foo bar baz qux"|truncate(9) }} 868 -> "foo..." 869 {{ "foo bar baz qux"|truncate(9, True) }} 870 -> "foo ba..." 871 {{ "foo bar baz qux"|truncate(11) }} 872 -> "foo bar baz qux" 873 {{ "foo bar baz qux"|truncate(11, False, '...', 0) }} 874 -> "foo bar..." 875 876 The default leeway on newer Jinja versions is 5 and was 0 before but 877 can be reconfigured globally. 878 """ 879 if leeway is None: 880 leeway = env.policies["truncate.leeway"] 881 882 assert length >= len(end), f"expected length >= {len(end)}, got {length}" 883 assert leeway >= 0, f"expected leeway >= 0, got {leeway}" 884 885 if len(s) <= length + leeway: 886 return s 887 888 if killwords: 889 return s[: length - len(end)] + end 890 891 result = s[: length - len(end)].rsplit(" ", 1)[0] 892 return result + end
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 Jinja versions is 5 and was 0 before but can be reconfigured globally.
895@pass_environment 896def do_wordwrap( 897 environment: "Environment", 898 s: str, 899 width: int = 79, 900 break_long_words: bool = True, 901 wrapstring: t.Optional[str] = None, 902 break_on_hyphens: bool = True, 903) -> str: 904 """Wrap a string to the given width. Existing newlines are treated 905 as paragraphs to be wrapped separately. 906 907 :param s: Original text to wrap. 908 :param width: Maximum length of wrapped lines. 909 :param break_long_words: If a word is longer than ``width``, break 910 it across lines. 911 :param break_on_hyphens: If a word contains hyphens, it may be split 912 across lines. 913 :param wrapstring: String to join each wrapped line. Defaults to 914 :attr:`Environment.newline_sequence`. 915 916 .. versionchanged:: 2.11 917 Existing newlines are treated as paragraphs wrapped separately. 918 919 .. versionchanged:: 2.11 920 Added the ``break_on_hyphens`` parameter. 921 922 .. versionchanged:: 2.7 923 Added the ``wrapstring`` parameter. 924 """ 925 import textwrap 926 927 if wrapstring is None: 928 wrapstring = environment.newline_sequence 929 930 # textwrap.wrap doesn't consider existing newlines when wrapping. 931 # If the string has a newline before width, wrap will still insert 932 # a newline at width, resulting in a short line. Instead, split and 933 # wrap each paragraph individually. 934 return wrapstring.join( 935 [ 936 wrapstring.join( 937 textwrap.wrap( 938 line, 939 width=width, 940 expand_tabs=False, 941 replace_whitespace=False, 942 break_long_words=break_long_words, 943 break_on_hyphens=break_on_hyphens, 944 ) 945 ) 946 for line in s.splitlines() 947 ] 948 )
Wrap a string to the given width. Existing newlines are treated as paragraphs to be wrapped separately.
Parameters
- s: Original text to wrap.
- width: Maximum length of wrapped lines.
- break_long_words: If a word is longer than
width, break it across lines. - break_on_hyphens: If a word contains hyphens, it may be split across lines.
- wrapstring: String to join each wrapped line. Defaults to
Environment.newline_sequence.
Changed in version 2.11: Existing newlines are treated as paragraphs wrapped separately.
Changed in version 2.11:
Added the break_on_hyphens parameter.
Changed in version 2.7:
Added the wrapstring parameter.
954def do_wordcount(s: str) -> int: 955 """Count the words in that string.""" 956 return len(_word_re.findall(soft_str(s)))
Count the words in that string.
959def do_int(value: t.Any, default: int = 0, base: int = 10) -> int: 960 """Convert the value into an integer. If the 961 conversion doesn't work it will return ``0``. You can 962 override this default using the first parameter. You 963 can also override the default base (10) in the second 964 parameter, which handles input with prefixes such as 965 0b, 0o and 0x for bases 2, 8 and 16 respectively. 966 The base is ignored for decimal numbers and non-string values. 967 """ 968 try: 969 if isinstance(value, str): 970 return int(value, base) 971 972 return int(value) 973 except (TypeError, ValueError): 974 # this quirk is necessary so that "42.23"|int gives 42. 975 try: 976 return int(float(value)) 977 except (TypeError, ValueError): 978 return default
Convert the value into an integer. If the
conversion doesn't work it will return 0. You can
override this default using the first parameter. You
can also override the default base (10) in the second
parameter, which handles input with prefixes such as
0b, 0o and 0x for bases 2, 8 and 16 respectively.
The base is ignored for decimal numbers and non-string values.
981def do_float(value: t.Any, default: float = 0.0) -> float: 982 """Convert the value into a floating point number. If the 983 conversion doesn't work it will return ``0.0``. You can 984 override this default using the first parameter. 985 """ 986 try: 987 return float(value) 988 except (TypeError, ValueError): 989 return default
Convert the value into a floating point number. If the
conversion doesn't work it will return 0.0. You can
override this default using the first parameter.
992def do_format(value: str, *args: t.Any, **kwargs: t.Any) -> str: 993 """Apply the given values to a `printf-style`_ format string, like 994 ``string % values``. 995 996 .. sourcecode:: jinja 997 998 {{ "%s, %s!"|format(greeting, name) }} 999 Hello, World! 1000 1001 In most cases it should be more convenient and efficient to use the 1002 ``%`` operator or :meth:`str.format`. 1003 1004 .. code-block:: text 1005 1006 {{ "%s, %s!" % (greeting, name) }} 1007 {{ "{}, {}!".format(greeting, name) }} 1008 1009 .. _printf-style: https://docs.python.org/library/stdtypes.html 1010 #printf-style-string-formatting 1011 """ 1012 if args and kwargs: 1013 raise FilterArgumentError( 1014 "can't handle positional and keyword arguments at the same time" 1015 ) 1016 1017 return soft_str(value) % (kwargs or args)
Apply the given values to a printf-style format string, like
string % values.
.. sourcecode:: jinja
{{ "%s, %s!"|format(greeting, name) }}
Hello, World!
In most cases it should be more convenient and efficient to use the
% operator or str.format().
{{ "%s, %s!" % (greeting, name) }}
{{ "{}, {}!".format(greeting, name) }}
#printf-style-string-formatting
1020def do_trim(value: str, chars: t.Optional[str] = None) -> str: 1021 """Strip leading and trailing characters, by default whitespace.""" 1022 return soft_str(value).strip(chars)
Strip leading and trailing characters, by default whitespace.
1033def sync_do_slice( 1034 value: "t.Collection[V]", slices: int, fill_with: "t.Optional[V]" = None 1035) -> "t.Iterator[t.List[V]]": 1036 """Slice an iterator and return a list of lists containing 1037 those items. Useful if you want to create a div containing 1038 three ul tags that represent columns: 1039 1040 .. sourcecode:: html+jinja 1041 1042 <div class="columnwrapper"> 1043 {%- for column in items|slice(3) %} 1044 <ul class="column-{{ loop.index }}"> 1045 {%- for item in column %} 1046 <li>{{ item }}</li> 1047 {%- endfor %} 1048 </ul> 1049 {%- endfor %} 1050 </div> 1051 1052 If you pass it a second argument it's used to fill missing 1053 values on the last iteration. 1054 """ 1055 seq = list(value) 1056 length = len(seq) 1057 items_per_slice = length // slices 1058 slices_with_extra = length % slices 1059 offset = 0 1060 1061 for slice_number in range(slices): 1062 start = offset + slice_number * items_per_slice 1063 1064 if slice_number < slices_with_extra: 1065 offset += 1 1066 1067 end = offset + (slice_number + 1) * items_per_slice 1068 tmp = seq[start:end] 1069 1070 if fill_with is not None and slice_number >= slices_with_extra: 1071 tmp.append(fill_with) 1072 1073 yield tmp
Slice an iterator and return a list of lists containing those items. Useful if you want to create a div containing three ul tags that represent columns:
.. sourcecode:: html+jinja
<div class="columnwrapper">
{%- for column in items|slice(3) %}
<ul class="column-{{ loop.index }}">
{%- for item in column %}
<li>{{ item }}</li>
{%- endfor %}
</ul>
{%- endfor %}
</div>
If you pass it a second argument it's used to fill missing values on the last iteration.
1033def sync_do_slice( 1034 value: "t.Collection[V]", slices: int, fill_with: "t.Optional[V]" = None 1035) -> "t.Iterator[t.List[V]]": 1036 """Slice an iterator and return a list of lists containing 1037 those items. Useful if you want to create a div containing 1038 three ul tags that represent columns: 1039 1040 .. sourcecode:: html+jinja 1041 1042 <div class="columnwrapper"> 1043 {%- for column in items|slice(3) %} 1044 <ul class="column-{{ loop.index }}"> 1045 {%- for item in column %} 1046 <li>{{ item }}</li> 1047 {%- endfor %} 1048 </ul> 1049 {%- endfor %} 1050 </div> 1051 1052 If you pass it a second argument it's used to fill missing 1053 values on the last iteration. 1054 """ 1055 seq = list(value) 1056 length = len(seq) 1057 items_per_slice = length // slices 1058 slices_with_extra = length % slices 1059 offset = 0 1060 1061 for slice_number in range(slices): 1062 start = offset + slice_number * items_per_slice 1063 1064 if slice_number < slices_with_extra: 1065 offset += 1 1066 1067 end = offset + (slice_number + 1) * items_per_slice 1068 tmp = seq[start:end] 1069 1070 if fill_with is not None and slice_number >= slices_with_extra: 1071 tmp.append(fill_with) 1072 1073 yield tmp
Slice an iterator and return a list of lists containing those items. Useful if you want to create a div containing three ul tags that represent columns:
.. sourcecode:: html+jinja
<div class="columnwrapper">
{%- for column in items|slice(3) %}
<ul class="column-{{ loop.index }}">
{%- for item in column %}
<li>{{ item }}</li>
{%- endfor %}
</ul>
{%- endfor %}
</div>
If you pass it a second argument it's used to fill missing values on the last iteration.
1085def do_batch( 1086 value: "t.Iterable[V]", linecount: int, fill_with: "t.Optional[V]" = None 1087) -> "t.Iterator[t.List[V]]": 1088 """ 1089 A filter that batches items. It works pretty much like `slice` 1090 just the other way round. It returns a list of lists with the 1091 given number of items. If you provide a second parameter this 1092 is used to fill up missing items. See this example: 1093 1094 .. sourcecode:: html+jinja 1095 1096 <table> 1097 {%- for row in items|batch(3, ' ') %} 1098 <tr> 1099 {%- for column in row %} 1100 <td>{{ column }}</td> 1101 {%- endfor %} 1102 </tr> 1103 {%- endfor %} 1104 </table> 1105 """ 1106 tmp: "t.List[V]" = [] 1107 1108 for item in value: 1109 if len(tmp) == linecount: 1110 yield tmp 1111 tmp = [] 1112 1113 tmp.append(item) 1114 1115 if tmp: 1116 if fill_with is not None and len(tmp) < linecount: 1117 tmp += [fill_with] * (linecount - len(tmp)) 1118 1119 yield tmp
A filter that batches items. It works pretty much like slice
just the other way round. It returns a list of lists with the
given number of items. If you provide a second parameter this
is used to fill up missing items. See this example:
.. sourcecode:: html+jinja
<table>
{%- for row in items|batch(3, ' ') %}
<tr>
{%- for column in row %}
<td>{{ column }}</td>
{%- endfor %}
</tr>
{%- endfor %}
</table>
1122def do_round( 1123 value: float, 1124 precision: int = 0, 1125 method: 'te.Literal["common", "ceil", "floor"]' = "common", 1126) -> float: 1127 """Round the number to a given precision. The first 1128 parameter specifies the precision (default is ``0``), the 1129 second the rounding method: 1130 1131 - ``'common'`` rounds either up or down 1132 - ``'ceil'`` always rounds up 1133 - ``'floor'`` always rounds down 1134 1135 If you don't specify a method ``'common'`` is used. 1136 1137 .. sourcecode:: jinja 1138 1139 {{ 42.55|round }} 1140 -> 43.0 1141 {{ 42.55|round(1, 'floor') }} 1142 -> 42.5 1143 1144 Note that even if rounded to 0 precision, a float is returned. If 1145 you need a real integer, pipe it through `int`: 1146 1147 .. sourcecode:: jinja 1148 1149 {{ 42.55|round|int }} 1150 -> 43 1151 """ 1152 if method not in {"common", "ceil", "floor"}: 1153 raise FilterArgumentError("method must be common, ceil or floor") 1154 1155 if method == "common": 1156 return round(value, precision) 1157 1158 func = getattr(math, method) 1159 return t.cast(float, func(value * (10**precision)) / (10**precision))
Round the number to a given precision. The first
parameter specifies the precision (default is 0), the
second the rounding method:
'common'rounds either up or down'ceil'always rounds up'floor'always rounds down
If you don't specify a method 'common' is used.
.. sourcecode:: jinja
{{ 42.55|round }}
-> 43.0
{{ 42.55|round(1, 'floor') }}
-> 42.5
Note that even if rounded to 0 precision, a float is returned. If
you need a real integer, pipe it through int:
.. sourcecode:: jinja
{{ 42.55|round|int }}
-> 43
1175@pass_environment 1176def sync_do_groupby( 1177 environment: "Environment", 1178 value: "t.Iterable[V]", 1179 attribute: t.Union[str, int], 1180 default: t.Optional[t.Any] = None, 1181 case_sensitive: bool = False, 1182) -> "t.List[_GroupTuple]": 1183 """Group a sequence of objects by an attribute using Python's 1184 :func:`itertools.groupby`. The attribute can use dot notation for 1185 nested access, like ``"address.city"``. Unlike Python's ``groupby``, 1186 the values are sorted first so only one group is returned for each 1187 unique value. 1188 1189 For example, a list of ``User`` objects with a ``city`` attribute 1190 can be rendered in groups. In this example, ``grouper`` refers to 1191 the ``city`` value of the group. 1192 1193 .. sourcecode:: html+jinja 1194 1195 <ul>{% for city, items in users|groupby("city") %} 1196 <li>{{ city }} 1197 <ul>{% for user in items %} 1198 <li>{{ user.name }} 1199 {% endfor %}</ul> 1200 </li> 1201 {% endfor %}</ul> 1202 1203 ``groupby`` yields namedtuples of ``(grouper, list)``, which 1204 can be used instead of the tuple unpacking above. ``grouper`` is the 1205 value of the attribute, and ``list`` is the items with that value. 1206 1207 .. sourcecode:: html+jinja 1208 1209 <ul>{% for group in users|groupby("city") %} 1210 <li>{{ group.grouper }}: {{ group.list|join(", ") }} 1211 {% endfor %}</ul> 1212 1213 You can specify a ``default`` value to use if an object in the list 1214 does not have the given attribute. 1215 1216 .. sourcecode:: jinja 1217 1218 <ul>{% for city, items in users|groupby("city", default="NY") %} 1219 <li>{{ city }}: {{ items|map(attribute="name")|join(", ") }}</li> 1220 {% endfor %}</ul> 1221 1222 Like the :func:`~jinja-filters.sort` filter, sorting and grouping is 1223 case-insensitive by default. The ``key`` for each group will have 1224 the case of the first item in that group of values. For example, if 1225 a list of users has cities ``["CA", "NY", "ca"]``, the "CA" group 1226 will have two values. This can be disabled by passing 1227 ``case_sensitive=True``. 1228 1229 .. versionchanged:: 3.1 1230 Added the ``case_sensitive`` parameter. Sorting and grouping is 1231 case-insensitive by default, matching other filters that do 1232 comparisons. 1233 1234 .. versionchanged:: 3.0 1235 Added the ``default`` parameter. 1236 1237 .. versionchanged:: 2.6 1238 The attribute supports dot notation for nested access. 1239 """ 1240 expr = make_attrgetter( 1241 environment, 1242 attribute, 1243 postprocess=ignore_case if not case_sensitive else None, 1244 default=default, 1245 ) 1246 out = [ 1247 _GroupTuple(key, list(values)) 1248 for key, values in groupby(sorted(value, key=expr), expr) 1249 ] 1250 1251 if not case_sensitive: 1252 # Return the real key from the first value instead of the lowercase key. 1253 output_expr = make_attrgetter(environment, attribute, default=default) 1254 out = [_GroupTuple(output_expr(values[0]), values) for _, values in out] 1255 1256 return out
Group a sequence of objects by an attribute using Python's
itertools.groupby(). The attribute can use dot notation for
nested access, like "address.city". Unlike Python's groupby,
the values are sorted first so only one group is returned for each
unique value.
For example, a list of User objects with a city attribute
can be rendered in groups. In this example, grouper refers to
the city value of the group.
.. sourcecode:: html+jinja
<ul>{% for city, items in users|groupby("city") %}
<li>{{ city }}
<ul>{% for user in items %}
<li>{{ user.name }}
{% endfor %}</ul>
</li>
{% endfor %}</ul>
groupby yields namedtuples of (grouper, list), which
can be used instead of the tuple unpacking above. grouper is the
value of the attribute, and list is the items with that value.
.. sourcecode:: html+jinja
<ul>{% for group in users|groupby("city") %}
<li>{{ group.grouper }}: {{ group.list|join(", ") }}
{% endfor %}</ul>
You can specify a default value to use if an object in the list
does not have the given attribute.
.. sourcecode:: jinja
<ul>{% for city, items in users|groupby("city", default="NY") %}
<li>{{ city }}: {{ items|map(attribute="name")|join(", ") }}</li>
{% endfor %}</ul>
Like the ~jinja-filters.sort() filter, sorting and grouping is
case-insensitive by default. The key for each group will have
the case of the first item in that group of values. For example, if
a list of users has cities ["CA", "NY", "ca"], the "CA" group
will have two values. This can be disabled by passing
case_sensitive=True.
Changed in version 3.1:
Added the case_sensitive parameter. Sorting and grouping is
case-insensitive by default, matching other filters that do
comparisons.
Changed in version 3.0:
Added the default parameter.
Changed in version 2.6: The attribute supports dot notation for nested access.
1175@pass_environment 1176def sync_do_groupby( 1177 environment: "Environment", 1178 value: "t.Iterable[V]", 1179 attribute: t.Union[str, int], 1180 default: t.Optional[t.Any] = None, 1181 case_sensitive: bool = False, 1182) -> "t.List[_GroupTuple]": 1183 """Group a sequence of objects by an attribute using Python's 1184 :func:`itertools.groupby`. The attribute can use dot notation for 1185 nested access, like ``"address.city"``. Unlike Python's ``groupby``, 1186 the values are sorted first so only one group is returned for each 1187 unique value. 1188 1189 For example, a list of ``User`` objects with a ``city`` attribute 1190 can be rendered in groups. In this example, ``grouper`` refers to 1191 the ``city`` value of the group. 1192 1193 .. sourcecode:: html+jinja 1194 1195 <ul>{% for city, items in users|groupby("city") %} 1196 <li>{{ city }} 1197 <ul>{% for user in items %} 1198 <li>{{ user.name }} 1199 {% endfor %}</ul> 1200 </li> 1201 {% endfor %}</ul> 1202 1203 ``groupby`` yields namedtuples of ``(grouper, list)``, which 1204 can be used instead of the tuple unpacking above. ``grouper`` is the 1205 value of the attribute, and ``list`` is the items with that value. 1206 1207 .. sourcecode:: html+jinja 1208 1209 <ul>{% for group in users|groupby("city") %} 1210 <li>{{ group.grouper }}: {{ group.list|join(", ") }} 1211 {% endfor %}</ul> 1212 1213 You can specify a ``default`` value to use if an object in the list 1214 does not have the given attribute. 1215 1216 .. sourcecode:: jinja 1217 1218 <ul>{% for city, items in users|groupby("city", default="NY") %} 1219 <li>{{ city }}: {{ items|map(attribute="name")|join(", ") }}</li> 1220 {% endfor %}</ul> 1221 1222 Like the :func:`~jinja-filters.sort` filter, sorting and grouping is 1223 case-insensitive by default. The ``key`` for each group will have 1224 the case of the first item in that group of values. For example, if 1225 a list of users has cities ``["CA", "NY", "ca"]``, the "CA" group 1226 will have two values. This can be disabled by passing 1227 ``case_sensitive=True``. 1228 1229 .. versionchanged:: 3.1 1230 Added the ``case_sensitive`` parameter. Sorting and grouping is 1231 case-insensitive by default, matching other filters that do 1232 comparisons. 1233 1234 .. versionchanged:: 3.0 1235 Added the ``default`` parameter. 1236 1237 .. versionchanged:: 2.6 1238 The attribute supports dot notation for nested access. 1239 """ 1240 expr = make_attrgetter( 1241 environment, 1242 attribute, 1243 postprocess=ignore_case if not case_sensitive else None, 1244 default=default, 1245 ) 1246 out = [ 1247 _GroupTuple(key, list(values)) 1248 for key, values in groupby(sorted(value, key=expr), expr) 1249 ] 1250 1251 if not case_sensitive: 1252 # Return the real key from the first value instead of the lowercase key. 1253 output_expr = make_attrgetter(environment, attribute, default=default) 1254 out = [_GroupTuple(output_expr(values[0]), values) for _, values in out] 1255 1256 return out
Group a sequence of objects by an attribute using Python's
itertools.groupby(). The attribute can use dot notation for
nested access, like "address.city". Unlike Python's groupby,
the values are sorted first so only one group is returned for each
unique value.
For example, a list of User objects with a city attribute
can be rendered in groups. In this example, grouper refers to
the city value of the group.
.. sourcecode:: html+jinja
<ul>{% for city, items in users|groupby("city") %}
<li>{{ city }}
<ul>{% for user in items %}
<li>{{ user.name }}
{% endfor %}</ul>
</li>
{% endfor %}</ul>
groupby yields namedtuples of (grouper, list), which
can be used instead of the tuple unpacking above. grouper is the
value of the attribute, and list is the items with that value.
.. sourcecode:: html+jinja
<ul>{% for group in users|groupby("city") %}
<li>{{ group.grouper }}: {{ group.list|join(", ") }}
{% endfor %}</ul>
You can specify a default value to use if an object in the list
does not have the given attribute.
.. sourcecode:: jinja
<ul>{% for city, items in users|groupby("city", default="NY") %}
<li>{{ city }}: {{ items|map(attribute="name")|join(", ") }}</li>
{% endfor %}</ul>
Like the ~jinja-filters.sort() filter, sorting and grouping is
case-insensitive by default. The key for each group will have
the case of the first item in that group of values. For example, if
a list of users has cities ["CA", "NY", "ca"], the "CA" group
will have two values. This can be disabled by passing
case_sensitive=True.
Changed in version 3.1:
Added the case_sensitive parameter. Sorting and grouping is
case-insensitive by default, matching other filters that do
comparisons.
Changed in version 3.0:
Added the default parameter.
Changed in version 2.6: The attribute supports dot notation for nested access.
1286@pass_environment 1287def sync_do_sum( 1288 environment: "Environment", 1289 iterable: "t.Iterable[V]", 1290 attribute: t.Optional[t.Union[str, int]] = None, 1291 start: V = 0, # type: ignore 1292) -> V: 1293 """Returns the sum of a sequence of numbers plus the value of parameter 1294 'start' (which defaults to 0). When the sequence is empty it returns 1295 start. 1296 1297 It is also possible to sum up only certain attributes: 1298 1299 .. sourcecode:: jinja 1300 1301 Total: {{ items|sum(attribute='price') }} 1302 1303 .. versionchanged:: 2.6 1304 The ``attribute`` parameter was added to allow summing up over 1305 attributes. Also the ``start`` parameter was moved on to the right. 1306 """ 1307 if attribute is not None: 1308 iterable = map(make_attrgetter(environment, attribute), iterable) 1309 1310 return sum(iterable, start) # type: ignore[no-any-return, call-overload]
Returns the sum of a sequence of numbers plus the value of parameter 'start' (which defaults to 0). When the sequence is empty it returns start.
It is also possible to sum up only certain attributes:
.. sourcecode:: jinja
Total: {{ items|sum(attribute='price') }}
Changed in version 2.6:
The attribute parameter was added to allow summing up over
attributes. Also the start parameter was moved on to the right.
1286@pass_environment 1287def sync_do_sum( 1288 environment: "Environment", 1289 iterable: "t.Iterable[V]", 1290 attribute: t.Optional[t.Union[str, int]] = None, 1291 start: V = 0, # type: ignore 1292) -> V: 1293 """Returns the sum of a sequence of numbers plus the value of parameter 1294 'start' (which defaults to 0). When the sequence is empty it returns 1295 start. 1296 1297 It is also possible to sum up only certain attributes: 1298 1299 .. sourcecode:: jinja 1300 1301 Total: {{ items|sum(attribute='price') }} 1302 1303 .. versionchanged:: 2.6 1304 The ``attribute`` parameter was added to allow summing up over 1305 attributes. Also the ``start`` parameter was moved on to the right. 1306 """ 1307 if attribute is not None: 1308 iterable = map(make_attrgetter(environment, attribute), iterable) 1309 1310 return sum(iterable, start) # type: ignore[no-any-return, call-overload]
Returns the sum of a sequence of numbers plus the value of parameter 'start' (which defaults to 0). When the sequence is empty it returns start.
It is also possible to sum up only certain attributes:
.. sourcecode:: jinja
Total: {{ items|sum(attribute='price') }}
Changed in version 2.6:
The attribute parameter was added to allow summing up over
attributes. Also the start parameter was moved on to the right.
1335def sync_do_list(value: "t.Iterable[V]") -> "t.List[V]": 1336 """Convert the value into a list. If it was a string the returned list 1337 will be a list of characters. 1338 """ 1339 return list(value)
Convert the value into a list. If it was a string the returned list will be a list of characters.
1335def sync_do_list(value: "t.Iterable[V]") -> "t.List[V]": 1336 """Convert the value into a list. If it was a string the returned list 1337 will be a list of characters. 1338 """ 1339 return list(value)
Convert the value into a list. If it was a string the returned list will be a list of characters.
1347def do_mark_safe(value: str) -> Markup: 1348 """Mark the value as safe which means that in an environment with automatic 1349 escaping enabled this variable will not be escaped. 1350 """ 1351 return Markup(value)
Mark the value as safe which means that in an environment with automatic escaping enabled this variable will not be escaped.
1354def do_mark_unsafe(value: str) -> str: 1355 """Mark a value as unsafe. This is the reverse operation for :func:`safe`.""" 1356 return str(value)
Mark a value as unsafe. This is the reverse operation for safe().
1369def do_reverse(value: t.Union[str, t.Iterable[V]]) -> t.Union[str, t.Iterable[V]]: 1370 """Reverse the object or return an iterator that iterates over it the other 1371 way round. 1372 """ 1373 if isinstance(value, str): 1374 return value[::-1] 1375 1376 try: 1377 return reversed(value) # type: ignore 1378 except TypeError: 1379 try: 1380 rv = list(value) 1381 rv.reverse() 1382 return rv 1383 except TypeError as e: 1384 raise FilterArgumentError("argument must be iterable") from e
Reverse the object or return an iterator that iterates over it the other way round.
1387@pass_environment 1388def do_attr( 1389 environment: "Environment", obj: t.Any, name: str 1390) -> t.Union[Undefined, t.Any]: 1391 """Get an attribute of an object. ``foo|attr("bar")`` works like 1392 ``foo.bar`` just that always an attribute is returned and items are not 1393 looked up. 1394 1395 See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details. 1396 """ 1397 try: 1398 name = str(name) 1399 except UnicodeError: 1400 pass 1401 else: 1402 try: 1403 value = getattr(obj, name) 1404 except AttributeError: 1405 pass 1406 else: 1407 if environment.sandboxed: 1408 environment = t.cast("SandboxedEnvironment", environment) 1409 1410 if not environment.is_safe_attribute(obj, name, value): 1411 return environment.unsafe_undefined(obj, name) 1412 1413 return value 1414 1415 return environment.undefined(obj=obj, name=name)
Get an attribute of an object. foo|attr("bar") works like
foo.bar just that always an attribute is returned and items are not
looked up.
See :ref:Notes on subscriptions <notes-on-subscriptions> for more details.
1436@pass_context 1437def sync_do_map( 1438 context: "Context", value: t.Iterable, *args: t.Any, **kwargs: t.Any 1439) -> t.Iterable: 1440 """Applies a filter on a sequence of objects or looks up an attribute. 1441 This is useful when dealing with lists of objects but you are really 1442 only interested in a certain value of it. 1443 1444 The basic usage is mapping on an attribute. Imagine you have a list 1445 of users but you are only interested in a list of usernames: 1446 1447 .. sourcecode:: jinja 1448 1449 Users on this page: {{ users|map(attribute='username')|join(', ') }} 1450 1451 You can specify a ``default`` value to use if an object in the list 1452 does not have the given attribute. 1453 1454 .. sourcecode:: jinja 1455 1456 {{ users|map(attribute="username", default="Anonymous")|join(", ") }} 1457 1458 Alternatively you can let it invoke a filter by passing the name of the 1459 filter and the arguments afterwards. A good example would be applying a 1460 text conversion filter on a sequence: 1461 1462 .. sourcecode:: jinja 1463 1464 Users on this page: {{ titles|map('lower')|join(', ') }} 1465 1466 Similar to a generator comprehension such as: 1467 1468 .. code-block:: python 1469 1470 (u.username for u in users) 1471 (getattr(u, "username", "Anonymous") for u in users) 1472 (do_lower(x) for x in titles) 1473 1474 .. versionchanged:: 2.11.0 1475 Added the ``default`` parameter. 1476 1477 .. versionadded:: 2.7 1478 """ 1479 if value: 1480 func = prepare_map(context, args, kwargs) 1481 1482 for item in value: 1483 yield func(item)
Applies a filter on a sequence of objects or looks up an attribute. This is useful when dealing with lists of objects but you are really only interested in a certain value of it.
The basic usage is mapping on an attribute. Imagine you have a list of users but you are only interested in a list of usernames:
.. sourcecode:: jinja
Users on this page: {{ users|map(attribute='username')|join(', ') }}
You can specify a default value to use if an object in the list
does not have the given attribute.
.. sourcecode:: jinja
{{ users|map(attribute="username", default="Anonymous")|join(", ") }}
Alternatively you can let it invoke a filter by passing the name of the filter and the arguments afterwards. A good example would be applying a text conversion filter on a sequence:
.. sourcecode:: jinja
Users on this page: {{ titles|map('lower')|join(', ') }}
Similar to a generator comprehension such as:
(u.username for u in users)
(getattr(u, "username", "Anonymous") for u in users)
(do_lower(x) for x in titles)
Changed in version 2.11.0:
Added the default parameter.
New in version 2.7.
1436@pass_context 1437def sync_do_map( 1438 context: "Context", value: t.Iterable, *args: t.Any, **kwargs: t.Any 1439) -> t.Iterable: 1440 """Applies a filter on a sequence of objects or looks up an attribute. 1441 This is useful when dealing with lists of objects but you are really 1442 only interested in a certain value of it. 1443 1444 The basic usage is mapping on an attribute. Imagine you have a list 1445 of users but you are only interested in a list of usernames: 1446 1447 .. sourcecode:: jinja 1448 1449 Users on this page: {{ users|map(attribute='username')|join(', ') }} 1450 1451 You can specify a ``default`` value to use if an object in the list 1452 does not have the given attribute. 1453 1454 .. sourcecode:: jinja 1455 1456 {{ users|map(attribute="username", default="Anonymous")|join(", ") }} 1457 1458 Alternatively you can let it invoke a filter by passing the name of the 1459 filter and the arguments afterwards. A good example would be applying a 1460 text conversion filter on a sequence: 1461 1462 .. sourcecode:: jinja 1463 1464 Users on this page: {{ titles|map('lower')|join(', ') }} 1465 1466 Similar to a generator comprehension such as: 1467 1468 .. code-block:: python 1469 1470 (u.username for u in users) 1471 (getattr(u, "username", "Anonymous") for u in users) 1472 (do_lower(x) for x in titles) 1473 1474 .. versionchanged:: 2.11.0 1475 Added the ``default`` parameter. 1476 1477 .. versionadded:: 2.7 1478 """ 1479 if value: 1480 func = prepare_map(context, args, kwargs) 1481 1482 for item in value: 1483 yield func(item)
Applies a filter on a sequence of objects or looks up an attribute. This is useful when dealing with lists of objects but you are really only interested in a certain value of it.
The basic usage is mapping on an attribute. Imagine you have a list of users but you are only interested in a list of usernames:
.. sourcecode:: jinja
Users on this page: {{ users|map(attribute='username')|join(', ') }}
You can specify a default value to use if an object in the list
does not have the given attribute.
.. sourcecode:: jinja
{{ users|map(attribute="username", default="Anonymous")|join(", ") }}
Alternatively you can let it invoke a filter by passing the name of the filter and the arguments afterwards. A good example would be applying a text conversion filter on a sequence:
.. sourcecode:: jinja
Users on this page: {{ titles|map('lower')|join(', ') }}
Similar to a generator comprehension such as:
(u.username for u in users)
(getattr(u, "username", "Anonymous") for u in users)
(do_lower(x) for x in titles)
Changed in version 2.11.0:
Added the default parameter.
New in version 2.7.
1522@pass_context 1523def sync_do_select( 1524 context: "Context", value: "t.Iterable[V]", *args: t.Any, **kwargs: t.Any 1525) -> "t.Iterator[V]": 1526 """Filters a sequence of objects by applying a test to each object, 1527 and only selecting the objects with the test succeeding. 1528 1529 If no test is specified, each object will be evaluated as a boolean. 1530 1531 Example usage: 1532 1533 .. sourcecode:: jinja 1534 1535 {{ numbers|select("odd") }} 1536 {{ numbers|select("odd") }} 1537 {{ numbers|select("divisibleby", 3) }} 1538 {{ numbers|select("lessthan", 42) }} 1539 {{ strings|select("equalto", "mystring") }} 1540 1541 Similar to a generator comprehension such as: 1542 1543 .. code-block:: python 1544 1545 (n for n in numbers if test_odd(n)) 1546 (n for n in numbers if test_divisibleby(n, 3)) 1547 1548 .. versionadded:: 2.7 1549 """ 1550 return select_or_reject(context, value, args, kwargs, lambda x: x, False)
Filters a sequence of objects by applying a test to each object, and only selecting the objects with the test succeeding.
If no test is specified, each object will be evaluated as a boolean.
Example usage:
.. sourcecode:: jinja
{{ numbers|select("odd") }}
{{ numbers|select("odd") }}
{{ numbers|select("divisibleby", 3) }}
{{ numbers|select("lessthan", 42) }}
{{ strings|select("equalto", "mystring") }}
Similar to a generator comprehension such as:
(n for n in numbers if test_odd(n))
(n for n in numbers if test_divisibleby(n, 3))
New in version 2.7.
1522@pass_context 1523def sync_do_select( 1524 context: "Context", value: "t.Iterable[V]", *args: t.Any, **kwargs: t.Any 1525) -> "t.Iterator[V]": 1526 """Filters a sequence of objects by applying a test to each object, 1527 and only selecting the objects with the test succeeding. 1528 1529 If no test is specified, each object will be evaluated as a boolean. 1530 1531 Example usage: 1532 1533 .. sourcecode:: jinja 1534 1535 {{ numbers|select("odd") }} 1536 {{ numbers|select("odd") }} 1537 {{ numbers|select("divisibleby", 3) }} 1538 {{ numbers|select("lessthan", 42) }} 1539 {{ strings|select("equalto", "mystring") }} 1540 1541 Similar to a generator comprehension such as: 1542 1543 .. code-block:: python 1544 1545 (n for n in numbers if test_odd(n)) 1546 (n for n in numbers if test_divisibleby(n, 3)) 1547 1548 .. versionadded:: 2.7 1549 """ 1550 return select_or_reject(context, value, args, kwargs, lambda x: x, False)
Filters a sequence of objects by applying a test to each object, and only selecting the objects with the test succeeding.
If no test is specified, each object will be evaluated as a boolean.
Example usage:
.. sourcecode:: jinja
{{ numbers|select("odd") }}
{{ numbers|select("odd") }}
{{ numbers|select("divisibleby", 3) }}
{{ numbers|select("lessthan", 42) }}
{{ strings|select("equalto", "mystring") }}
Similar to a generator comprehension such as:
(n for n in numbers if test_odd(n))
(n for n in numbers if test_divisibleby(n, 3))
New in version 2.7.
1563@pass_context 1564def sync_do_reject( 1565 context: "Context", value: "t.Iterable[V]", *args: t.Any, **kwargs: t.Any 1566) -> "t.Iterator[V]": 1567 """Filters a sequence of objects by applying a test to each object, 1568 and rejecting the objects with the test succeeding. 1569 1570 If no test is specified, each object will be evaluated as a boolean. 1571 1572 Example usage: 1573 1574 .. sourcecode:: jinja 1575 1576 {{ numbers|reject("odd") }} 1577 1578 Similar to a generator comprehension such as: 1579 1580 .. code-block:: python 1581 1582 (n for n in numbers if not test_odd(n)) 1583 1584 .. versionadded:: 2.7 1585 """ 1586 return select_or_reject(context, value, args, kwargs, lambda x: not x, False)
Filters a sequence of objects by applying a test to each object, and rejecting the objects with the test succeeding.
If no test is specified, each object will be evaluated as a boolean.
Example usage:
.. sourcecode:: jinja
{{ numbers|reject("odd") }}
Similar to a generator comprehension such as:
(n for n in numbers if not test_odd(n))
New in version 2.7.
1563@pass_context 1564def sync_do_reject( 1565 context: "Context", value: "t.Iterable[V]", *args: t.Any, **kwargs: t.Any 1566) -> "t.Iterator[V]": 1567 """Filters a sequence of objects by applying a test to each object, 1568 and rejecting the objects with the test succeeding. 1569 1570 If no test is specified, each object will be evaluated as a boolean. 1571 1572 Example usage: 1573 1574 .. sourcecode:: jinja 1575 1576 {{ numbers|reject("odd") }} 1577 1578 Similar to a generator comprehension such as: 1579 1580 .. code-block:: python 1581 1582 (n for n in numbers if not test_odd(n)) 1583 1584 .. versionadded:: 2.7 1585 """ 1586 return select_or_reject(context, value, args, kwargs, lambda x: not x, False)
Filters a sequence of objects by applying a test to each object, and rejecting the objects with the test succeeding.
If no test is specified, each object will be evaluated as a boolean.
Example usage:
.. sourcecode:: jinja
{{ numbers|reject("odd") }}
Similar to a generator comprehension such as:
(n for n in numbers if not test_odd(n))
New in version 2.7.
1599@pass_context 1600def sync_do_selectattr( 1601 context: "Context", value: "t.Iterable[V]", *args: t.Any, **kwargs: t.Any 1602) -> "t.Iterator[V]": 1603 """Filters a sequence of objects by applying a test to the specified 1604 attribute of each object, and only selecting the objects with the 1605 test succeeding. 1606 1607 If no test is specified, the attribute's value will be evaluated as 1608 a boolean. 1609 1610 Example usage: 1611 1612 .. sourcecode:: jinja 1613 1614 {{ users|selectattr("is_active") }} 1615 {{ users|selectattr("email", "none") }} 1616 1617 Similar to a generator comprehension such as: 1618 1619 .. code-block:: python 1620 1621 (u for user in users if user.is_active) 1622 (u for user in users if test_none(user.email)) 1623 1624 .. versionadded:: 2.7 1625 """ 1626 return select_or_reject(context, value, args, kwargs, lambda x: x, True)
Filters a sequence of objects by applying a test to the specified attribute of each object, and only selecting the objects with the test succeeding.
If no test is specified, the attribute's value will be evaluated as a boolean.
Example usage:
.. sourcecode:: jinja
{{ users|selectattr("is_active") }}
{{ users|selectattr("email", "none") }}
Similar to a generator comprehension such as:
(u for user in users if user.is_active)
(u for user in users if test_none(user.email))
New in version 2.7.
1599@pass_context 1600def sync_do_selectattr( 1601 context: "Context", value: "t.Iterable[V]", *args: t.Any, **kwargs: t.Any 1602) -> "t.Iterator[V]": 1603 """Filters a sequence of objects by applying a test to the specified 1604 attribute of each object, and only selecting the objects with the 1605 test succeeding. 1606 1607 If no test is specified, the attribute's value will be evaluated as 1608 a boolean. 1609 1610 Example usage: 1611 1612 .. sourcecode:: jinja 1613 1614 {{ users|selectattr("is_active") }} 1615 {{ users|selectattr("email", "none") }} 1616 1617 Similar to a generator comprehension such as: 1618 1619 .. code-block:: python 1620 1621 (u for user in users if user.is_active) 1622 (u for user in users if test_none(user.email)) 1623 1624 .. versionadded:: 2.7 1625 """ 1626 return select_or_reject(context, value, args, kwargs, lambda x: x, True)
Filters a sequence of objects by applying a test to the specified attribute of each object, and only selecting the objects with the test succeeding.
If no test is specified, the attribute's value will be evaluated as a boolean.
Example usage:
.. sourcecode:: jinja
{{ users|selectattr("is_active") }}
{{ users|selectattr("email", "none") }}
Similar to a generator comprehension such as:
(u for user in users if user.is_active)
(u for user in users if test_none(user.email))
New in version 2.7.
1639@pass_context 1640def sync_do_rejectattr( 1641 context: "Context", value: "t.Iterable[V]", *args: t.Any, **kwargs: t.Any 1642) -> "t.Iterator[V]": 1643 """Filters a sequence of objects by applying a test to the specified 1644 attribute of each object, and rejecting the objects with the test 1645 succeeding. 1646 1647 If no test is specified, the attribute's value will be evaluated as 1648 a boolean. 1649 1650 .. sourcecode:: jinja 1651 1652 {{ users|rejectattr("is_active") }} 1653 {{ users|rejectattr("email", "none") }} 1654 1655 Similar to a generator comprehension such as: 1656 1657 .. code-block:: python 1658 1659 (u for user in users if not user.is_active) 1660 (u for user in users if not test_none(user.email)) 1661 1662 .. versionadded:: 2.7 1663 """ 1664 return select_or_reject(context, value, args, kwargs, lambda x: not x, True)
Filters a sequence of objects by applying a test to the specified attribute of each object, and rejecting the objects with the test succeeding.
If no test is specified, the attribute's value will be evaluated as a boolean.
.. sourcecode:: jinja
{{ users|rejectattr("is_active") }}
{{ users|rejectattr("email", "none") }}
Similar to a generator comprehension such as:
(u for user in users if not user.is_active)
(u for user in users if not test_none(user.email))
New in version 2.7.
1639@pass_context 1640def sync_do_rejectattr( 1641 context: "Context", value: "t.Iterable[V]", *args: t.Any, **kwargs: t.Any 1642) -> "t.Iterator[V]": 1643 """Filters a sequence of objects by applying a test to the specified 1644 attribute of each object, and rejecting the objects with the test 1645 succeeding. 1646 1647 If no test is specified, the attribute's value will be evaluated as 1648 a boolean. 1649 1650 .. sourcecode:: jinja 1651 1652 {{ users|rejectattr("is_active") }} 1653 {{ users|rejectattr("email", "none") }} 1654 1655 Similar to a generator comprehension such as: 1656 1657 .. code-block:: python 1658 1659 (u for user in users if not user.is_active) 1660 (u for user in users if not test_none(user.email)) 1661 1662 .. versionadded:: 2.7 1663 """ 1664 return select_or_reject(context, value, args, kwargs, lambda x: not x, True)
Filters a sequence of objects by applying a test to the specified attribute of each object, and rejecting the objects with the test succeeding.
If no test is specified, the attribute's value will be evaluated as a boolean.
.. sourcecode:: jinja
{{ users|rejectattr("is_active") }}
{{ users|rejectattr("email", "none") }}
Similar to a generator comprehension such as:
(u for user in users if not user.is_active)
(u for user in users if not test_none(user.email))
New in version 2.7.
1677@pass_eval_context 1678def do_tojson( 1679 eval_ctx: "EvalContext", value: t.Any, indent: t.Optional[int] = None 1680) -> Markup: 1681 """Serialize an object to a string of JSON, and mark it safe to 1682 render in HTML. This filter is only for use in HTML documents. 1683 1684 The returned string is safe to render in HTML documents and 1685 ``<script>`` tags. The exception is in HTML attributes that are 1686 double quoted; either use single quotes or the ``|forceescape`` 1687 filter. 1688 1689 :param value: The object to serialize to JSON. 1690 :param indent: The ``indent`` parameter passed to ``dumps``, for 1691 pretty-printing the value. 1692 1693 .. versionadded:: 2.9 1694 """ 1695 policies = eval_ctx.environment.policies 1696 dumps = policies["json.dumps_function"] 1697 kwargs = policies["json.dumps_kwargs"] 1698 1699 if indent is not None: 1700 kwargs = kwargs.copy() 1701 kwargs["indent"] = indent 1702 1703 return htmlsafe_json_dumps(value, dumps=dumps, **kwargs)
Serialize an object to a string of JSON, and mark it safe to render in HTML. This filter is only for use in HTML documents.
The returned string is safe to render in HTML documents and
<script> tags. The exception is in HTML attributes that are
double quoted; either use single quotes or the |forceescape
filter.
Parameters
- value: The object to serialize to JSON.
- indent: The
indentparameter passed todumps, for pretty-printing the value.
New in version 2.9.
1706def prepare_map( 1707 context: "Context", args: t.Tuple, kwargs: t.Dict[str, t.Any] 1708) -> t.Callable[[t.Any], t.Any]: 1709 if not args and "attribute" in kwargs: 1710 attribute = kwargs.pop("attribute") 1711 default = kwargs.pop("default", None) 1712 1713 if kwargs: 1714 raise FilterArgumentError( 1715 f"Unexpected keyword argument {next(iter(kwargs))!r}" 1716 ) 1717 1718 func = make_attrgetter(context.environment, attribute, default=default) 1719 else: 1720 try: 1721 name = args[0] 1722 args = args[1:] 1723 except LookupError: 1724 raise FilterArgumentError("map requires a filter argument") from None 1725 1726 def func(item: t.Any) -> t.Any: 1727 return context.environment.call_filter( 1728 name, item, args, kwargs, context=context 1729 ) 1730 1731 return func
1734def prepare_select_or_reject( 1735 context: "Context", 1736 args: t.Tuple, 1737 kwargs: t.Dict[str, t.Any], 1738 modfunc: t.Callable[[t.Any], t.Any], 1739 lookup_attr: bool, 1740) -> t.Callable[[t.Any], t.Any]: 1741 if lookup_attr: 1742 try: 1743 attr = args[0] 1744 except LookupError: 1745 raise FilterArgumentError("Missing parameter for attribute name") from None 1746 1747 transfunc = make_attrgetter(context.environment, attr) 1748 off = 1 1749 else: 1750 off = 0 1751 1752 def transfunc(x: V) -> V: 1753 return x 1754 1755 try: 1756 name = args[off] 1757 args = args[1 + off :] 1758 1759 def func(item: t.Any) -> t.Any: 1760 return context.environment.call_test(name, item, args, kwargs) 1761 1762 except LookupError: 1763 func = bool # type: ignore 1764 1765 return lambda item: modfunc(func(transfunc(item)))
1768def select_or_reject( 1769 context: "Context", 1770 value: "t.Iterable[V]", 1771 args: t.Tuple, 1772 kwargs: t.Dict[str, t.Any], 1773 modfunc: t.Callable[[t.Any], t.Any], 1774 lookup_attr: bool, 1775) -> "t.Iterator[V]": 1776 if value: 1777 func = prepare_select_or_reject(context, args, kwargs, modfunc, lookup_attr) 1778 1779 for item in value: 1780 if func(item): 1781 yield item
1784async def async_select_or_reject( 1785 context: "Context", 1786 value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", 1787 args: t.Tuple, 1788 kwargs: t.Dict[str, t.Any], 1789 modfunc: t.Callable[[t.Any], t.Any], 1790 lookup_attr: bool, 1791) -> "t.AsyncIterator[V]": 1792 if value: 1793 func = prepare_select_or_reject(context, args, kwargs, modfunc, lookup_attr) 1794 1795 async for item in auto_aiter(value): 1796 if func(item): 1797 yield item