mirror of
https://github.com/django-components/django-components.git
synced 2025-09-19 12:19:44 +00:00
752 lines
No EOL
334 KiB
HTML
752 lines
No EOL
334 KiB
HTML
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content="A way to create simple reusable template components in Django."><link href=https://django-components.github.io/django-components/latest/release_notes/ rel=canonical><link href=../reference/testing_api/ rel=prev><link rel=icon href=../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.6.16"><title>Release Notes - Django-Components</title><link rel=stylesheet href=../assets/stylesheets/main.7e37652d.min.css><link rel=stylesheet href=../assets/stylesheets/palette.06af60db.min.css><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link rel=stylesheet href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback"><style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style><link rel=stylesheet href=../assets/_markdown_exec_pyodide.css><link rel=stylesheet href=../assets/_mkdocstrings.css><link rel=stylesheet href=../css/timeago.css><link rel=stylesheet href=../css/style.css><script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script><meta property=og:type content=website><meta property=og:title content="Release Notes - Django-Components"><meta property=og:description content="A way to create simple reusable template components in Django."><meta property=og:image content=https://django-components.github.io/django-components/latest/assets/images/social/release_notes.png><meta property=og:image:type content=image/png><meta property=og:image:width content=1200><meta property=og:image:height content=630><meta content=https://django-components.github.io/django-components/latest/release_notes/ property=og:url><meta name=twitter:card content=summary_large_image><meta name=twitter:title content="Release Notes - Django-Components"><meta name=twitter:description content="A way to create simple reusable template components in Django."><meta name=twitter:image content=https://django-components.github.io/django-components/latest/assets/images/social/release_notes.png></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=indigo data-md-color-accent=indigo> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#release-notes class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <div data-md-color-scheme=default data-md-component=outdated hidden> </div> <header class=md-header data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=.. title=Django-Components class="md-header__button md-logo" aria-label=Django-Components data-md-component=logo> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> Django-Components </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> Release Notes </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media=(prefers-color-scheme) data-md-color-scheme=default data-md-color-primary=indigo data-md-color-accent=indigo aria-label="Switch to light mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="m14.3 16-.7-2h-3.2l-.7 2H7.8L11 7h2l3.2 9zM20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12zm-9.15 3.96h2.3L12 9z"/></svg> </label> <input class=md-option data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme=default data-md-color-primary=teal data-md-color-accent=indigo aria-label="Switch to dark mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_2 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="m17.75 4.09-2.53 1.94.91 3.06-2.63-1.81-2.63 1.81.91-3.06-2.53-1.94L12.44 4l1.06-3 1.06 3zm3.5 6.91-1.64 1.25.59 1.98-1.7-1.17-1.7 1.17.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95zm-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14.4-.4.82-.76 1.27-1.08.75-.53 1.93.36 1.85 1.19-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82-2.81 3.14-2.7 7.96.31 10.98 3.02 3.01 7.84 3.12 10.98.31"/></svg> </label> <input class=md-option data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme=slate data-md-color-primary=teal data-md-color-accent=indigo aria-label="Switch to light mode" type=radio name=__palette id=__palette_2> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 7a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5m0 2a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3m0-7 2.39 3.42C13.65 5.15 12.84 5 12 5s-1.65.15-2.39.42zM3.34 7l4.16-.35A7.2 7.2 0 0 0 5.94 8.5c-.44.74-.69 1.5-.83 2.29zm.02 10 1.76-3.77a7.131 7.131 0 0 0 2.38 4.14zM20.65 7l-1.77 3.79a7.02 7.02 0 0 0-2.38-4.15zm-.01 10-4.14.36c.59-.51 1.12-1.14 1.54-1.86.42-.73.69-1.5.83-2.29zM12 22l-2.41-3.44c.74.27 1.55.44 2.41.44.82 0 1.63-.17 2.37-.44z"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script> <label class="md-header__button md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg> </label> <div class=md-search data-md-component=search role=dialog> <label class=md-search__overlay for=__search></label> <div class=md-search__inner role=search> <form class=md-search__form name=search> <input type=text class=md-search__input name=query aria-label=Search placeholder=Search autocapitalize=off autocorrect=off autocomplete=off spellcheck=false data-md-component=search-query required> <label class="md-search__icon md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </label> <nav class=md-search__options aria-label=Search> <a href=javascript:void(0) class="md-search__icon md-icon" title=Share aria-label=Share data-clipboard data-clipboard-text data-md-component=search-share tabindex=-1> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"/></svg> </a> <button type=reset class="md-search__icon md-icon" title=Clear aria-label=Clear tabindex=-1> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg> </button> </nav> <div class=md-search__suggest data-md-component=search-suggest></div> </form> <div class=md-search__output> <div class=md-search__scrollwrap tabindex=0 data-md-scrollfix> <div class=md-search-result data-md-component=search-result> <div class=md-search-result__meta> Initializing search </div> <ol class=md-search-result__list role=presentation></ol> </div> </div> </div> </div> </div> <div class=md-header__source> <a href=https://github.com/django-components/django-components title="Go to repository" class=md-source data-md-component=source> <div class="md-source__icon md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill=currentColor d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg> </div> <div class=md-source__repository> django-components </div> </a> </div> </nav> </header> <div class=md-container data-md-component=container> <nav class=md-tabs aria-label=Tabs data-md-component=tabs> <div class=md-grid> <ul class=md-tabs__list> <li class=md-tabs__item> <a href=../overview/welcome/ class=md-tabs__link> Overview </a> </li> <li class=md-tabs__item> <a href=../getting_started/your_first_component/ class=md-tabs__link> Getting Started </a> </li> <li class=md-tabs__item> <a href=../concepts/fundamentals/single_file_components/ class=md-tabs__link> Concepts </a> </li> <li class=md-tabs__item> <a href=../guides/setup/caching/ class=md-tabs__link> Guides </a> </li> <li class=md-tabs__item> <a href=../reference/api/ class=md-tabs__link> API Documentation </a> </li> <li class="md-tabs__item md-tabs__item--active"> <a href=./ class=md-tabs__link> Release Notes </a> </li> </ul> </div> </nav> <main class=md-main data-md-component=main> <div class="md-main__inner md-grid"> <div class="md-sidebar md-sidebar--primary" data-md-component=sidebar data-md-type=navigation> <div class=md-sidebar__scrollwrap> <div class=md-sidebar__inner> <nav class="md-nav md-nav--primary md-nav--lifted" aria-label=Navigation data-md-level=0> <label class=md-nav__title for=__drawer> <a href=.. title=Django-Components class="md-nav__button md-logo" aria-label=Django-Components data-md-component=logo> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg> </a> Django-Components </label> <div class=md-nav__source> <a href=https://github.com/django-components/django-components title="Go to repository" class=md-source data-md-component=source> <div class="md-source__icon md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill=currentColor d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg> </div> <div class=md-source__repository> django-components </div> </a> </div> <ul class=md-nav__list data-md-scrollfix> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle md-toggle--indeterminate" type=checkbox id=__nav_1> <label class=md-nav__link for=__nav_1 id=__nav_1_label tabindex=0> <span class=md-ellipsis> Overview </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_1_label aria-expanded=false> <label class=md-nav__title for=__nav_1> <span class="md-nav__icon md-icon"></span> Overview </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../overview/welcome/ class=md-nav__link> <span class=md-ellipsis> Welcome to Django Components </span> </a> </li> <li class=md-nav__item> <a href=../overview/compatibility/ class=md-nav__link> <span class=md-ellipsis> Compatibility </span> </a> </li> <li class=md-nav__item> <a href=../overview/installation/ class=md-nav__link> <span class=md-ellipsis> Installation </span> </a> </li> <li class=md-nav__item> <a href=../overview/security_notes/ class=md-nav__link> <span class=md-ellipsis> Security notes 🚨 </span> </a> </li> <li class=md-nav__item> <a href=../overview/migrating/ class=md-nav__link> <span class=md-ellipsis> Migrating </span> </a> </li> <li class=md-nav__item> <a href=../overview/community/ class=md-nav__link> <span class=md-ellipsis> Community </span> </a> </li> <li class=md-nav__item> <a href=../overview/contributing/ class=md-nav__link> <span class=md-ellipsis> Contributing </span> </a> </li> <li class=md-nav__item> <a href=../overview/development/ class=md-nav__link> <span class=md-ellipsis> Development </span> </a> </li> <li class=md-nav__item> <a href=../overview/performance/ class=md-nav__link> <span class=md-ellipsis> Performance </span> </a> </li> <li class=md-nav__item> <a href=../overview/code_of_conduct/ class=md-nav__link> <span class=md-ellipsis> Code of Conduct </span> </a> </li> <li class=md-nav__item> <a href=../overview/license/ class=md-nav__link> <span class=md-ellipsis> License </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle md-toggle--indeterminate" type=checkbox id=__nav_2> <label class=md-nav__link for=__nav_2 id=__nav_2_label tabindex=0> <span class=md-ellipsis> Getting Started </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_2_label aria-expanded=false> <label class=md-nav__title for=__nav_2> <span class="md-nav__icon md-icon"></span> Getting Started </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../getting_started/your_first_component/ class=md-nav__link> <span class=md-ellipsis> Create your first component </span> </a> </li> <li class=md-nav__item> <a href=../getting_started/adding_js_and_css/ class=md-nav__link> <span class=md-ellipsis> Adding JS and CSS </span> </a> </li> <li class=md-nav__item> <a href=../getting_started/components_in_templates/ class=md-nav__link> <span class=md-ellipsis> Components in templates </span> </a> </li> <li class=md-nav__item> <a href=../getting_started/parametrising_components/ class=md-nav__link> <span class=md-ellipsis> Parametrising components </span> </a> </li> <li class=md-nav__item> <a href=../getting_started/adding_slots/ class=md-nav__link> <span class=md-ellipsis> Adding slots </span> </a> </li> <li class=md-nav__item> <a href=../getting_started/rendering_components/ class=md-nav__link> <span class=md-ellipsis> Rendering components </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle md-toggle--indeterminate" type=checkbox id=__nav_3> <label class=md-nav__link for=__nav_3 id=__nav_3_label tabindex=0> <span class=md-ellipsis> Concepts </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_3_label aria-expanded=false> <label class=md-nav__title for=__nav_3> <span class="md-nav__icon md-icon"></span> Concepts </label> <ul class=md-nav__list data-md-scrollfix> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle md-toggle--indeterminate" type=checkbox id=__nav_3_1> <label class=md-nav__link for=__nav_3_1 id=__nav_3_1_label tabindex=0> <span class=md-ellipsis> Fundamentals </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_3_1_label aria-expanded=false> <label class=md-nav__title for=__nav_3_1> <span class="md-nav__icon md-icon"></span> Fundamentals </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../concepts/fundamentals/single_file_components/ class=md-nav__link> <span class=md-ellipsis> Single-file components </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/html_js_css_files/ class=md-nav__link> <span class=md-ellipsis> HTML / JS / CSS files </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/html_js_css_variables/ class=md-nav__link> <span class=md-ellipsis> HTML / JS / CSS variables </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/secondary_js_css_files/ class=md-nav__link> <span class=md-ellipsis> Secondary JS / CSS files </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/component_defaults/ class=md-nav__link> <span class=md-ellipsis> Component defaults </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/render_api/ class=md-nav__link> <span class=md-ellipsis> Render API </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/rendering_components/ class=md-nav__link> <span class=md-ellipsis> Rendering components </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/slots/ class=md-nav__link> <span class=md-ellipsis> Slots </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/template_tag_syntax/ class=md-nav__link> <span class=md-ellipsis> Template tag syntax </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/html_attributes/ class=md-nav__link> <span class=md-ellipsis> HTML attributes </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/component_views_urls/ class=md-nav__link> <span class=md-ellipsis> Component views and URLs </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/http_request/ class=md-nav__link> <span class=md-ellipsis> HTTP Request </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/typing_and_validation/ class=md-nav__link> <span class=md-ellipsis> Typing and validation </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/subclassing_components/ class=md-nav__link> <span class=md-ellipsis> Subclassing components </span> </a> </li> <li class=md-nav__item> <a href=../concepts/fundamentals/autodiscovery/ class=md-nav__link> <span class=md-ellipsis> Autodiscovery </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle md-toggle--indeterminate" type=checkbox id=__nav_3_2> <label class=md-nav__link for=__nav_3_2 id=__nav_3_2_label tabindex=0> <span class=md-ellipsis> Advanced </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_3_2_label aria-expanded=false> <label class=md-nav__title for=__nav_3_2> <span class="md-nav__icon md-icon"></span> Advanced </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../concepts/advanced/rendering_js_css/ class=md-nav__link> <span class=md-ellipsis> Rendering JS / CSS </span> </a> </li> <li class=md-nav__item> <a href=../concepts/advanced/html_fragments/ class=md-nav__link> <span class=md-ellipsis> HTML fragments </span> </a> </li> <li class=md-nav__item> <a href=../concepts/advanced/provide_inject/ class=md-nav__link> <span class=md-ellipsis> Prop drilling and provide / inject </span> </a> </li> <li class=md-nav__item> <a href=../concepts/advanced/hooks/ class=md-nav__link> <span class=md-ellipsis> Lifecycle hooks </span> </a> </li> <li class=md-nav__item> <a href=../concepts/advanced/component_registry/ class=md-nav__link> <span class=md-ellipsis> Registering components </span> </a> </li> <li class=md-nav__item> <a href=../concepts/advanced/component_caching/ class=md-nav__link> <span class=md-ellipsis> Component caching </span> </a> </li> <li class=md-nav__item> <a href=../concepts/advanced/component_context_scope/ class=md-nav__link> <span class=md-ellipsis> Component context and scope </span> </a> </li> <li class=md-nav__item> <a href=../concepts/advanced/template_tags/ class=md-nav__link> <span class=md-ellipsis> Custom template tags </span> </a> </li> <li class=md-nav__item> <a href=../concepts/advanced/tag_formatters/ class=md-nav__link> <span class=md-ellipsis> Tag formatters </span> </a> </li> <li class=md-nav__item> <a href=../concepts/advanced/extensions/ class=md-nav__link> <span class=md-ellipsis> Extensions </span> </a> </li> <li class=md-nav__item> <a href=../concepts/advanced/testing/ class=md-nav__link> <span class=md-ellipsis> Testing </span> </a> </li> <li class=md-nav__item> <a href=../concepts/advanced/component_libraries/ class=md-nav__link> <span class=md-ellipsis> Component libraries </span> </a> </li> </ul> </nav> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle md-toggle--indeterminate" type=checkbox id=__nav_4> <label class=md-nav__link for=__nav_4 id=__nav_4_label tabindex=0> <span class=md-ellipsis> Guides </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_4_label aria-expanded=false> <label class=md-nav__title for=__nav_4> <span class="md-nav__icon md-icon"></span> Guides </label> <ul class=md-nav__list data-md-scrollfix> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle md-toggle--indeterminate" type=checkbox id=__nav_4_1> <label class=md-nav__link for=__nav_4_1 id=__nav_4_1_label tabindex=0> <span class=md-ellipsis> Setup </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_4_1_label aria-expanded=false> <label class=md-nav__title for=__nav_4_1> <span class="md-nav__icon md-icon"></span> Setup </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../guides/setup/caching/ class=md-nav__link> <span class=md-ellipsis> Caching </span> </a> </li> <li class=md-nav__item> <a href=../guides/setup/development_server/ class=md-nav__link> <span class=md-ellipsis> Development server </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle md-toggle--indeterminate" type=checkbox id=__nav_4_2> <label class=md-nav__link for=__nav_4_2 id=__nav_4_2_label tabindex=0> <span class=md-ellipsis> Other </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_4_2_label aria-expanded=false> <label class=md-nav__title for=__nav_4_2> <span class="md-nav__icon md-icon"></span> Other </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../guides/other/troubleshooting/ class=md-nav__link> <span class=md-ellipsis> Troubleshooting </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle md-toggle--indeterminate" type=checkbox id=__nav_4_3> <label class=md-nav__link for=__nav_4_3 id=__nav_4_3_label tabindex=0> <span class=md-ellipsis> Dev Guides </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_4_3_label aria-expanded=false> <label class=md-nav__title for=__nav_4_3> <span class="md-nav__icon md-icon"></span> Dev Guides </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../guides/devguides/dependency_mgmt/ class=md-nav__link> <span class=md-ellipsis> JS and CSS rendering </span> </a> </li> <li class=md-nav__item> <a href=../guides/devguides/slot_rendering/ class=md-nav__link> <span class=md-ellipsis> Slot rendering </span> </a> </li> <li class=md-nav__item> <a href=../guides/devguides/slots_and_blocks/ class=md-nav__link> <span class=md-ellipsis> Using slot and block tags </span> </a> </li> </ul> </nav> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle md-toggle--indeterminate" type=checkbox id=__nav_5> <label class=md-nav__link for=__nav_5 id=__nav_5_label tabindex=0> <span class=md-ellipsis> API Documentation </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_5_label aria-expanded=false> <label class=md-nav__title for=__nav_5> <span class="md-nav__icon md-icon"></span> API Documentation </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../reference/api/ class=md-nav__link> <span class=md-ellipsis> API </span> </a> </li> <li class=md-nav__item> <a href=../reference/commands/ class=md-nav__link> <span class=md-ellipsis> CLI commands </span> </a> </li> <li class=md-nav__item> <a href=../reference/components/ class=md-nav__link> <span class=md-ellipsis> Components </span> </a> </li> <li class=md-nav__item> <a href=../reference/exceptions/ class=md-nav__link> <span class=md-ellipsis> Exceptions </span> </a> </li> <li class=md-nav__item> <a href=../reference/extension_hooks/ class=md-nav__link> <span class=md-ellipsis> Extension hooks </span> </a> </li> <li class=md-nav__item> <a href=../reference/extension_commands/ class=md-nav__link> <span class=md-ellipsis> Extension commands API </span> </a> </li> <li class=md-nav__item> <a href=../reference/extension_urls/ class=md-nav__link> <span class=md-ellipsis> Extension URLs API </span> </a> </li> <li class=md-nav__item> <a href=../reference/settings/ class=md-nav__link> <span class=md-ellipsis> Settings </span> </a> </li> <li class=md-nav__item> <a href=../reference/signals/ class=md-nav__link> <span class=md-ellipsis> Signals </span> </a> </li> <li class=md-nav__item> <a href=../reference/tag_formatters/ class=md-nav__link> <span class=md-ellipsis> Tag formatters </span> </a> </li> <li class=md-nav__item> <a href=../reference/template_tags/ class=md-nav__link> <span class=md-ellipsis> Template tags </span> </a> </li> <li class=md-nav__item> <a href=../reference/template_variables/ class=md-nav__link> <span class=md-ellipsis> Template variables </span> </a> </li> <li class=md-nav__item> <a href=../reference/urls/ class=md-nav__link> <span class=md-ellipsis> URLs </span> </a> </li> <li class=md-nav__item> <a href=../reference/testing_api/ class=md-nav__link> <span class=md-ellipsis> Testing API </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--active"> <input class="md-nav__toggle md-toggle" type=checkbox id=__toc> <label class="md-nav__link md-nav__link--active" for=__toc> <span class=md-ellipsis> Release Notes </span> <span class="md-nav__icon md-icon"></span> </label> <a href=./ class="md-nav__link md-nav__link--active"> <span class=md-ellipsis> Release Notes </span> </a> <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> <label class=md-nav__title for=__toc> <span class="md-nav__icon md-icon"></span> Table of contents </label> <ul class=md-nav__list data-md-component=toc data-md-scrollfix> <li class=md-nav__item> <a href=#v01414 class=md-nav__link> <span class=md-ellipsis> v0.141.4 </span> </a> <nav class=md-nav aria-label=v0.141.4> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01413 class=md-nav__link> <span class=md-ellipsis> v0.141.3 </span> </a> <nav class=md-nav aria-label=v0.141.3> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#fix_1 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01412 class=md-nav__link> <span class=md-ellipsis> v0.141.2 </span> </a> <nav class=md-nav aria-label=v0.141.2> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_2 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01411 class=md-nav__link> <span class=md-ellipsis> v0.141.1 </span> </a> <nav class=md-nav aria-label=v0.141.1> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_3 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01410 class=md-nav__link> <span class=md-ellipsis> v0.141.0 </span> </a> <nav class=md-nav aria-label=v0.141.0> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_1 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#fix_4 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01401 class=md-nav__link> <span class=md-ellipsis> v0.140.1 </span> </a> <nav class=md-nav aria-label=v0.140.1> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_5 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01400 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.140.0 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.140.0"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes class=md-nav__link> <span class=md-ellipsis> 🚨📢 BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#deprecation class=md-nav__link> <span class=md-ellipsis> 🚨📢 Deprecation </span> </a> </li> <li class=md-nav__item> <a href=#feat_2 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_1 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> <li class=md-nav__item> <a href=#fix_6 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01391 class=md-nav__link> <span class=md-ellipsis> v0.139.1 </span> </a> <nav class=md-nav aria-label=v0.139.1> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_7 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor_2 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01390 class=md-nav__link> <span class=md-ellipsis> v0.139.0 </span> </a> <nav class=md-nav aria-label=v0.139.0> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_8 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0138 class=md-nav__link> <span class=md-ellipsis> v0.138 </span> </a> <nav class=md-nav aria-label=v0.138> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_9 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0137 class=md-nav__link> <span class=md-ellipsis> v0.137 </span> </a> <nav class=md-nav aria-label=v0.137> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_3 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#deprecation_1 class=md-nav__link> <span class=md-ellipsis> Deprecation </span> </a> </li> <li class=md-nav__item> <a href=#refactor_3 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0136 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.136 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.136"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_1 class=md-nav__link> <span class=md-ellipsis> 🚨📢 BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#fix_10 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0135 class=md-nav__link> <span class=md-ellipsis> v0.135 </span> </a> <nav class=md-nav aria-label=v0.135> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_4 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#fix_11 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0134 class=md-nav__link> <span class=md-ellipsis> v0.134 </span> </a> <nav class=md-nav aria-label=v0.134> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_12 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0133 class=md-nav__link> <span class=md-ellipsis> v0.133 </span> </a> <nav class=md-nav aria-label=v0.133> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_13 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0132 class=md-nav__link> <span class=md-ellipsis> v0.132 </span> </a> <nav class=md-nav aria-label=v0.132> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_5 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#fix_14 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0131 class=md-nav__link> <span class=md-ellipsis> v0.131 </span> </a> <nav class=md-nav aria-label=v0.131> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_6 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_4 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> <li class=md-nav__item> <a href=#internal class=md-nav__link> <span class=md-ellipsis> Internal </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0130 class=md-nav__link> <span class=md-ellipsis> v0.130 </span> </a> <nav class=md-nav aria-label=v0.130> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_7 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0129 class=md-nav__link> <span class=md-ellipsis> v0.129 </span> </a> <nav class=md-nav aria-label=v0.129> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_15 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0128 class=md-nav__link> <span class=md-ellipsis> v0.128 </span> </a> <nav class=md-nav aria-label=v0.128> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_8 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_5 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> <li class=md-nav__item> <a href=#perf class=md-nav__link> <span class=md-ellipsis> Perf </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0127 class=md-nav__link> <span class=md-ellipsis> v0.127 </span> </a> <nav class=md-nav aria-label=v0.127> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_16 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0126 class=md-nav__link> <span class=md-ellipsis> v0.126 </span> </a> <nav class=md-nav aria-label=v0.126> <ul class=md-nav__list> <li class=md-nav__item> <a href=#refactor_6 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0125 class=md-nav__link> <span class=md-ellipsis> v0.125 </span> </a> <nav class=md-nav aria-label=v0.125> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_9 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_7 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0124 class=md-nav__link> <span class=md-ellipsis> v0.124 </span> </a> <nav class=md-nav aria-label=v0.124> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_10 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_8 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0123 class=md-nav__link> <span class=md-ellipsis> v0.123 </span> </a> <nav class=md-nav aria-label=v0.123> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_17 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0122 class=md-nav__link> <span class=md-ellipsis> v0.122 </span> </a> <nav class=md-nav aria-label=v0.122> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_11 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0121 class=md-nav__link> <span class=md-ellipsis> v0.121 </span> </a> <nav class=md-nav aria-label=v0.121> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_18 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0120 class=md-nav__link> <span class=md-ellipsis> v0.120 </span> </a> <nav class=md-nav aria-label=v0.120> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_19 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0119 class=md-nav__link> <span class=md-ellipsis> v0.119 </span> </a> <nav class=md-nav aria-label=v0.119> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_20 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor_9 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0118 class=md-nav__link> <span class=md-ellipsis> v0.118 </span> </a> <nav class=md-nav aria-label=v0.118> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_12 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0117 class=md-nav__link> <span class=md-ellipsis> v0.117 </span> </a> <nav class=md-nav aria-label=v0.117> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_21 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor_10 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0116 class=md-nav__link> <span class=md-ellipsis> v0.116 </span> </a> <nav class=md-nav aria-label=v0.116> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_22 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0115 class=md-nav__link> <span class=md-ellipsis> v0.115 </span> </a> <nav class=md-nav aria-label=v0.115> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_23 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0114 class=md-nav__link> <span class=md-ellipsis> v0.114 </span> </a> <nav class=md-nav aria-label=v0.114> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_24 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0113 class=md-nav__link> <span class=md-ellipsis> v0.113 </span> </a> <nav class=md-nav aria-label=v0.113> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_25 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0112 class=md-nav__link> <span class=md-ellipsis> v0.112 </span> </a> <nav class=md-nav aria-label=v0.112> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_26 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0111 class=md-nav__link> <span class=md-ellipsis> v0.111 </span> </a> <nav class=md-nav aria-label=v0.111> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_27 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0110 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.110 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.110"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#general class=md-nav__link> <span class=md-ellipsis> General </span> </a> <nav class=md-nav aria-label=General> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_2 class=md-nav__link> <span class=md-ellipsis> 🚨📢 BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#feat_13 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_11 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#tags class=md-nav__link> <span class=md-ellipsis> Tags </span> </a> <nav class=md-nav aria-label=Tags> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_3 class=md-nav__link> <span class=md-ellipsis> 🚨📢 BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#fix_28 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor_12 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#slots class=md-nav__link> <span class=md-ellipsis> Slots </span> </a> <nav class=md-nav aria-label=Slots> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_14 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#fix_29 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor_13 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0100 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.100 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.100"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_4 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#feat_15 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_14 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v097 class=md-nav__link> <span class=md-ellipsis> v0.97 </span> </a> <nav class=md-nav aria-label=v0.97> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_30 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor_15 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v096 class=md-nav__link> <span class=md-ellipsis> v0.96 </span> </a> <nav class=md-nav aria-label=v0.96> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_16 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#095 class=md-nav__link> <span class=md-ellipsis> 0.95 </span> </a> <nav class=md-nav aria-label=0.95> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_17 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_16 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v094 class=md-nav__link> <span class=md-ellipsis> v0.94 </span> </a> <nav class=md-nav aria-label=v0.94> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_18 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v093 class=md-nav__link> <span class=md-ellipsis> v0.93 </span> </a> <nav class=md-nav aria-label=v0.93> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_19 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v092 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.92 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.92"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_5 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#feat_20 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v090 class=md-nav__link> <span class=md-ellipsis> v0.90 </span> </a> <nav class=md-nav aria-label=v0.90> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_21 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v085 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.85 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.85"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_6 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v081 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.81 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.81"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_7 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#feat_22 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v080 class=md-nav__link> <span class=md-ellipsis> v0.80 </span> </a> <nav class=md-nav aria-label=v0.80> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_23 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v079 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.79 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.79"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_8 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v077 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.77 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.77"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking class=md-nav__link> <span class=md-ellipsis> BREAKING </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v074 class=md-nav__link> <span class=md-ellipsis> v0.74 </span> </a> <nav class=md-nav aria-label=v0.74> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_24 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v070 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.70 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.70"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_9 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v067 class=md-nav__link> <span class=md-ellipsis> v0.67 </span> </a> <nav class=md-nav aria-label=v0.67> <ul class=md-nav__list> <li class=md-nav__item> <a href=#refactor_17 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v050 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.50 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.50"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_10 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v034 class=md-nav__link> <span class=md-ellipsis> v0.34 </span> </a> <nav class=md-nav aria-label=v0.34> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_25 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v028 class=md-nav__link> <span class=md-ellipsis> v0.28 </span> </a> <nav class=md-nav aria-label=v0.28> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_26 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v027 class=md-nav__link> <span class=md-ellipsis> v0.27 </span> </a> <nav class=md-nav aria-label=v0.27> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_27 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v026 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.26 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.26"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_11 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v022 class=md-nav__link> <span class=md-ellipsis> v0.22 </span> </a> <nav class=md-nav aria-label=v0.22> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_28 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v017 class=md-nav__link> <span class=md-ellipsis> v0.17 </span> </a> <nav class=md-nav aria-label=v0.17> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_12 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> </ul> </nav> </li> </ul> </nav> </li> </ul> </nav> </div> </div> </div> <div class="md-sidebar md-sidebar--secondary" data-md-component=sidebar data-md-type=toc> <div class=md-sidebar__scrollwrap> <div class=md-sidebar__inner> <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> <label class=md-nav__title for=__toc> <span class="md-nav__icon md-icon"></span> Table of contents </label> <ul class=md-nav__list data-md-component=toc data-md-scrollfix> <li class=md-nav__item> <a href=#v01414 class=md-nav__link> <span class=md-ellipsis> v0.141.4 </span> </a> <nav class=md-nav aria-label=v0.141.4> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01413 class=md-nav__link> <span class=md-ellipsis> v0.141.3 </span> </a> <nav class=md-nav aria-label=v0.141.3> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#fix_1 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01412 class=md-nav__link> <span class=md-ellipsis> v0.141.2 </span> </a> <nav class=md-nav aria-label=v0.141.2> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_2 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01411 class=md-nav__link> <span class=md-ellipsis> v0.141.1 </span> </a> <nav class=md-nav aria-label=v0.141.1> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_3 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01410 class=md-nav__link> <span class=md-ellipsis> v0.141.0 </span> </a> <nav class=md-nav aria-label=v0.141.0> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_1 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#fix_4 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01401 class=md-nav__link> <span class=md-ellipsis> v0.140.1 </span> </a> <nav class=md-nav aria-label=v0.140.1> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_5 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01400 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.140.0 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.140.0"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes class=md-nav__link> <span class=md-ellipsis> 🚨📢 BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#deprecation class=md-nav__link> <span class=md-ellipsis> 🚨📢 Deprecation </span> </a> </li> <li class=md-nav__item> <a href=#feat_2 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_1 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> <li class=md-nav__item> <a href=#fix_6 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01391 class=md-nav__link> <span class=md-ellipsis> v0.139.1 </span> </a> <nav class=md-nav aria-label=v0.139.1> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_7 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor_2 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v01390 class=md-nav__link> <span class=md-ellipsis> v0.139.0 </span> </a> <nav class=md-nav aria-label=v0.139.0> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_8 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0138 class=md-nav__link> <span class=md-ellipsis> v0.138 </span> </a> <nav class=md-nav aria-label=v0.138> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_9 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0137 class=md-nav__link> <span class=md-ellipsis> v0.137 </span> </a> <nav class=md-nav aria-label=v0.137> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_3 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#deprecation_1 class=md-nav__link> <span class=md-ellipsis> Deprecation </span> </a> </li> <li class=md-nav__item> <a href=#refactor_3 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0136 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.136 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.136"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_1 class=md-nav__link> <span class=md-ellipsis> 🚨📢 BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#fix_10 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0135 class=md-nav__link> <span class=md-ellipsis> v0.135 </span> </a> <nav class=md-nav aria-label=v0.135> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_4 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#fix_11 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0134 class=md-nav__link> <span class=md-ellipsis> v0.134 </span> </a> <nav class=md-nav aria-label=v0.134> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_12 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0133 class=md-nav__link> <span class=md-ellipsis> v0.133 </span> </a> <nav class=md-nav aria-label=v0.133> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_13 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0132 class=md-nav__link> <span class=md-ellipsis> v0.132 </span> </a> <nav class=md-nav aria-label=v0.132> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_5 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#fix_14 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0131 class=md-nav__link> <span class=md-ellipsis> v0.131 </span> </a> <nav class=md-nav aria-label=v0.131> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_6 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_4 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> <li class=md-nav__item> <a href=#internal class=md-nav__link> <span class=md-ellipsis> Internal </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0130 class=md-nav__link> <span class=md-ellipsis> v0.130 </span> </a> <nav class=md-nav aria-label=v0.130> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_7 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0129 class=md-nav__link> <span class=md-ellipsis> v0.129 </span> </a> <nav class=md-nav aria-label=v0.129> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_15 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0128 class=md-nav__link> <span class=md-ellipsis> v0.128 </span> </a> <nav class=md-nav aria-label=v0.128> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_8 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_5 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> <li class=md-nav__item> <a href=#perf class=md-nav__link> <span class=md-ellipsis> Perf </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0127 class=md-nav__link> <span class=md-ellipsis> v0.127 </span> </a> <nav class=md-nav aria-label=v0.127> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_16 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0126 class=md-nav__link> <span class=md-ellipsis> v0.126 </span> </a> <nav class=md-nav aria-label=v0.126> <ul class=md-nav__list> <li class=md-nav__item> <a href=#refactor_6 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0125 class=md-nav__link> <span class=md-ellipsis> v0.125 </span> </a> <nav class=md-nav aria-label=v0.125> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_9 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_7 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0124 class=md-nav__link> <span class=md-ellipsis> v0.124 </span> </a> <nav class=md-nav aria-label=v0.124> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_10 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_8 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0123 class=md-nav__link> <span class=md-ellipsis> v0.123 </span> </a> <nav class=md-nav aria-label=v0.123> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_17 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0122 class=md-nav__link> <span class=md-ellipsis> v0.122 </span> </a> <nav class=md-nav aria-label=v0.122> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_11 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0121 class=md-nav__link> <span class=md-ellipsis> v0.121 </span> </a> <nav class=md-nav aria-label=v0.121> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_18 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0120 class=md-nav__link> <span class=md-ellipsis> v0.120 </span> </a> <nav class=md-nav aria-label=v0.120> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_19 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0119 class=md-nav__link> <span class=md-ellipsis> v0.119 </span> </a> <nav class=md-nav aria-label=v0.119> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_20 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor_9 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0118 class=md-nav__link> <span class=md-ellipsis> v0.118 </span> </a> <nav class=md-nav aria-label=v0.118> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_12 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0117 class=md-nav__link> <span class=md-ellipsis> v0.117 </span> </a> <nav class=md-nav aria-label=v0.117> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_21 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor_10 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0116 class=md-nav__link> <span class=md-ellipsis> v0.116 </span> </a> <nav class=md-nav aria-label=v0.116> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_22 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0115 class=md-nav__link> <span class=md-ellipsis> v0.115 </span> </a> <nav class=md-nav aria-label=v0.115> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_23 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0114 class=md-nav__link> <span class=md-ellipsis> v0.114 </span> </a> <nav class=md-nav aria-label=v0.114> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_24 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0113 class=md-nav__link> <span class=md-ellipsis> v0.113 </span> </a> <nav class=md-nav aria-label=v0.113> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_25 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0112 class=md-nav__link> <span class=md-ellipsis> v0.112 </span> </a> <nav class=md-nav aria-label=v0.112> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_26 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0111 class=md-nav__link> <span class=md-ellipsis> v0.111 </span> </a> <nav class=md-nav aria-label=v0.111> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_27 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0110 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.110 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.110"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#general class=md-nav__link> <span class=md-ellipsis> General </span> </a> <nav class=md-nav aria-label=General> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_2 class=md-nav__link> <span class=md-ellipsis> 🚨📢 BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#feat_13 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_11 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#tags class=md-nav__link> <span class=md-ellipsis> Tags </span> </a> <nav class=md-nav aria-label=Tags> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_3 class=md-nav__link> <span class=md-ellipsis> 🚨📢 BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#fix_28 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor_12 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#slots class=md-nav__link> <span class=md-ellipsis> Slots </span> </a> <nav class=md-nav aria-label=Slots> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_14 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#fix_29 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor_13 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v0100 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.100 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.100"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_4 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#feat_15 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_14 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v097 class=md-nav__link> <span class=md-ellipsis> v0.97 </span> </a> <nav class=md-nav aria-label=v0.97> <ul class=md-nav__list> <li class=md-nav__item> <a href=#fix_30 class=md-nav__link> <span class=md-ellipsis> Fix </span> </a> </li> <li class=md-nav__item> <a href=#refactor_15 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v096 class=md-nav__link> <span class=md-ellipsis> v0.96 </span> </a> <nav class=md-nav aria-label=v0.96> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_16 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#095 class=md-nav__link> <span class=md-ellipsis> 0.95 </span> </a> <nav class=md-nav aria-label=0.95> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_17 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> <li class=md-nav__item> <a href=#refactor_16 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v094 class=md-nav__link> <span class=md-ellipsis> v0.94 </span> </a> <nav class=md-nav aria-label=v0.94> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_18 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v093 class=md-nav__link> <span class=md-ellipsis> v0.93 </span> </a> <nav class=md-nav aria-label=v0.93> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_19 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v092 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.92 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.92"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_5 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#feat_20 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v090 class=md-nav__link> <span class=md-ellipsis> v0.90 </span> </a> <nav class=md-nav aria-label=v0.90> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_21 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v085 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.85 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.85"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_6 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v081 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.81 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.81"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_7 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> <li class=md-nav__item> <a href=#feat_22 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v080 class=md-nav__link> <span class=md-ellipsis> v0.80 </span> </a> <nav class=md-nav aria-label=v0.80> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_23 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v079 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.79 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.79"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_8 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v077 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.77 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.77"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking class=md-nav__link> <span class=md-ellipsis> BREAKING </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v074 class=md-nav__link> <span class=md-ellipsis> v0.74 </span> </a> <nav class=md-nav aria-label=v0.74> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_24 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v070 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.70 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.70"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_9 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v067 class=md-nav__link> <span class=md-ellipsis> v0.67 </span> </a> <nav class=md-nav aria-label=v0.67> <ul class=md-nav__list> <li class=md-nav__item> <a href=#refactor_17 class=md-nav__link> <span class=md-ellipsis> Refactor </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v050 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.50 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.50"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_10 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v034 class=md-nav__link> <span class=md-ellipsis> v0.34 </span> </a> <nav class=md-nav aria-label=v0.34> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_25 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v028 class=md-nav__link> <span class=md-ellipsis> v0.28 </span> </a> <nav class=md-nav aria-label=v0.28> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_26 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v027 class=md-nav__link> <span class=md-ellipsis> v0.27 </span> </a> <nav class=md-nav aria-label=v0.27> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_27 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v026 class=md-nav__link> <span class=md-ellipsis> 🚨📢 v0.26 </span> </a> <nav class=md-nav aria-label="🚨📢 v0.26"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_11 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v022 class=md-nav__link> <span class=md-ellipsis> v0.22 </span> </a> <nav class=md-nav aria-label=v0.22> <ul class=md-nav__list> <li class=md-nav__item> <a href=#feat_28 class=md-nav__link> <span class=md-ellipsis> Feat </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#v017 class=md-nav__link> <span class=md-ellipsis> v0.17 </span> </a> <nav class=md-nav aria-label=v0.17> <ul class=md-nav__list> <li class=md-nav__item> <a href=#breaking-changes_12 class=md-nav__link> <span class=md-ellipsis> BREAKING CHANGES </span> </a> </li> </ul> </nav> </li> </ul> </nav> </div> </div> </div> <div class=md-content data-md-component=content> <article class="md-content__inner md-typeset"> <a href=https://github.com/django-components/django-components/edit/master/docs/release_notes.md title="Edit this page" class="md-content__button md-icon" rel=edit> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M10 20H6V4h7v5h5v3.1l2-2V8l-6-6H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h4zm10.2-7c.1 0 .3.1.4.2l1.3 1.3c.2.2.2.6 0 .8l-1 1-2.1-2.1 1-1c.1-.1.2-.2.4-.2m0 3.9L14.1 23H12v-2.1l6.1-6.1z"/></svg> </a> <a href=https://github.com/django-components/django-components/raw/master/docs/release_notes.md title="View source of this page" class="md-content__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M17 18c.56 0 1 .44 1 1s-.44 1-1 1-1-.44-1-1 .44-1 1-1m0-3c-2.73 0-5.06 1.66-6 4 .94 2.34 3.27 4 6 4s5.06-1.66 6-4c-.94-2.34-3.27-4-6-4m0 6.5a2.5 2.5 0 0 1-2.5-2.5 2.5 2.5 0 0 1 2.5-2.5 2.5 2.5 0 0 1 2.5 2.5 2.5 2.5 0 0 1-2.5 2.5M9.27 20H6V4h7v5h5v4.07c.7.08 1.36.25 2 .49V8l-6-6H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h4.5a8.2 8.2 0 0 1-1.23-2"/></svg> </a> <h1 id=release-notes>Release notes<a class=headerlink href=#release-notes title="Permanent link">¤</a></h1> <h2 id=v01414>v0.141.4<a class=headerlink href=#v01414 title="Permanent link">¤</a></h2> <h4 id=fix>Fix<a class=headerlink href=#fix title="Permanent link">¤</a></h4> <ul> <li>Fix compatibility with Django's <code>{% include %}</code> and <code>{% extends %}</code> tags. See <a href=https://github.com/django-components/django-components/issues/1325>https://github.com/django-components/django-components/issues/1325</a></li> </ul> <h2 id=v01413>v0.141.3<a class=headerlink href=#v01413 title="Permanent link">¤</a></h2> <h4 id=feat>Feat<a class=headerlink href=#feat title="Permanent link">¤</a></h4> <ul> <li> <p>You no longer need to render the whole page with the <code>document</code> strategy to use HTML fragments.</p> <p>Previously, if you wanted to insert rendered components as HTML fragments, you had to ensure that the HTML document it was being inserted into was rendered with the <code>document</code> strategy.</p> <p>Now, when you render components with <code>fragment</code> strategy, they know how to fetch their own JS / CSS dependencies.</p> </li> </ul> <h4 id=fix_1>Fix<a class=headerlink href=#fix_1 title="Permanent link">¤</a></h4> <ul> <li>Fix compatibility with django-template-partials (<a href=https://github.com/django-components/django-components/issues/1322>#1322</a>)</li> </ul> <h2 id=v01412>v0.141.2<a class=headerlink href=#v01412 title="Permanent link">¤</a></h2> <h4 id=fix_2>Fix<a class=headerlink href=#fix_2 title="Permanent link">¤</a></h4> <ul> <li>Fix bug where JS and CSS were missing when <code>{% component %}</code> tag was inside <code>{% include %}</code> tag (<a href=https://github.com/django-components/django-components/issues/1296>#1296</a>)</li> </ul> <h2 id=v01411>v0.141.1<a class=headerlink href=#v01411 title="Permanent link">¤</a></h2> <h4 id=fix_3>Fix<a class=headerlink href=#fix_3 title="Permanent link">¤</a></h4> <ul> <li> <p>Components' JS and CSS scripts (e.g. from <code>Component.js</code> or <code>Component.js_file</code>) are now cached at class creation time.</p> <p>This means that when you now restart the server while having a page opened in the browser, the JS / CSS files are immediately available.</p> <p>Previously, the JS/CSS were cached only after the components were rendered. So you had to reload the page to trigger the rendering, in order to make the JS/CSS files available.</p> </li> <li> <p>Fix the default cache for JS / CSS scripts to be unbounded.</p> <p>Previously, the default cache for the JS/CSS scripts (<code>LocMemCache</code>) was accidentally limited to 300 entries (~150 components).</p> </li> <li> <p>Do not send <code>template_rendered</code> signal when rendering a component with no template. (<a href=https://github.com/django-components/django-components/issues/1277>#1277</a>)</p> </li> </ul> <h2 id=v01410>v0.141.0<a class=headerlink href=#v01410 title="Permanent link">¤</a></h2> <h4 id=feat_1>Feat<a class=headerlink href=#feat_1 title="Permanent link">¤</a></h4> <ul> <li> <p>New extension hooks <code>on_template_loaded</code>, <code>on_js_loaded</code>, <code>on_css_loaded</code>, and <code>on_template_compiled</code></p> <p>The first 3 hooks are called when Component's template / JS / CSS is loaded as a string.</p> <p>The <code>on_template_compiled</code> hook is called when Component's template is compiled to a Template.</p> <p>The <code>on_xx_loaded</code> hooks can modify the content by returning the new value.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-0-1 name=__codelineno-0-1 href=#__codelineno-0-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyExtension</span><span class=p>(</span><span class=n>ComponentExtension</span><span class=p>):</span>
|
|
<a id=__codelineno-0-2 name=__codelineno-0-2 href=#__codelineno-0-2></a> <span class=k>def</span><span class=w> </span><span class=nf>on_template_loaded</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>ctx</span><span class=p>:</span> <span class=n>OnTemplateLoadedContext</span><span class=p>)</span> <span class=o>-></span> <span class=n>Optional</span><span class=p>[</span><span class=nb>str</span><span class=p>]:</span>
|
|
<a id=__codelineno-0-3 name=__codelineno-0-3 href=#__codelineno-0-3></a> <span class=k>return</span> <span class=n>ctx</span><span class=o>.</span><span class=n>content</span> <span class=o>+</span> <span class=s2>"<!-- Hello! -->"</span>
|
|
<a id=__codelineno-0-4 name=__codelineno-0-4 href=#__codelineno-0-4></a>
|
|
<a id=__codelineno-0-5 name=__codelineno-0-5 href=#__codelineno-0-5></a> <span class=k>def</span><span class=w> </span><span class=nf>on_js_loaded</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>ctx</span><span class=p>:</span> <span class=n>OnJsLoadedContext</span><span class=p>)</span> <span class=o>-></span> <span class=n>Optional</span><span class=p>[</span><span class=nb>str</span><span class=p>]:</span>
|
|
<a id=__codelineno-0-6 name=__codelineno-0-6 href=#__codelineno-0-6></a> <span class=k>return</span> <span class=n>ctx</span><span class=o>.</span><span class=n>content</span> <span class=o>+</span> <span class=s2>"// Hello!"</span>
|
|
<a id=__codelineno-0-7 name=__codelineno-0-7 href=#__codelineno-0-7></a>
|
|
<a id=__codelineno-0-8 name=__codelineno-0-8 href=#__codelineno-0-8></a> <span class=k>def</span><span class=w> </span><span class=nf>on_css_loaded</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>ctx</span><span class=p>:</span> <span class=n>OnCssLoadedContext</span><span class=p>)</span> <span class=o>-></span> <span class=n>Optional</span><span class=p>[</span><span class=nb>str</span><span class=p>]:</span>
|
|
<a id=__codelineno-0-9 name=__codelineno-0-9 href=#__codelineno-0-9></a> <span class=k>return</span> <span class=n>ctx</span><span class=o>.</span><span class=n>content</span> <span class=o>+</span> <span class=s2>"/* Hello! */"</span>
|
|
</code></pre></div> <p>See all <a href=https://django-components.github.io/django-components/0.141.0/reference/extension_hooks/ >Extension hooks</a>.</p> </li> </ul> <h4 id=fix_4>Fix<a class=headerlink href=#fix_4 title="Permanent link">¤</a></h4> <ul> <li> <p>Subclassing - Previously, if a parent component defined <code>Component.template</code> or <code>Component.template_file</code>, it's subclass would use the same <code>Template</code> instance.</p> <p>This could lead to unexpected behavior, where a change to the template of the subclass would also change the template of the parent class.</p> <p>Now, each subclass has it's own <code>Template</code> instance, and changes to the template of the subclass do not affect the template of the parent class.</p> </li> <li> <p>Fix Django failing to restart due to "TypeError: 'Dynamic' object is not iterable" (<a href=https://github.com/django-components/django-components/issues/1232>#1232</a>)</p> </li> <li> <p>Fix bug when error formatting failed when error value was not a string.</p> </li> </ul> <h4 id=refactor>Refactor<a class=headerlink href=#refactor title="Permanent link">¤</a></h4> <ul> <li><code>components ext run</code> CLI command now allows to call only those extensions that actually have subcommands.</li> </ul> <h2 id=v01401>v0.140.1<a class=headerlink href=#v01401 title="Permanent link">¤</a></h2> <h4 id=fix_5>Fix<a class=headerlink href=#fix_5 title="Permanent link">¤</a></h4> <ul> <li>Fix typo preventing benchmarking (<a href=https://github.com/django-components/django-components/pull/1235>#1235</a>)</li> </ul> <h2 id=v01400>🚨📢 v0.140.0<a class=headerlink href=#v01400 title="Permanent link">¤</a></h2> <p>⚠️ Major release ⚠️ - Please test thoroughly before / after upgrading.</p> <p>This is the biggest step towards v1. While this version introduces many small API changes, we don't expect to make further changes to the affected parts before v1.</p> <p>For more details see <a href=https://github.com/django-components/django-components/issues/433>#433</a>.</p> <p>Summary:</p> <ul> <li>Overhauled typing system</li> <li>Middleware removed, no longer needed</li> <li><code>get_template_data()</code> is the new canonical way to define template data. <code>get_context_data()</code> is now deprecated but will remain until v2.</li> <li>Slots API polished and prepared for v1.</li> <li>Merged <code>Component.Url</code> with <code>Component.View</code></li> <li>Added <code>Component.args</code>, <code>Component.kwargs</code>, <code>Component.slots</code>, <code>Component.context</code></li> <li>Added <code>{{ component_vars.args }}</code>, <code>{{ component_vars.kwargs }}</code>, <code>{{ component_vars.slots }}</code></li> <li>You should no longer instantiate <code>Component</code> instances. Instead, call <code>Component.render()</code> or <code>Component.render_to_response()</code> directly.</li> <li>Component caching can now consider slots (opt-in)</li> <li>And lot more...</li> </ul> <h4 id=breaking-changes>🚨📢 BREAKING CHANGES<a class=headerlink href=#breaking-changes title="Permanent link">¤</a></h4> <p><strong>Middleware</strong></p> <ul> <li> <p>The middleware <code>ComponentDependencyMiddleware</code> was removed as it is no longer needed.</p> <p>The middleware served one purpose - to render the JS and CSS dependencies of components when you rendered templates with <code>Template.render()</code> or <code>django.shortcuts.render()</code> and those templates contained <code>{% component %}</code> tags.</p> <ul> <li>NOTE: If you rendered HTML with <code>Component.render()</code> or <code>Component.render_to_response()</code>, the JS and CSS were already rendered.</li> </ul> <p>Now, the JS and CSS dependencies of components are automatically rendered, even when you render Templates with <code>Template.render()</code> or <code>django.shortcuts.render()</code>.</p> <p>To disable this behavior, set the <code>DJC_DEPS_STRATEGY</code> context key to <code>"ignore"</code> when rendering the template:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-1-1 name=__codelineno-1-1 href=#__codelineno-1-1></a><span class=c1># With `Template.render()`:</span>
|
|
<a id=__codelineno-1-2 name=__codelineno-1-2 href=#__codelineno-1-2></a><span class=n>template</span> <span class=o>=</span> <span class=n>Template</span><span class=p>(</span><span class=n>template_str</span><span class=p>)</span>
|
|
<a id=__codelineno-1-3 name=__codelineno-1-3 href=#__codelineno-1-3></a><span class=n>rendered</span> <span class=o>=</span> <span class=n>template</span><span class=o>.</span><span class=n>render</span><span class=p>(</span><span class=n>Context</span><span class=p>({</span><span class=s2>"DJC_DEPS_STRATEGY"</span><span class=p>:</span> <span class=s2>"ignore"</span><span class=p>}))</span>
|
|
<a id=__codelineno-1-4 name=__codelineno-1-4 href=#__codelineno-1-4></a>
|
|
<a id=__codelineno-1-5 name=__codelineno-1-5 href=#__codelineno-1-5></a><span class=c1># Or with django.shortcuts.render():</span>
|
|
<a id=__codelineno-1-6 name=__codelineno-1-6 href=#__codelineno-1-6></a><span class=kn>from</span><span class=w> </span><span class=nn>django.shortcuts</span><span class=w> </span><span class=kn>import</span> <span class=n>render</span>
|
|
<a id=__codelineno-1-7 name=__codelineno-1-7 href=#__codelineno-1-7></a><span class=n>rendered</span> <span class=o>=</span> <span class=n>render</span><span class=p>(</span>
|
|
<a id=__codelineno-1-8 name=__codelineno-1-8 href=#__codelineno-1-8></a> <span class=n>request</span><span class=p>,</span>
|
|
<a id=__codelineno-1-9 name=__codelineno-1-9 href=#__codelineno-1-9></a> <span class=s2>"my_template.html"</span><span class=p>,</span>
|
|
<a id=__codelineno-1-10 name=__codelineno-1-10 href=#__codelineno-1-10></a> <span class=n>context</span><span class=o>=</span><span class=p>{</span><span class=s2>"DJC_DEPS_STRATEGY"</span><span class=p>:</span> <span class=s2>"ignore"</span><span class=p>},</span>
|
|
<a id=__codelineno-1-11 name=__codelineno-1-11 href=#__codelineno-1-11></a><span class=p>)</span>
|
|
</code></pre></div> <p>In fact, you can set the <code>DJC_DEPS_STRATEGY</code> context key to any of the strategies:</p> <ul> <li><code>"document"</code></li> <li><code>"fragment"</code></li> <li><code>"simple"</code></li> <li><code>"prepend"</code></li> <li><code>"append"</code></li> <li><code>"ignore"</code></li> </ul> <p>See <a href=https://django-components.github.io/django-components/0.140.1/concepts/advanced/rendering_js_css/ >Dependencies rendering</a> for more info.</p> </li> </ul> <p><strong>Typing</strong></p> <ul> <li> <p>Component typing no longer uses generics. Instead, the types are now defined as class attributes of the component class.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-2-1 name=__codelineno-2-1 href=#__codelineno-2-1></a><span class=n>Args</span> <span class=o>=</span> <span class=n>Tuple</span><span class=p>[</span><span class=nb>float</span><span class=p>,</span> <span class=nb>str</span><span class=p>]</span>
|
|
<a id=__codelineno-2-2 name=__codelineno-2-2 href=#__codelineno-2-2></a>
|
|
<a id=__codelineno-2-3 name=__codelineno-2-3 href=#__codelineno-2-3></a><span class=k>class</span><span class=w> </span><span class=nc>Button</span><span class=p>(</span><span class=n>Component</span><span class=p>[</span><span class=n>Args</span><span class=p>]):</span>
|
|
<a id=__codelineno-2-4 name=__codelineno-2-4 href=#__codelineno-2-4></a> <span class=k>pass</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-3-1 name=__codelineno-3-1 href=#__codelineno-3-1></a><span class=k>class</span><span class=w> </span><span class=nc>Button</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-3-2 name=__codelineno-3-2 href=#__codelineno-3-2></a> <span class=k>class</span><span class=w> </span><span class=nc>Args</span><span class=p>(</span><span class=n>NamedTuple</span><span class=p>):</span>
|
|
<a id=__codelineno-3-3 name=__codelineno-3-3 href=#__codelineno-3-3></a> <span class=n>size</span><span class=p>:</span> <span class=nb>float</span>
|
|
<a id=__codelineno-3-4 name=__codelineno-3-4 href=#__codelineno-3-4></a> <span class=n>text</span><span class=p>:</span> <span class=nb>str</span>
|
|
</code></pre></div> <p>See <a href=https://django-components.github.io/django-components/0.140.1/concepts/fundamentals/typing_and_validation/#migrating-from-generics-to-class-attributes>Migrating from generics to class attributes</a> for more info. - Removed <code>EmptyTuple</code> and <code>EmptyDict</code> types. Instead, there is now a single <code>Empty</code> type.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-4-1 name=__codelineno-4-1 href=#__codelineno-4-1></a><span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>Component</span><span class=p>,</span> <span class=n>Empty</span>
|
|
<a id=__codelineno-4-2 name=__codelineno-4-2 href=#__codelineno-4-2></a>
|
|
<a id=__codelineno-4-3 name=__codelineno-4-3 href=#__codelineno-4-3></a><span class=k>class</span><span class=w> </span><span class=nc>Button</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-4-4 name=__codelineno-4-4 href=#__codelineno-4-4></a> <span class=n>template</span> <span class=o>=</span> <span class=s2>"Hello"</span>
|
|
<a id=__codelineno-4-5 name=__codelineno-4-5 href=#__codelineno-4-5></a>
|
|
<a id=__codelineno-4-6 name=__codelineno-4-6 href=#__codelineno-4-6></a> <span class=n>Args</span> <span class=o>=</span> <span class=n>Empty</span>
|
|
<a id=__codelineno-4-7 name=__codelineno-4-7 href=#__codelineno-4-7></a> <span class=n>Kwargs</span> <span class=o>=</span> <span class=n>Empty</span>
|
|
</code></pre></div> </li> </ul> <p><strong>Component API</strong></p> <ul> <li> <p>The interface of the not-yet-released <code>get_js_data()</code> and <code>get_css_data()</code> methods has changed to match <code>get_template_data()</code>.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-5-1 name=__codelineno-5-1 href=#__codelineno-5-1></a><span class=k>def</span><span class=w> </span><span class=nf>get_js_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=o>*</span><span class=n>args</span><span class=p>,</span> <span class=o>**</span><span class=n>kwargs</span><span class=p>):</span>
|
|
<a id=__codelineno-5-2 name=__codelineno-5-2 href=#__codelineno-5-2></a><span class=k>def</span><span class=w> </span><span class=nf>get_css_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=o>*</span><span class=n>args</span><span class=p>,</span> <span class=o>**</span><span class=n>kwargs</span><span class=p>):</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-6-1 name=__codelineno-6-1 href=#__codelineno-6-1></a><span class=k>def</span><span class=w> </span><span class=nf>get_js_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>args</span><span class=p>,</span> <span class=n>kwargs</span><span class=p>,</span> <span class=n>slots</span><span class=p>,</span> <span class=n>context</span><span class=p>):</span>
|
|
<a id=__codelineno-6-2 name=__codelineno-6-2 href=#__codelineno-6-2></a><span class=k>def</span><span class=w> </span><span class=nf>get_css_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>args</span><span class=p>,</span> <span class=n>kwargs</span><span class=p>,</span> <span class=n>slots</span><span class=p>,</span> <span class=n>context</span><span class=p>):</span>
|
|
</code></pre></div> </li> <li> <p>Arguments in <code>Component.render_to_response()</code> have changed to match that of <code>Component.render()</code>.</p> <p>Please ensure that you pass the parameters as kwargs, not as positional arguments, to avoid breaking changes.</p> <p>The signature changed, moving the <code>args</code> and <code>kwargs</code> parameters to 2nd and 3rd position.</p> <p>Next, the <code>render_dependencies</code> parameter was added to match <code>Component.render()</code>.</p> <p>Lastly:</p> <ul> <li>Previously, any extra ARGS and KWARGS were passed to the <code>response_class</code>.</li> <li>Now, only extra KWARGS will be passed to the <code>response_class</code>.</li> </ul> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-7-1 name=__codelineno-7-1 href=#__codelineno-7-1></a> <span class=k>def</span><span class=w> </span><span class=nf>render_to_response</span><span class=p>(</span>
|
|
<a id=__codelineno-7-2 name=__codelineno-7-2 href=#__codelineno-7-2></a> <span class=bp>cls</span><span class=p>,</span>
|
|
<a id=__codelineno-7-3 name=__codelineno-7-3 href=#__codelineno-7-3></a> <span class=n>context</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>Union</span><span class=p>[</span><span class=n>Dict</span><span class=p>[</span><span class=nb>str</span><span class=p>,</span> <span class=n>Any</span><span class=p>],</span> <span class=n>Context</span><span class=p>]]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-7-4 name=__codelineno-7-4 href=#__codelineno-7-4></a> <span class=n>slots</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>SlotsType</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-7-5 name=__codelineno-7-5 href=#__codelineno-7-5></a> <span class=n>escape_slots_content</span><span class=p>:</span> <span class=nb>bool</span> <span class=o>=</span> <span class=kc>True</span><span class=p>,</span>
|
|
<a id=__codelineno-7-6 name=__codelineno-7-6 href=#__codelineno-7-6></a> <span class=n>args</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>ArgsType</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-7-7 name=__codelineno-7-7 href=#__codelineno-7-7></a> <span class=n>kwargs</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>KwargsType</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-7-8 name=__codelineno-7-8 href=#__codelineno-7-8></a> <span class=n>deps_strategy</span><span class=p>:</span> <span class=n>DependenciesStrategy</span> <span class=o>=</span> <span class=s2>"document"</span><span class=p>,</span>
|
|
<a id=__codelineno-7-9 name=__codelineno-7-9 href=#__codelineno-7-9></a> <span class=n>request</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>HttpRequest</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-7-10 name=__codelineno-7-10 href=#__codelineno-7-10></a> <span class=o>*</span><span class=n>response_args</span><span class=p>:</span> <span class=n>Any</span><span class=p>,</span>
|
|
<a id=__codelineno-7-11 name=__codelineno-7-11 href=#__codelineno-7-11></a> <span class=o>**</span><span class=n>response_kwargs</span><span class=p>:</span> <span class=n>Any</span><span class=p>,</span>
|
|
<a id=__codelineno-7-12 name=__codelineno-7-12 href=#__codelineno-7-12></a> <span class=p>)</span> <span class=o>-></span> <span class=n>HttpResponse</span><span class=p>:</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-8-1 name=__codelineno-8-1 href=#__codelineno-8-1></a><span class=k>def</span><span class=w> </span><span class=nf>render_to_response</span><span class=p>(</span>
|
|
<a id=__codelineno-8-2 name=__codelineno-8-2 href=#__codelineno-8-2></a> <span class=n>context</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>Union</span><span class=p>[</span><span class=n>Dict</span><span class=p>[</span><span class=nb>str</span><span class=p>,</span> <span class=n>Any</span><span class=p>],</span> <span class=n>Context</span><span class=p>]]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-8-3 name=__codelineno-8-3 href=#__codelineno-8-3></a> <span class=n>args</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>Any</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-8-4 name=__codelineno-8-4 href=#__codelineno-8-4></a> <span class=n>kwargs</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>Any</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-8-5 name=__codelineno-8-5 href=#__codelineno-8-5></a> <span class=n>slots</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>Any</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-8-6 name=__codelineno-8-6 href=#__codelineno-8-6></a> <span class=n>deps_strategy</span><span class=p>:</span> <span class=n>DependenciesStrategy</span> <span class=o>=</span> <span class=s2>"document"</span><span class=p>,</span>
|
|
<a id=__codelineno-8-7 name=__codelineno-8-7 href=#__codelineno-8-7></a> <span class=nb>type</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>DependenciesStrategy</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span> <span class=c1># Deprecated, use `deps_strategy`</span>
|
|
<a id=__codelineno-8-8 name=__codelineno-8-8 href=#__codelineno-8-8></a> <span class=n>render_dependencies</span><span class=p>:</span> <span class=nb>bool</span> <span class=o>=</span> <span class=kc>True</span><span class=p>,</span> <span class=c1># Deprecated, use `deps_strategy="ignore"`</span>
|
|
<a id=__codelineno-8-9 name=__codelineno-8-9 href=#__codelineno-8-9></a> <span class=n>outer_context</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>Context</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-8-10 name=__codelineno-8-10 href=#__codelineno-8-10></a> <span class=n>request</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>HttpRequest</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-8-11 name=__codelineno-8-11 href=#__codelineno-8-11></a> <span class=n>registry</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>ComponentRegistry</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-8-12 name=__codelineno-8-12 href=#__codelineno-8-12></a> <span class=n>registered_name</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=nb>str</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-8-13 name=__codelineno-8-13 href=#__codelineno-8-13></a> <span class=n>node</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>ComponentNode</span><span class=p>]</span> <span class=o>=</span> <span class=kc>None</span><span class=p>,</span>
|
|
<a id=__codelineno-8-14 name=__codelineno-8-14 href=#__codelineno-8-14></a> <span class=o>**</span><span class=n>response_kwargs</span><span class=p>:</span> <span class=n>Any</span><span class=p>,</span>
|
|
<a id=__codelineno-8-15 name=__codelineno-8-15 href=#__codelineno-8-15></a><span class=p>)</span> <span class=o>-></span> <span class=n>HttpResponse</span><span class=p>:</span>
|
|
</code></pre></div> </li> <li> <p><code>Component.render()</code> and <code>Component.render_to_response()</code> NO LONGER accept <code>escape_slots_content</code> kwarg.</p> <p>Instead, slots are now always escaped.</p> <p>To disable escaping, wrap the result of <code>slots</code> in <a href=https://docs.djangoproject.com/en/5.2/ref/utils/#django.utils.safestring.mark_safe><code>mark_safe()</code></a>.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-9-1 name=__codelineno-9-1 href=#__codelineno-9-1></a><span class=n>html</span> <span class=o>=</span> <span class=n>component</span><span class=o>.</span><span class=n>render</span><span class=p>(</span>
|
|
<a id=__codelineno-9-2 name=__codelineno-9-2 href=#__codelineno-9-2></a> <span class=n>slots</span><span class=o>=</span><span class=p>{</span><span class=s2>"my_slot"</span><span class=p>:</span> <span class=s2>"CONTENT"</span><span class=p>},</span>
|
|
<a id=__codelineno-9-3 name=__codelineno-9-3 href=#__codelineno-9-3></a> <span class=n>escape_slots_content</span><span class=o>=</span><span class=kc>False</span><span class=p>,</span>
|
|
<a id=__codelineno-9-4 name=__codelineno-9-4 href=#__codelineno-9-4></a><span class=p>)</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-10-1 name=__codelineno-10-1 href=#__codelineno-10-1></a><span class=n>html</span> <span class=o>=</span> <span class=n>component</span><span class=o>.</span><span class=n>render</span><span class=p>(</span>
|
|
<a id=__codelineno-10-2 name=__codelineno-10-2 href=#__codelineno-10-2></a> <span class=n>slots</span><span class=o>=</span><span class=p>{</span><span class=s2>"my_slot"</span><span class=p>:</span> <span class=n>mark_safe</span><span class=p>(</span><span class=s2>"CONTENT"</span><span class=p>)}</span>
|
|
<a id=__codelineno-10-3 name=__codelineno-10-3 href=#__codelineno-10-3></a><span class=p>)</span>
|
|
</code></pre></div> </li> <li> <p><code>Component.template</code> no longer accepts a Template instance, only plain string.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-11-1 name=__codelineno-11-1 href=#__codelineno-11-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-11-2 name=__codelineno-11-2 href=#__codelineno-11-2></a> <span class=n>template</span> <span class=o>=</span> <span class=n>Template</span><span class=p>(</span><span class=s2>"{{ my_var }}"</span><span class=p>)</span>
|
|
</code></pre></div> <p>Instead, either:</p> <ol> <li> <p>Set <code>Component.template</code> to a plain string.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-12-1 name=__codelineno-12-1 href=#__codelineno-12-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-12-2 name=__codelineno-12-2 href=#__codelineno-12-2></a> <span class=n>template</span> <span class=o>=</span> <span class=s2>"{{ my_var }}"</span>
|
|
</code></pre></div> </li> <li> <p>Move the template to it's own HTML file and set <code>Component.template_file</code>.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-13-1 name=__codelineno-13-1 href=#__codelineno-13-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-13-2 name=__codelineno-13-2 href=#__codelineno-13-2></a> <span class=n>template_file</span> <span class=o>=</span> <span class=s2>"my_template.html"</span>
|
|
</code></pre></div> </li> <li> <p>Or, if you dynamically created the template, render the template inside <code>Component.on_render()</code>.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-14-1 name=__codelineno-14-1 href=#__codelineno-14-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-14-2 name=__codelineno-14-2 href=#__codelineno-14-2></a> <span class=k>def</span><span class=w> </span><span class=nf>on_render</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>context</span><span class=p>,</span> <span class=n>template</span><span class=p>):</span>
|
|
<a id=__codelineno-14-3 name=__codelineno-14-3 href=#__codelineno-14-3></a> <span class=n>dynamic_template</span> <span class=o>=</span> <span class=n>do_something_dynamic</span><span class=p>()</span>
|
|
<a id=__codelineno-14-4 name=__codelineno-14-4 href=#__codelineno-14-4></a> <span class=k>return</span> <span class=n>dynamic_template</span><span class=o>.</span><span class=n>render</span><span class=p>(</span><span class=n>context</span><span class=p>)</span>
|
|
</code></pre></div> </li> </ol> </li> <li> <p>Subclassing of components with <code>None</code> values has changed:</p> <p>Previously, when a child component's template / JS / CSS attributes were set to <code>None</code>, the child component still inherited the parent's template / JS / CSS.</p> <p>Now, the child component will not inherit the parent's template / JS / CSS if it sets the attribute to <code>None</code>.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-15-1 name=__codelineno-15-1 href=#__codelineno-15-1></a><span class=k>class</span><span class=w> </span><span class=nc>Parent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-15-2 name=__codelineno-15-2 href=#__codelineno-15-2></a> <span class=n>template</span> <span class=o>=</span> <span class=s2>"parent.html"</span>
|
|
<a id=__codelineno-15-3 name=__codelineno-15-3 href=#__codelineno-15-3></a>
|
|
<a id=__codelineno-15-4 name=__codelineno-15-4 href=#__codelineno-15-4></a><span class=k>class</span><span class=w> </span><span class=nc>Child</span><span class=p>(</span><span class=n>Parent</span><span class=p>):</span>
|
|
<a id=__codelineno-15-5 name=__codelineno-15-5 href=#__codelineno-15-5></a> <span class=n>template</span> <span class=o>=</span> <span class=kc>None</span>
|
|
<a id=__codelineno-15-6 name=__codelineno-15-6 href=#__codelineno-15-6></a>
|
|
<a id=__codelineno-15-7 name=__codelineno-15-7 href=#__codelineno-15-7></a><span class=c1># Child still inherited parent's template</span>
|
|
<a id=__codelineno-15-8 name=__codelineno-15-8 href=#__codelineno-15-8></a><span class=k>assert</span> <span class=n>Child</span><span class=o>.</span><span class=n>template</span> <span class=o>==</span> <span class=n>Parent</span><span class=o>.</span><span class=n>template</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-16-1 name=__codelineno-16-1 href=#__codelineno-16-1></a><span class=k>class</span><span class=w> </span><span class=nc>Parent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-16-2 name=__codelineno-16-2 href=#__codelineno-16-2></a> <span class=n>template</span> <span class=o>=</span> <span class=s2>"parent.html"</span>
|
|
<a id=__codelineno-16-3 name=__codelineno-16-3 href=#__codelineno-16-3></a>
|
|
<a id=__codelineno-16-4 name=__codelineno-16-4 href=#__codelineno-16-4></a><span class=k>class</span><span class=w> </span><span class=nc>Child</span><span class=p>(</span><span class=n>Parent</span><span class=p>):</span>
|
|
<a id=__codelineno-16-5 name=__codelineno-16-5 href=#__codelineno-16-5></a> <span class=n>template</span> <span class=o>=</span> <span class=kc>None</span>
|
|
<a id=__codelineno-16-6 name=__codelineno-16-6 href=#__codelineno-16-6></a>
|
|
<a id=__codelineno-16-7 name=__codelineno-16-7 href=#__codelineno-16-7></a><span class=c1># Child does not inherit parent's template</span>
|
|
<a id=__codelineno-16-8 name=__codelineno-16-8 href=#__codelineno-16-8></a><span class=k>assert</span> <span class=n>Child</span><span class=o>.</span><span class=n>template</span> <span class=ow>is</span> <span class=kc>None</span>
|
|
</code></pre></div> </li> <li> <p>The <code>Component.Url</code> class was merged with <code>Component.View</code>.</p> <p>Instead of <code>Component.Url.public</code>, use <code>Component.View.public</code>.</p> <p>If you imported <code>ComponentUrl</code> from <code>django_components</code>, you need to update your import to <code>ComponentView</code>.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-17-1 name=__codelineno-17-1 href=#__codelineno-17-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-17-2 name=__codelineno-17-2 href=#__codelineno-17-2></a> <span class=k>class</span><span class=w> </span><span class=nc>Url</span><span class=p>:</span>
|
|
<a id=__codelineno-17-3 name=__codelineno-17-3 href=#__codelineno-17-3></a> <span class=n>public</span> <span class=o>=</span> <span class=kc>True</span>
|
|
<a id=__codelineno-17-4 name=__codelineno-17-4 href=#__codelineno-17-4></a>
|
|
<a id=__codelineno-17-5 name=__codelineno-17-5 href=#__codelineno-17-5></a> <span class=k>class</span><span class=w> </span><span class=nc>View</span><span class=p>:</span>
|
|
<a id=__codelineno-17-6 name=__codelineno-17-6 href=#__codelineno-17-6></a> <span class=k>def</span><span class=w> </span><span class=nf>get</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>request</span><span class=p>):</span>
|
|
<a id=__codelineno-17-7 name=__codelineno-17-7 href=#__codelineno-17-7></a> <span class=k>return</span> <span class=bp>self</span><span class=o>.</span><span class=n>render_to_response</span><span class=p>()</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-18-1 name=__codelineno-18-1 href=#__codelineno-18-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-18-2 name=__codelineno-18-2 href=#__codelineno-18-2></a> <span class=k>class</span><span class=w> </span><span class=nc>View</span><span class=p>:</span>
|
|
<a id=__codelineno-18-3 name=__codelineno-18-3 href=#__codelineno-18-3></a> <span class=n>public</span> <span class=o>=</span> <span class=kc>True</span>
|
|
<a id=__codelineno-18-4 name=__codelineno-18-4 href=#__codelineno-18-4></a>
|
|
<a id=__codelineno-18-5 name=__codelineno-18-5 href=#__codelineno-18-5></a> <span class=k>def</span><span class=w> </span><span class=nf>get</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>request</span><span class=p>):</span>
|
|
<a id=__codelineno-18-6 name=__codelineno-18-6 href=#__codelineno-18-6></a> <span class=k>return</span> <span class=bp>self</span><span class=o>.</span><span class=n>render_to_response</span><span class=p>()</span>
|
|
</code></pre></div> </li> <li> <p>Caching - The function signatures of <code>Component.Cache.get_cache_key()</code> and <code>Component.Cache.hash()</code> have changed to enable passing slots.</p> <p>Args and kwargs are no longer spread, but passed as a list and a dict, respectively.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-19-1 name=__codelineno-19-1 href=#__codelineno-19-1></a><span class=k>def</span><span class=w> </span><span class=nf>get_cache_key</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=o>*</span><span class=n>args</span><span class=p>:</span> <span class=n>Any</span><span class=p>,</span> <span class=o>**</span><span class=n>kwargs</span><span class=p>:</span> <span class=n>Any</span><span class=p>)</span> <span class=o>-></span> <span class=nb>str</span><span class=p>:</span>
|
|
<a id=__codelineno-19-2 name=__codelineno-19-2 href=#__codelineno-19-2></a>
|
|
<a id=__codelineno-19-3 name=__codelineno-19-3 href=#__codelineno-19-3></a><span class=k>def</span><span class=w> </span><span class=nf>hash</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=o>*</span><span class=n>args</span><span class=p>:</span> <span class=n>Any</span><span class=p>,</span> <span class=o>**</span><span class=n>kwargs</span><span class=p>:</span> <span class=n>Any</span><span class=p>)</span> <span class=o>-></span> <span class=nb>str</span><span class=p>:</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-20-1 name=__codelineno-20-1 href=#__codelineno-20-1></a><span class=k>def</span><span class=w> </span><span class=nf>get_cache_key</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>args</span><span class=p>:</span> <span class=n>Any</span><span class=p>,</span> <span class=n>kwargs</span><span class=p>:</span> <span class=n>Any</span><span class=p>,</span> <span class=n>slots</span><span class=p>:</span> <span class=n>Any</span><span class=p>)</span> <span class=o>-></span> <span class=nb>str</span><span class=p>:</span>
|
|
<a id=__codelineno-20-2 name=__codelineno-20-2 href=#__codelineno-20-2></a>
|
|
<a id=__codelineno-20-3 name=__codelineno-20-3 href=#__codelineno-20-3></a><span class=k>def</span><span class=w> </span><span class=nf>hash</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>args</span><span class=p>:</span> <span class=n>Any</span><span class=p>,</span> <span class=n>kwargs</span><span class=p>:</span> <span class=n>Any</span><span class=p>)</span> <span class=o>-></span> <span class=nb>str</span><span class=p>:</span>
|
|
</code></pre></div> </li> </ul> <p><strong>Template tags</strong></p> <ul> <li> <p>Component name in the <code>{% component %}</code> tag can no longer be set as a kwarg.</p> <p>Instead, the component name MUST be the first POSITIONAL argument only.</p> <p>Before, it was possible to set the component name as a kwarg and put it anywhere in the <code>{% component %}</code> tag:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-21-1 name=__codelineno-21-1 href=#__codelineno-21-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=nv>rows</span><span class=o>=</span><span class=nv>rows</span> <span class=nv>headers</span><span class=o>=</span><span class=nv>headers</span> <span class=nv>name</span><span class=o>=</span><span class=s2>"my_table"</span> <span class=p>...</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>Now, the component name MUST be the first POSITIONAL argument:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-22-1 name=__codelineno-22-1 href=#__codelineno-22-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"my_table"</span> <span class=nv>rows</span><span class=o>=</span><span class=nv>rows</span> <span class=nv>headers</span><span class=o>=</span><span class=nv>headers</span> <span class=p>...</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>Thus, the <code>name</code> kwarg can now be used as a regular input.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-23-1 name=__codelineno-23-1 href=#__codelineno-23-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"profile"</span> <span class=nv>name</span><span class=o>=</span><span class=s2>"John"</span> <span class=nv>job</span><span class=o>=</span><span class=s2>"Developer"</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
</code></pre></div> </li> </ul> <p><strong>Slots</strong></p> <ul> <li> <p>If you instantiated <code>Slot</code> class with kwargs, you should now use <code>contents</code> instead of <code>content_func</code>.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-24-1 name=__codelineno-24-1 href=#__codelineno-24-1></a><span class=n>slot</span> <span class=o>=</span> <span class=n>Slot</span><span class=p>(</span><span class=n>content_func</span><span class=o>=</span><span class=k>lambda</span> <span class=o>*</span><span class=n>a</span><span class=p>,</span> <span class=o>**</span><span class=n>kw</span><span class=p>:</span> <span class=s2>"CONTENT"</span><span class=p>)</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-25-1 name=__codelineno-25-1 href=#__codelineno-25-1></a><span class=n>slot</span> <span class=o>=</span> <span class=n>Slot</span><span class=p>(</span><span class=n>contents</span><span class=o>=</span><span class=k>lambda</span> <span class=n>ctx</span><span class=p>:</span> <span class=s2>"CONTENT"</span><span class=p>)</span>
|
|
</code></pre></div> <p>Alternatively, pass the function / content as first positional argument:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-26-1 name=__codelineno-26-1 href=#__codelineno-26-1></a><span class=n>slot</span> <span class=o>=</span> <span class=n>Slot</span><span class=p>(</span><span class=k>lambda</span> <span class=n>ctx</span><span class=p>:</span> <span class=s2>"CONTENT"</span><span class=p>)</span>
|
|
</code></pre></div> </li> <li> <p>The undocumented <code>Slot.escaped</code> attribute was removed.</p> <p>Instead, slots are now always escaped.</p> <p>To disable escaping, wrap the result of <code>slots</code> in <a href=https://docs.djangoproject.com/en/5.2/ref/utils/#django.utils.safestring.mark_safe><code>mark_safe()</code></a>.</p> </li> <li> <p>Slot functions behavior has changed. See the new <a href=https://django-components.github.io/django-components/latest/concepts/fundamentals/slots/ >Slots</a> docs for more info.</p> <ul> <li> <p>Function signature:</p> <ol> <li> <p>All parameters are now passed under a single <code>ctx</code> argument.</p> <p>You can still access all the same parameters via <code>ctx.context</code>, <code>ctx.data</code>, and <code>ctx.fallback</code>.</p> </li> <li> <p><code>context</code> and <code>fallback</code> now may be <code>None</code> if the slot function was called outside of <code>{% slot %}</code> tag.</p> </li> </ol> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-27-1 name=__codelineno-27-1 href=#__codelineno-27-1></a><span class=k>def</span><span class=w> </span><span class=nf>slot_fn</span><span class=p>(</span><span class=n>context</span><span class=p>:</span> <span class=n>Context</span><span class=p>,</span> <span class=n>data</span><span class=p>:</span> <span class=n>Dict</span><span class=p>,</span> <span class=n>slot_ref</span><span class=p>:</span> <span class=n>SlotRef</span><span class=p>):</span>
|
|
<a id=__codelineno-27-2 name=__codelineno-27-2 href=#__codelineno-27-2></a> <span class=nb>isinstance</span><span class=p>(</span><span class=n>context</span><span class=p>,</span> <span class=n>Context</span><span class=p>)</span>
|
|
<a id=__codelineno-27-3 name=__codelineno-27-3 href=#__codelineno-27-3></a> <span class=nb>isinstance</span><span class=p>(</span><span class=n>data</span><span class=p>,</span> <span class=n>Dict</span><span class=p>)</span>
|
|
<a id=__codelineno-27-4 name=__codelineno-27-4 href=#__codelineno-27-4></a> <span class=nb>isinstance</span><span class=p>(</span><span class=n>slot_ref</span><span class=p>,</span> <span class=n>SlotRef</span><span class=p>)</span>
|
|
<a id=__codelineno-27-5 name=__codelineno-27-5 href=#__codelineno-27-5></a>
|
|
<a id=__codelineno-27-6 name=__codelineno-27-6 href=#__codelineno-27-6></a> <span class=k>return</span> <span class=s2>"CONTENT"</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-28-1 name=__codelineno-28-1 href=#__codelineno-28-1></a><span class=k>def</span><span class=w> </span><span class=nf>slot_fn</span><span class=p>(</span><span class=n>ctx</span><span class=p>:</span> <span class=n>SlotContext</span><span class=p>):</span>
|
|
<a id=__codelineno-28-2 name=__codelineno-28-2 href=#__codelineno-28-2></a> <span class=k>assert</span> <span class=nb>isinstance</span><span class=p>(</span><span class=n>ctx</span><span class=o>.</span><span class=n>context</span><span class=p>,</span> <span class=n>Context</span><span class=p>)</span> <span class=c1># May be None</span>
|
|
<a id=__codelineno-28-3 name=__codelineno-28-3 href=#__codelineno-28-3></a> <span class=k>assert</span> <span class=nb>isinstance</span><span class=p>(</span><span class=n>ctx</span><span class=o>.</span><span class=n>data</span><span class=p>,</span> <span class=n>Dict</span><span class=p>)</span>
|
|
<a id=__codelineno-28-4 name=__codelineno-28-4 href=#__codelineno-28-4></a> <span class=k>assert</span> <span class=nb>isinstance</span><span class=p>(</span><span class=n>ctx</span><span class=o>.</span><span class=n>fallback</span><span class=p>,</span> <span class=n>SlotFallback</span><span class=p>)</span> <span class=c1># May be None</span>
|
|
<a id=__codelineno-28-5 name=__codelineno-28-5 href=#__codelineno-28-5></a>
|
|
<a id=__codelineno-28-6 name=__codelineno-28-6 href=#__codelineno-28-6></a> <span class=k>return</span> <span class=s2>"CONTENT"</span>
|
|
</code></pre></div> </li> <li> <p>Calling slot functions:</p> <ol> <li> <p>Rather than calling the slot functions directly, you should now call the <code>Slot</code> instances.</p> </li> <li> <p>All parameters are now optional.</p> </li> <li> <p>The order of parameters has changed.</p> </li> </ol> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-29-1 name=__codelineno-29-1 href=#__codelineno-29-1></a><span class=k>def</span><span class=w> </span><span class=nf>slot_fn</span><span class=p>(</span><span class=n>context</span><span class=p>:</span> <span class=n>Context</span><span class=p>,</span> <span class=n>data</span><span class=p>:</span> <span class=n>Dict</span><span class=p>,</span> <span class=n>slot_ref</span><span class=p>:</span> <span class=n>SlotRef</span><span class=p>):</span>
|
|
<a id=__codelineno-29-2 name=__codelineno-29-2 href=#__codelineno-29-2></a> <span class=k>return</span> <span class=s2>"CONTENT"</span>
|
|
<a id=__codelineno-29-3 name=__codelineno-29-3 href=#__codelineno-29-3></a>
|
|
<a id=__codelineno-29-4 name=__codelineno-29-4 href=#__codelineno-29-4></a><span class=n>html</span> <span class=o>=</span> <span class=n>slot_fn</span><span class=p>(</span><span class=n>context</span><span class=p>,</span> <span class=n>data</span><span class=p>,</span> <span class=n>slot_ref</span><span class=p>)</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-30-1 name=__codelineno-30-1 href=#__codelineno-30-1></a><span class=k>def</span><span class=w> </span><span class=nf>slot_fn</span><span class=p>(</span><span class=n>ctx</span><span class=p>:</span> <span class=n>SlotContext</span><span class=p>):</span>
|
|
<a id=__codelineno-30-2 name=__codelineno-30-2 href=#__codelineno-30-2></a> <span class=k>return</span> <span class=s2>"CONTENT"</span>
|
|
<a id=__codelineno-30-3 name=__codelineno-30-3 href=#__codelineno-30-3></a>
|
|
<a id=__codelineno-30-4 name=__codelineno-30-4 href=#__codelineno-30-4></a><span class=n>slot</span> <span class=o>=</span> <span class=n>Slot</span><span class=p>(</span><span class=n>slot_fn</span><span class=p>)</span>
|
|
<a id=__codelineno-30-5 name=__codelineno-30-5 href=#__codelineno-30-5></a><span class=n>html</span> <span class=o>=</span> <span class=n>slot</span><span class=p>()</span>
|
|
<a id=__codelineno-30-6 name=__codelineno-30-6 href=#__codelineno-30-6></a><span class=n>html</span> <span class=o>=</span> <span class=n>slot</span><span class=p>({</span><span class=s2>"data1"</span><span class=p>:</span> <span class=s2>"abc"</span><span class=p>,</span> <span class=s2>"data2"</span><span class=p>:</span> <span class=s2>"hello"</span><span class=p>})</span>
|
|
<a id=__codelineno-30-7 name=__codelineno-30-7 href=#__codelineno-30-7></a><span class=n>html</span> <span class=o>=</span> <span class=n>slot</span><span class=p>({</span><span class=s2>"data1"</span><span class=p>:</span> <span class=s2>"abc"</span><span class=p>,</span> <span class=s2>"data2"</span><span class=p>:</span> <span class=s2>"hello"</span><span class=p>},</span> <span class=n>fallback</span><span class=o>=</span><span class=s2>"FALLBACK"</span><span class=p>)</span>
|
|
</code></pre></div> </li> <li> <p>Usage in components:</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-31-1 name=__codelineno-31-1 href=#__codelineno-31-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-31-2 name=__codelineno-31-2 href=#__codelineno-31-2></a> <span class=k>def</span><span class=w> </span><span class=nf>get_context_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=o>*</span><span class=n>args</span><span class=p>,</span> <span class=o>**</span><span class=n>kwargs</span><span class=p>):</span>
|
|
<a id=__codelineno-31-3 name=__codelineno-31-3 href=#__codelineno-31-3></a> <span class=n>slots</span> <span class=o>=</span> <span class=bp>self</span><span class=o>.</span><span class=n>input</span><span class=o>.</span><span class=n>slots</span>
|
|
<a id=__codelineno-31-4 name=__codelineno-31-4 href=#__codelineno-31-4></a> <span class=n>slot_fn</span> <span class=o>=</span> <span class=n>slots</span><span class=p>[</span><span class=s2>"my_slot"</span><span class=p>]</span>
|
|
<a id=__codelineno-31-5 name=__codelineno-31-5 href=#__codelineno-31-5></a> <span class=n>html</span> <span class=o>=</span> <span class=n>slot_fn</span><span class=p>(</span><span class=n>context</span><span class=p>,</span> <span class=n>data</span><span class=p>,</span> <span class=n>slot_ref</span><span class=p>)</span>
|
|
<a id=__codelineno-31-6 name=__codelineno-31-6 href=#__codelineno-31-6></a> <span class=k>return</span> <span class=p>{</span>
|
|
<a id=__codelineno-31-7 name=__codelineno-31-7 href=#__codelineno-31-7></a> <span class=s2>"html"</span><span class=p>:</span> <span class=n>html</span><span class=p>,</span>
|
|
<a id=__codelineno-31-8 name=__codelineno-31-8 href=#__codelineno-31-8></a> <span class=p>}</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-32-1 name=__codelineno-32-1 href=#__codelineno-32-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-32-2 name=__codelineno-32-2 href=#__codelineno-32-2></a> <span class=k>def</span><span class=w> </span><span class=nf>get_template_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>args</span><span class=p>,</span> <span class=n>kwargs</span><span class=p>,</span> <span class=n>slots</span><span class=p>,</span> <span class=n>context</span><span class=p>):</span>
|
|
<a id=__codelineno-32-3 name=__codelineno-32-3 href=#__codelineno-32-3></a> <span class=n>slot_fn</span> <span class=o>=</span> <span class=n>slots</span><span class=p>[</span><span class=s2>"my_slot"</span><span class=p>]</span>
|
|
<a id=__codelineno-32-4 name=__codelineno-32-4 href=#__codelineno-32-4></a> <span class=n>html</span> <span class=o>=</span> <span class=n>slot_fn</span><span class=p>(</span><span class=n>data</span><span class=p>)</span>
|
|
<a id=__codelineno-32-5 name=__codelineno-32-5 href=#__codelineno-32-5></a> <span class=k>return</span> <span class=p>{</span>
|
|
<a id=__codelineno-32-6 name=__codelineno-32-6 href=#__codelineno-32-6></a> <span class=s2>"html"</span><span class=p>:</span> <span class=n>html</span><span class=p>,</span>
|
|
<a id=__codelineno-32-7 name=__codelineno-32-7 href=#__codelineno-32-7></a> <span class=p>}</span>
|
|
</code></pre></div> </li> </ul> </li> </ul> <p><strong>Miscellaneous</strong></p> <ul> <li> <p>The second argument to <code>render_dependencies()</code> is now <code>strategy</code> instead of <code>type</code>.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-33-1 name=__codelineno-33-1 href=#__codelineno-33-1></a><span class=n>render_dependencies</span><span class=p>(</span><span class=n>content</span><span class=p>,</span> <span class=nb>type</span><span class=o>=</span><span class=s2>"document"</span><span class=p>)</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-34-1 name=__codelineno-34-1 href=#__codelineno-34-1></a><span class=n>render_dependencies</span><span class=p>(</span><span class=n>content</span><span class=p>,</span> <span class=n>strategy</span><span class=o>=</span><span class=s2>"document"</span><span class=p>)</span>
|
|
</code></pre></div> </li> </ul> <h4 id=deprecation>🚨📢 Deprecation<a class=headerlink href=#deprecation title="Permanent link">¤</a></h4> <p><strong>Component API</strong></p> <ul> <li> <p><code>Component.get_context_data()</code> is now deprecated. Use <code>Component.get_template_data()</code> instead.</p> <p><code>get_template_data()</code> behaves the same way, but has a different function signature to accept also slots and context.</p> <p>Since <code>get_context_data()</code> is widely used, it will remain available until v2.</p> </li> <li> <p><code>Component.get_template_name()</code> and <code>Component.get_template()</code> are now deprecated. Use <code>Component.template</code>, <code>Component.template_file</code> or <code>Component.on_render()</code> instead.</p> <p><code>Component.get_template_name()</code> and <code>Component.get_template()</code> will be removed in v1.</p> <p>In v1, each Component will have at most one static template. This is needed to enable support for Markdown, Pug, or other pre-processing of templates by extensions.</p> <p>If you are using the deprecated methods to point to different templates, there's 2 ways to migrate:</p> <ol> <li> <p>Split the single Component into multiple Components, each with its own template. Then switch between them in <code>Component.on_render()</code>:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-35-1 name=__codelineno-35-1 href=#__codelineno-35-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponentA</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-35-2 name=__codelineno-35-2 href=#__codelineno-35-2></a> <span class=n>template_file</span> <span class=o>=</span> <span class=s2>"a.html"</span>
|
|
<a id=__codelineno-35-3 name=__codelineno-35-3 href=#__codelineno-35-3></a>
|
|
<a id=__codelineno-35-4 name=__codelineno-35-4 href=#__codelineno-35-4></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponentB</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-35-5 name=__codelineno-35-5 href=#__codelineno-35-5></a> <span class=n>template_file</span> <span class=o>=</span> <span class=s2>"b.html"</span>
|
|
<a id=__codelineno-35-6 name=__codelineno-35-6 href=#__codelineno-35-6></a>
|
|
<a id=__codelineno-35-7 name=__codelineno-35-7 href=#__codelineno-35-7></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-35-8 name=__codelineno-35-8 href=#__codelineno-35-8></a> <span class=k>def</span><span class=w> </span><span class=nf>on_render</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>context</span><span class=p>,</span> <span class=n>template</span><span class=p>):</span>
|
|
<a id=__codelineno-35-9 name=__codelineno-35-9 href=#__codelineno-35-9></a> <span class=k>if</span> <span class=n>context</span><span class=p>[</span><span class=s2>"a"</span><span class=p>]:</span>
|
|
<a id=__codelineno-35-10 name=__codelineno-35-10 href=#__codelineno-35-10></a> <span class=k>return</span> <span class=n>MyComponentA</span><span class=o>.</span><span class=n>render</span><span class=p>(</span><span class=n>context</span><span class=p>)</span>
|
|
<a id=__codelineno-35-11 name=__codelineno-35-11 href=#__codelineno-35-11></a> <span class=k>else</span><span class=p>:</span>
|
|
<a id=__codelineno-35-12 name=__codelineno-35-12 href=#__codelineno-35-12></a> <span class=k>return</span> <span class=n>MyComponentB</span><span class=o>.</span><span class=n>render</span><span class=p>(</span><span class=n>context</span><span class=p>)</span>
|
|
</code></pre></div> </li> <li> <p>Alternatively, use <code>Component.on_render()</code> with Django's <code>get_template()</code> to dynamically render different templates:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-36-1 name=__codelineno-36-1 href=#__codelineno-36-1></a><span class=kn>from</span><span class=w> </span><span class=nn>django.template.loader</span><span class=w> </span><span class=kn>import</span> <span class=n>get_template</span>
|
|
<a id=__codelineno-36-2 name=__codelineno-36-2 href=#__codelineno-36-2></a>
|
|
<a id=__codelineno-36-3 name=__codelineno-36-3 href=#__codelineno-36-3></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-36-4 name=__codelineno-36-4 href=#__codelineno-36-4></a> <span class=k>def</span><span class=w> </span><span class=nf>on_render</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>context</span><span class=p>,</span> <span class=n>template</span><span class=p>):</span>
|
|
<a id=__codelineno-36-5 name=__codelineno-36-5 href=#__codelineno-36-5></a> <span class=k>if</span> <span class=n>context</span><span class=p>[</span><span class=s2>"a"</span><span class=p>]:</span>
|
|
<a id=__codelineno-36-6 name=__codelineno-36-6 href=#__codelineno-36-6></a> <span class=n>template_name</span> <span class=o>=</span> <span class=s2>"a.html"</span>
|
|
<a id=__codelineno-36-7 name=__codelineno-36-7 href=#__codelineno-36-7></a> <span class=k>else</span><span class=p>:</span>
|
|
<a id=__codelineno-36-8 name=__codelineno-36-8 href=#__codelineno-36-8></a> <span class=n>template_name</span> <span class=o>=</span> <span class=s2>"b.html"</span>
|
|
<a id=__codelineno-36-9 name=__codelineno-36-9 href=#__codelineno-36-9></a>
|
|
<a id=__codelineno-36-10 name=__codelineno-36-10 href=#__codelineno-36-10></a> <span class=n>actual_template</span> <span class=o>=</span> <span class=n>get_template</span><span class=p>(</span><span class=n>template_name</span><span class=p>)</span>
|
|
<a id=__codelineno-36-11 name=__codelineno-36-11 href=#__codelineno-36-11></a> <span class=k>return</span> <span class=n>actual_template</span><span class=o>.</span><span class=n>render</span><span class=p>(</span><span class=n>context</span><span class=p>)</span>
|
|
</code></pre></div> </li> </ol> <p>Read more in <a href=https://github.com/django-components/django-components/discussions/1204>django-components#1204</a>.</p> </li> <li> <p>The <code>type</code> kwarg in <code>Component.render()</code> and <code>Component.render_to_response()</code> is now deprecated. Use <code>deps_strategy</code> instead. The <code>type</code> kwarg will be removed in v1.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-37-1 name=__codelineno-37-1 href=#__codelineno-37-1></a><span class=n>Calendar</span><span class=o>.</span><span class=n>render_to_response</span><span class=p>(</span><span class=nb>type</span><span class=o>=</span><span class=s2>"fragment"</span><span class=p>)</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-38-1 name=__codelineno-38-1 href=#__codelineno-38-1></a><span class=n>Calendar</span><span class=o>.</span><span class=n>render_to_response</span><span class=p>(</span><span class=n>deps_strategy</span><span class=o>=</span><span class=s2>"fragment"</span><span class=p>)</span>
|
|
</code></pre></div> </li> <li> <p>The <code>render_dependencies</code> kwarg in <code>Component.render()</code> and <code>Component.render_to_response()</code> is now deprecated. Use <code>deps_strategy="ignore"</code> instead. The <code>render_dependencies</code> kwarg will be removed in v1.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-39-1 name=__codelineno-39-1 href=#__codelineno-39-1></a><span class=n>Calendar</span><span class=o>.</span><span class=n>render_to_response</span><span class=p>(</span><span class=n>render_dependencies</span><span class=o>=</span><span class=kc>False</span><span class=p>)</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-40-1 name=__codelineno-40-1 href=#__codelineno-40-1></a><span class=n>Calendar</span><span class=o>.</span><span class=n>render_to_response</span><span class=p>(</span><span class=n>deps_strategy</span><span class=o>=</span><span class=s2>"ignore"</span><span class=p>)</span>
|
|
</code></pre></div> </li> <li> <p>Support for <code>Component</code> constructor kwargs <code>registered_name</code>, <code>outer_context</code>, and <code>registry</code> is deprecated, and will be removed in v1.</p> <p>Before, you could instantiate a standalone component, and then call <code>render()</code> on the instance:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-41-1 name=__codelineno-41-1 href=#__codelineno-41-1></a><span class=n>comp</span> <span class=o>=</span> <span class=n>MyComponent</span><span class=p>(</span>
|
|
<a id=__codelineno-41-2 name=__codelineno-41-2 href=#__codelineno-41-2></a> <span class=n>registered_name</span><span class=o>=</span><span class=s2>"my_component"</span><span class=p>,</span>
|
|
<a id=__codelineno-41-3 name=__codelineno-41-3 href=#__codelineno-41-3></a> <span class=n>outer_context</span><span class=o>=</span><span class=n>my_context</span><span class=p>,</span>
|
|
<a id=__codelineno-41-4 name=__codelineno-41-4 href=#__codelineno-41-4></a> <span class=n>registry</span><span class=o>=</span><span class=n>my_registry</span><span class=p>,</span>
|
|
<a id=__codelineno-41-5 name=__codelineno-41-5 href=#__codelineno-41-5></a><span class=p>)</span>
|
|
<a id=__codelineno-41-6 name=__codelineno-41-6 href=#__codelineno-41-6></a><span class=n>comp</span><span class=o>.</span><span class=n>render</span><span class=p>(</span>
|
|
<a id=__codelineno-41-7 name=__codelineno-41-7 href=#__codelineno-41-7></a> <span class=n>args</span><span class=o>=</span><span class=p>[</span><span class=mi>1</span><span class=p>,</span> <span class=mi>2</span><span class=p>,</span> <span class=mi>3</span><span class=p>],</span>
|
|
<a id=__codelineno-41-8 name=__codelineno-41-8 href=#__codelineno-41-8></a> <span class=n>kwargs</span><span class=o>=</span><span class=p>{</span><span class=s2>"a"</span><span class=p>:</span> <span class=mi>1</span><span class=p>,</span> <span class=s2>"b"</span><span class=p>:</span> <span class=mi>2</span><span class=p>},</span>
|
|
<a id=__codelineno-41-9 name=__codelineno-41-9 href=#__codelineno-41-9></a> <span class=n>slots</span><span class=o>=</span><span class=p>{</span><span class=s2>"my_slot"</span><span class=p>:</span> <span class=s2>"CONTENT"</span><span class=p>},</span>
|
|
<a id=__codelineno-41-10 name=__codelineno-41-10 href=#__codelineno-41-10></a><span class=p>)</span>
|
|
</code></pre></div> <p>Now you should instead pass all that data to <code>Component.render()</code> / <code>Component.render_to_response()</code>:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-42-1 name=__codelineno-42-1 href=#__codelineno-42-1></a><span class=n>MyComponent</span><span class=o>.</span><span class=n>render</span><span class=p>(</span>
|
|
<a id=__codelineno-42-2 name=__codelineno-42-2 href=#__codelineno-42-2></a> <span class=n>args</span><span class=o>=</span><span class=p>[</span><span class=mi>1</span><span class=p>,</span> <span class=mi>2</span><span class=p>,</span> <span class=mi>3</span><span class=p>],</span>
|
|
<a id=__codelineno-42-3 name=__codelineno-42-3 href=#__codelineno-42-3></a> <span class=n>kwargs</span><span class=o>=</span><span class=p>{</span><span class=s2>"a"</span><span class=p>:</span> <span class=mi>1</span><span class=p>,</span> <span class=s2>"b"</span><span class=p>:</span> <span class=mi>2</span><span class=p>},</span>
|
|
<a id=__codelineno-42-4 name=__codelineno-42-4 href=#__codelineno-42-4></a> <span class=n>slots</span><span class=o>=</span><span class=p>{</span><span class=s2>"my_slot"</span><span class=p>:</span> <span class=s2>"CONTENT"</span><span class=p>},</span>
|
|
<a id=__codelineno-42-5 name=__codelineno-42-5 href=#__codelineno-42-5></a> <span class=c1># NEW</span>
|
|
<a id=__codelineno-42-6 name=__codelineno-42-6 href=#__codelineno-42-6></a> <span class=n>registered_name</span><span class=o>=</span><span class=s2>"my_component"</span><span class=p>,</span>
|
|
<a id=__codelineno-42-7 name=__codelineno-42-7 href=#__codelineno-42-7></a> <span class=n>outer_context</span><span class=o>=</span><span class=n>my_context</span><span class=p>,</span>
|
|
<a id=__codelineno-42-8 name=__codelineno-42-8 href=#__codelineno-42-8></a> <span class=n>registry</span><span class=o>=</span><span class=n>my_registry</span><span class=p>,</span>
|
|
<a id=__codelineno-42-9 name=__codelineno-42-9 href=#__codelineno-42-9></a><span class=p>)</span>
|
|
</code></pre></div> </li> <li> <p><code>Component.input</code> (and its type <code>ComponentInput</code>) is now deprecated. The <code>input</code> property will be removed in v1.</p> <p>Instead, use attributes directly on the Component instance.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-43-1 name=__codelineno-43-1 href=#__codelineno-43-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-43-2 name=__codelineno-43-2 href=#__codelineno-43-2></a> <span class=k>def</span><span class=w> </span><span class=nf>on_render</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>context</span><span class=p>,</span> <span class=n>template</span><span class=p>):</span>
|
|
<a id=__codelineno-43-3 name=__codelineno-43-3 href=#__codelineno-43-3></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>input</span><span class=o>.</span><span class=n>args</span> <span class=o>==</span> <span class=p>[</span><span class=mi>1</span><span class=p>,</span> <span class=mi>2</span><span class=p>,</span> <span class=mi>3</span><span class=p>]</span>
|
|
<a id=__codelineno-43-4 name=__codelineno-43-4 href=#__codelineno-43-4></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>input</span><span class=o>.</span><span class=n>kwargs</span> <span class=o>==</span> <span class=p>{</span><span class=s2>"a"</span><span class=p>:</span> <span class=mi>1</span><span class=p>,</span> <span class=s2>"b"</span><span class=p>:</span> <span class=mi>2</span><span class=p>}</span>
|
|
<a id=__codelineno-43-5 name=__codelineno-43-5 href=#__codelineno-43-5></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>input</span><span class=o>.</span><span class=n>slots</span> <span class=o>==</span> <span class=p>{</span><span class=s2>"my_slot"</span><span class=p>:</span> <span class=s2>"CONTENT"</span><span class=p>}</span>
|
|
<a id=__codelineno-43-6 name=__codelineno-43-6 href=#__codelineno-43-6></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>input</span><span class=o>.</span><span class=n>context</span> <span class=o>==</span> <span class=p>{</span><span class=s2>"my_slot"</span><span class=p>:</span> <span class=s2>"CONTENT"</span><span class=p>}</span>
|
|
<a id=__codelineno-43-7 name=__codelineno-43-7 href=#__codelineno-43-7></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>input</span><span class=o>.</span><span class=n>deps_strategy</span> <span class=o>==</span> <span class=s2>"document"</span>
|
|
<a id=__codelineno-43-8 name=__codelineno-43-8 href=#__codelineno-43-8></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>input</span><span class=o>.</span><span class=n>type</span> <span class=o>==</span> <span class=s2>"document"</span>
|
|
<a id=__codelineno-43-9 name=__codelineno-43-9 href=#__codelineno-43-9></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>input</span><span class=o>.</span><span class=n>render_dependencies</span> <span class=o>==</span> <span class=kc>True</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-44-1 name=__codelineno-44-1 href=#__codelineno-44-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-44-2 name=__codelineno-44-2 href=#__codelineno-44-2></a> <span class=k>def</span><span class=w> </span><span class=nf>on_render</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>context</span><span class=p>,</span> <span class=n>template</span><span class=p>):</span>
|
|
<a id=__codelineno-44-3 name=__codelineno-44-3 href=#__codelineno-44-3></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>args</span> <span class=o>==</span> <span class=p>[</span><span class=mi>1</span><span class=p>,</span> <span class=mi>2</span><span class=p>,</span> <span class=mi>3</span><span class=p>]</span>
|
|
<a id=__codelineno-44-4 name=__codelineno-44-4 href=#__codelineno-44-4></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>kwargs</span> <span class=o>==</span> <span class=p>{</span><span class=s2>"a"</span><span class=p>:</span> <span class=mi>1</span><span class=p>,</span> <span class=s2>"b"</span><span class=p>:</span> <span class=mi>2</span><span class=p>}</span>
|
|
<a id=__codelineno-44-5 name=__codelineno-44-5 href=#__codelineno-44-5></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>slots</span> <span class=o>==</span> <span class=p>{</span><span class=s2>"my_slot"</span><span class=p>:</span> <span class=s2>"CONTENT"</span><span class=p>}</span>
|
|
<a id=__codelineno-44-6 name=__codelineno-44-6 href=#__codelineno-44-6></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>context</span> <span class=o>==</span> <span class=p>{</span><span class=s2>"my_slot"</span><span class=p>:</span> <span class=s2>"CONTENT"</span><span class=p>}</span>
|
|
<a id=__codelineno-44-7 name=__codelineno-44-7 href=#__codelineno-44-7></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>deps_strategy</span> <span class=o>==</span> <span class=s2>"document"</span>
|
|
<a id=__codelineno-44-8 name=__codelineno-44-8 href=#__codelineno-44-8></a> <span class=k>assert</span> <span class=p>(</span><span class=bp>self</span><span class=o>.</span><span class=n>deps_strategy</span> <span class=o>!=</span> <span class=s2>"ignore"</span><span class=p>)</span> <span class=ow>is</span> <span class=kc>True</span>
|
|
</code></pre></div> </li> <li> <p>Component method <code>on_render_after</code> was updated to receive also <code>error</code> field.</p> <p>For backwards compatibility, the <code>error</code> field can be omitted until v1.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-45-1 name=__codelineno-45-1 href=#__codelineno-45-1></a><span class=k>def</span><span class=w> </span><span class=nf>on_render_after</span><span class=p>(</span>
|
|
<a id=__codelineno-45-2 name=__codelineno-45-2 href=#__codelineno-45-2></a> <span class=bp>self</span><span class=p>,</span>
|
|
<a id=__codelineno-45-3 name=__codelineno-45-3 href=#__codelineno-45-3></a> <span class=n>context</span><span class=p>:</span> <span class=n>Context</span><span class=p>,</span>
|
|
<a id=__codelineno-45-4 name=__codelineno-45-4 href=#__codelineno-45-4></a> <span class=n>template</span><span class=p>:</span> <span class=n>Template</span><span class=p>,</span>
|
|
<a id=__codelineno-45-5 name=__codelineno-45-5 href=#__codelineno-45-5></a> <span class=n>html</span><span class=p>:</span> <span class=nb>str</span><span class=p>,</span>
|
|
<a id=__codelineno-45-6 name=__codelineno-45-6 href=#__codelineno-45-6></a><span class=p>)</span> <span class=o>-></span> <span class=kc>None</span><span class=p>:</span>
|
|
<a id=__codelineno-45-7 name=__codelineno-45-7 href=#__codelineno-45-7></a> <span class=k>pass</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-46-1 name=__codelineno-46-1 href=#__codelineno-46-1></a><span class=k>def</span><span class=w> </span><span class=nf>on_render_after</span><span class=p>(</span>
|
|
<a id=__codelineno-46-2 name=__codelineno-46-2 href=#__codelineno-46-2></a> <span class=bp>self</span><span class=p>,</span>
|
|
<a id=__codelineno-46-3 name=__codelineno-46-3 href=#__codelineno-46-3></a> <span class=n>context</span><span class=p>:</span> <span class=n>Context</span><span class=p>,</span>
|
|
<a id=__codelineno-46-4 name=__codelineno-46-4 href=#__codelineno-46-4></a> <span class=n>template</span><span class=p>:</span> <span class=n>Template</span><span class=p>,</span>
|
|
<a id=__codelineno-46-5 name=__codelineno-46-5 href=#__codelineno-46-5></a> <span class=n>html</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=nb>str</span><span class=p>],</span>
|
|
<a id=__codelineno-46-6 name=__codelineno-46-6 href=#__codelineno-46-6></a> <span class=n>error</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=ne>Exception</span><span class=p>],</span>
|
|
<a id=__codelineno-46-7 name=__codelineno-46-7 href=#__codelineno-46-7></a><span class=p>)</span> <span class=o>-></span> <span class=kc>None</span><span class=p>:</span>
|
|
<a id=__codelineno-46-8 name=__codelineno-46-8 href=#__codelineno-46-8></a> <span class=k>pass</span>
|
|
</code></pre></div> </li> <li> <p>If you are using the Components as views, the way to access the component class is now different.</p> <p>Instead of <code>self.component</code>, use <code>self.component_cls</code>. <code>self.component</code> will be removed in v1.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-47-1 name=__codelineno-47-1 href=#__codelineno-47-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyView</span><span class=p>(</span><span class=n>View</span><span class=p>):</span>
|
|
<a id=__codelineno-47-2 name=__codelineno-47-2 href=#__codelineno-47-2></a> <span class=k>def</span><span class=w> </span><span class=nf>get</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>request</span><span class=p>):</span>
|
|
<a id=__codelineno-47-3 name=__codelineno-47-3 href=#__codelineno-47-3></a> <span class=k>return</span> <span class=bp>self</span><span class=o>.</span><span class=n>component</span><span class=o>.</span><span class=n>render_to_response</span><span class=p>(</span><span class=n>request</span><span class=o>=</span><span class=n>request</span><span class=p>)</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-48-1 name=__codelineno-48-1 href=#__codelineno-48-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyView</span><span class=p>(</span><span class=n>View</span><span class=p>):</span>
|
|
<a id=__codelineno-48-2 name=__codelineno-48-2 href=#__codelineno-48-2></a> <span class=k>def</span><span class=w> </span><span class=nf>get</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>request</span><span class=p>):</span>
|
|
<a id=__codelineno-48-3 name=__codelineno-48-3 href=#__codelineno-48-3></a> <span class=k>return</span> <span class=bp>self</span><span class=o>.</span><span class=n>component_cls</span><span class=o>.</span><span class=n>render_to_response</span><span class=p>(</span><span class=n>request</span><span class=o>=</span><span class=n>request</span><span class=p>)</span>
|
|
</code></pre></div> </li> </ul> <p><strong>Extensions</strong></p> <ul> <li> <p>In the <code>on_component_data()</code> extension hook, the <code>context_data</code> field of the context object was superseded by <code>template_data</code>.</p> <p>The <code>context_data</code> field will be removed in v1.0.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-49-1 name=__codelineno-49-1 href=#__codelineno-49-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyExtension</span><span class=p>(</span><span class=n>ComponentExtension</span><span class=p>):</span>
|
|
<a id=__codelineno-49-2 name=__codelineno-49-2 href=#__codelineno-49-2></a> <span class=k>def</span><span class=w> </span><span class=nf>on_component_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>ctx</span><span class=p>:</span> <span class=n>OnComponentDataContext</span><span class=p>)</span> <span class=o>-></span> <span class=kc>None</span><span class=p>:</span>
|
|
<a id=__codelineno-49-3 name=__codelineno-49-3 href=#__codelineno-49-3></a> <span class=n>ctx</span><span class=o>.</span><span class=n>context_data</span><span class=p>[</span><span class=s2>"my_template_var"</span><span class=p>]</span> <span class=o>=</span> <span class=s2>"my_value"</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-50-1 name=__codelineno-50-1 href=#__codelineno-50-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyExtension</span><span class=p>(</span><span class=n>ComponentExtension</span><span class=p>):</span>
|
|
<a id=__codelineno-50-2 name=__codelineno-50-2 href=#__codelineno-50-2></a> <span class=k>def</span><span class=w> </span><span class=nf>on_component_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>ctx</span><span class=p>:</span> <span class=n>OnComponentDataContext</span><span class=p>)</span> <span class=o>-></span> <span class=kc>None</span><span class=p>:</span>
|
|
<a id=__codelineno-50-3 name=__codelineno-50-3 href=#__codelineno-50-3></a> <span class=n>ctx</span><span class=o>.</span><span class=n>template_data</span><span class=p>[</span><span class=s2>"my_template_var"</span><span class=p>]</span> <span class=o>=</span> <span class=s2>"my_value"</span>
|
|
</code></pre></div> </li> <li> <p>When creating extensions, the <code>ComponentExtension.ExtensionClass</code> attribute was renamed to <code>ComponentConfig</code>.</p> <p>The old name is deprecated and will be removed in v1.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-51-1 name=__codelineno-51-1 href=#__codelineno-51-1></a><span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>ComponentExtension</span>
|
|
<a id=__codelineno-51-2 name=__codelineno-51-2 href=#__codelineno-51-2></a>
|
|
<a id=__codelineno-51-3 name=__codelineno-51-3 href=#__codelineno-51-3></a><span class=k>class</span><span class=w> </span><span class=nc>MyExtension</span><span class=p>(</span><span class=n>ComponentExtension</span><span class=p>):</span>
|
|
<a id=__codelineno-51-4 name=__codelineno-51-4 href=#__codelineno-51-4></a> <span class=k>class</span><span class=w> </span><span class=nc>ExtensionClass</span><span class=p>(</span><span class=n>ComponentExtension</span><span class=o>.</span><span class=n>ExtensionClass</span><span class=p>):</span>
|
|
<a id=__codelineno-51-5 name=__codelineno-51-5 href=#__codelineno-51-5></a> <span class=k>pass</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-52-1 name=__codelineno-52-1 href=#__codelineno-52-1></a><span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>ComponentExtension</span><span class=p>,</span> <span class=n>ExtensionComponentConfig</span>
|
|
<a id=__codelineno-52-2 name=__codelineno-52-2 href=#__codelineno-52-2></a>
|
|
<a id=__codelineno-52-3 name=__codelineno-52-3 href=#__codelineno-52-3></a><span class=k>class</span><span class=w> </span><span class=nc>MyExtension</span><span class=p>(</span><span class=n>ComponentExtension</span><span class=p>):</span>
|
|
<a id=__codelineno-52-4 name=__codelineno-52-4 href=#__codelineno-52-4></a> <span class=k>class</span><span class=w> </span><span class=nc>ComponentConfig</span><span class=p>(</span><span class=n>ExtensionComponentConfig</span><span class=p>):</span>
|
|
<a id=__codelineno-52-5 name=__codelineno-52-5 href=#__codelineno-52-5></a> <span class=k>pass</span>
|
|
</code></pre></div> </li> <li> <p>When creating extensions, to access the Component class from within the methods of the extension nested classes, use <code>component_cls</code>.</p> <p>Previously this field was named <code>component_class</code>. The old name is deprecated and will be removed in v1.</p> </li> </ul> <p><code>ComponentExtension.ExtensionClass</code> attribute was renamed to <code>ComponentConfig</code>.</p> <div class=codehilite><pre><span></span><code><span class=n>The</span> <span class=n>old</span> <span class=n>name</span> <span class=ow>is</span> <span class=n>deprecated</span> <span class=ow>and</span> <span class=n>will</span> <span class=n>be</span> <span class=n>removed</span> <span class=ow>in</span> <span class=n>v1</span><span class=o>.</span>
|
|
|
|
<span class=n>Before</span><span class=p>:</span>
|
|
|
|
<span class=err>```</span><span class=n>py</span>
|
|
<span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>ComponentExtension</span><span class=p>,</span> <span class=n>ExtensionComponentConfig</span>
|
|
|
|
<span class=k>class</span><span class=w> </span><span class=nc>LoggerExtension</span><span class=p>(</span><span class=n>ComponentExtension</span><span class=p>):</span>
|
|
<span class=n>name</span> <span class=o>=</span> <span class=s2>"logger"</span>
|
|
|
|
<span class=k>class</span><span class=w> </span><span class=nc>ComponentConfig</span><span class=p>(</span><span class=n>ExtensionComponentConfig</span><span class=p>):</span>
|
|
<span class=k>def</span><span class=w> </span><span class=nf>log</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>msg</span><span class=p>:</span> <span class=nb>str</span><span class=p>)</span> <span class=o>-></span> <span class=kc>None</span><span class=p>:</span>
|
|
<span class=nb>print</span><span class=p>(</span><span class=sa>f</span><span class=s2>"</span><span class=si>{</span><span class=bp>self</span><span class=o>.</span><span class=n>component_class</span><span class=o>.</span><span class=vm>__name__</span><span class=si>}</span><span class=s2>: </span><span class=si>{</span><span class=n>msg</span><span class=si>}</span><span class=s2>"</span><span class=p>)</span>
|
|
<span class=err>```</span>
|
|
|
|
<span class=n>After</span><span class=p>:</span>
|
|
|
|
<span class=err>```</span><span class=n>py</span>
|
|
<span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>ComponentExtension</span><span class=p>,</span> <span class=n>ExtensionComponentConfig</span>
|
|
|
|
<span class=k>class</span><span class=w> </span><span class=nc>LoggerExtension</span><span class=p>(</span><span class=n>ComponentExtension</span><span class=p>):</span>
|
|
<span class=n>name</span> <span class=o>=</span> <span class=s2>"logger"</span>
|
|
|
|
<span class=k>class</span><span class=w> </span><span class=nc>ComponentConfig</span><span class=p>(</span><span class=n>ExtensionComponentConfig</span><span class=p>):</span>
|
|
<span class=k>def</span><span class=w> </span><span class=nf>log</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>msg</span><span class=p>:</span> <span class=nb>str</span><span class=p>)</span> <span class=o>-></span> <span class=kc>None</span><span class=p>:</span>
|
|
<span class=nb>print</span><span class=p>(</span><span class=sa>f</span><span class=s2>"</span><span class=si>{</span><span class=bp>self</span><span class=o>.</span><span class=n>component_cls</span><span class=o>.</span><span class=vm>__name__</span><span class=si>}</span><span class=s2>: </span><span class=si>{</span><span class=n>msg</span><span class=si>}</span><span class=s2>"</span><span class=p>)</span>
|
|
<span class=err>```</span>
|
|
</code></pre></div> <p><strong>Slots</strong></p> <ul> <li> <p><code>SlotContent</code> was renamed to <code>SlotInput</code>. The old name is deprecated and will be removed in v1.</p> </li> <li> <p><code>SlotRef</code> was renamed to <code>SlotFallback</code>. The old name is deprecated and will be removed in v1.</p> </li> <li> <p>The <code>default</code> kwarg in <code>{% fill %}</code> tag was renamed to <code>fallback</code>. The old name is deprecated and will be removed in v1.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-55-1 name=__codelineno-55-1 href=#__codelineno-55-1></a><span class=cp>{%</span> <span class=k>fill</span> <span class=s2>"footer"</span> <span class=nv>default</span><span class=o>=</span><span class=s2>"footer"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-55-2 name=__codelineno-55-2 href=#__codelineno-55-2></a><span class=x> </span><span class=cp>{{</span> <span class=nv>footer</span> <span class=cp>}}</span>
|
|
<a id=__codelineno-55-3 name=__codelineno-55-3 href=#__codelineno-55-3></a><span class=cp>{%</span> <span class=k>endfill</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-56-1 name=__codelineno-56-1 href=#__codelineno-56-1></a><span class=cp>{%</span> <span class=k>fill</span> <span class=s2>"footer"</span> <span class=nv>fallback</span><span class=o>=</span><span class=s2>"footer"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-56-2 name=__codelineno-56-2 href=#__codelineno-56-2></a><span class=x> </span><span class=cp>{{</span> <span class=nv>footer</span> <span class=cp>}}</span>
|
|
<a id=__codelineno-56-3 name=__codelineno-56-3 href=#__codelineno-56-3></a><span class=cp>{%</span> <span class=k>endfill</span> <span class=cp>%}</span>
|
|
</code></pre></div> </li> <li> <p>The template variable <code>{{ component_vars.is_filled }}</code> is now deprecated. Will be removed in v1. Use <code>{{ component_vars.slots }}</code> instead.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-57-1 name=__codelineno-57-1 href=#__codelineno-57-1></a><span class=cp>{%</span> <span class=k>if</span> <span class=nv>component_vars.is_filled.footer</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-57-2 name=__codelineno-57-2 href=#__codelineno-57-2></a><span class=x> <div></span>
|
|
<a id=__codelineno-57-3 name=__codelineno-57-3 href=#__codelineno-57-3></a><span class=x> </span><span class=cp>{%</span> <span class=k>slot</span> <span class=s2>"footer"</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-57-4 name=__codelineno-57-4 href=#__codelineno-57-4></a><span class=x> </div></span>
|
|
<a id=__codelineno-57-5 name=__codelineno-57-5 href=#__codelineno-57-5></a><span class=cp>{%</span> <span class=k>endif</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-58-1 name=__codelineno-58-1 href=#__codelineno-58-1></a><span class=cp>{%</span> <span class=k>if</span> <span class=nv>component_vars.slots.footer</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-58-2 name=__codelineno-58-2 href=#__codelineno-58-2></a><span class=x> <div></span>
|
|
<a id=__codelineno-58-3 name=__codelineno-58-3 href=#__codelineno-58-3></a><span class=x> </span><span class=cp>{%</span> <span class=k>slot</span> <span class=s2>"footer"</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-58-4 name=__codelineno-58-4 href=#__codelineno-58-4></a><span class=x> </div></span>
|
|
<a id=__codelineno-58-5 name=__codelineno-58-5 href=#__codelineno-58-5></a><span class=cp>{%</span> <span class=k>endif</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>NOTE: <code>component_vars.is_filled</code> automatically escaped slot names, so that even slot names that are not valid python identifiers could be set as slot names. <code>component_vars.slots</code> no longer does that.</p> </li> <li> <p>Component attribute <code>Component.is_filled</code> is now deprecated. Will be removed in v1. Use <code>Component.slots</code> instead.</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-59-1 name=__codelineno-59-1 href=#__codelineno-59-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-59-2 name=__codelineno-59-2 href=#__codelineno-59-2></a> <span class=k>def</span><span class=w> </span><span class=nf>get_template_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>args</span><span class=p>,</span> <span class=n>kwargs</span><span class=p>,</span> <span class=n>slots</span><span class=p>,</span> <span class=n>context</span><span class=p>):</span>
|
|
<a id=__codelineno-59-3 name=__codelineno-59-3 href=#__codelineno-59-3></a> <span class=k>if</span> <span class=bp>self</span><span class=o>.</span><span class=n>is_filled</span><span class=o>.</span><span class=n>footer</span><span class=p>:</span>
|
|
<a id=__codelineno-59-4 name=__codelineno-59-4 href=#__codelineno-59-4></a> <span class=n>color</span> <span class=o>=</span> <span class=s2>"red"</span>
|
|
<a id=__codelineno-59-5 name=__codelineno-59-5 href=#__codelineno-59-5></a> <span class=k>else</span><span class=p>:</span>
|
|
<a id=__codelineno-59-6 name=__codelineno-59-6 href=#__codelineno-59-6></a> <span class=n>color</span> <span class=o>=</span> <span class=s2>"blue"</span>
|
|
<a id=__codelineno-59-7 name=__codelineno-59-7 href=#__codelineno-59-7></a>
|
|
<a id=__codelineno-59-8 name=__codelineno-59-8 href=#__codelineno-59-8></a> <span class=k>return</span> <span class=p>{</span>
|
|
<a id=__codelineno-59-9 name=__codelineno-59-9 href=#__codelineno-59-9></a> <span class=s2>"color"</span><span class=p>:</span> <span class=n>color</span><span class=p>,</span>
|
|
<a id=__codelineno-59-10 name=__codelineno-59-10 href=#__codelineno-59-10></a> <span class=p>}</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-60-1 name=__codelineno-60-1 href=#__codelineno-60-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-60-2 name=__codelineno-60-2 href=#__codelineno-60-2></a> <span class=k>def</span><span class=w> </span><span class=nf>get_template_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>args</span><span class=p>,</span> <span class=n>kwargs</span><span class=p>,</span> <span class=n>slots</span><span class=p>,</span> <span class=n>context</span><span class=p>):</span>
|
|
<a id=__codelineno-60-3 name=__codelineno-60-3 href=#__codelineno-60-3></a> <span class=k>if</span> <span class=s2>"footer"</span> <span class=ow>in</span> <span class=n>slots</span><span class=p>:</span>
|
|
<a id=__codelineno-60-4 name=__codelineno-60-4 href=#__codelineno-60-4></a> <span class=n>color</span> <span class=o>=</span> <span class=s2>"red"</span>
|
|
<a id=__codelineno-60-5 name=__codelineno-60-5 href=#__codelineno-60-5></a> <span class=k>else</span><span class=p>:</span>
|
|
<a id=__codelineno-60-6 name=__codelineno-60-6 href=#__codelineno-60-6></a> <span class=n>color</span> <span class=o>=</span> <span class=s2>"blue"</span>
|
|
<a id=__codelineno-60-7 name=__codelineno-60-7 href=#__codelineno-60-7></a>
|
|
<a id=__codelineno-60-8 name=__codelineno-60-8 href=#__codelineno-60-8></a> <span class=k>return</span> <span class=p>{</span>
|
|
<a id=__codelineno-60-9 name=__codelineno-60-9 href=#__codelineno-60-9></a> <span class=s2>"color"</span><span class=p>:</span> <span class=n>color</span><span class=p>,</span>
|
|
<a id=__codelineno-60-10 name=__codelineno-60-10 href=#__codelineno-60-10></a> <span class=p>}</span>
|
|
</code></pre></div> <p>NOTE: <code>Component.is_filled</code> automatically escaped slot names, so that even slot names that are not valid python identifiers could be set as slot names. <code>Component.slots</code> no longer does that.</p> </li> </ul> <p><strong>Miscellaneous</strong></p> <ul> <li> <p>Template caching with <code>cached_template()</code> helper and <code>template_cache_size</code> setting is deprecated. These will be removed in v1.</p> <p>This feature made sense if you were dynamically generating templates for components using <code>Component.get_template_string()</code> and <code>Component.get_template()</code>.</p> <p>However, in v1, each Component will have at most one static template. This static template is cached internally per component class, and reused across renders.</p> <p>This makes the template caching feature obsolete.</p> <p>If you relied on <code>cached_template()</code>, you should either:</p> <ol> <li>Wrap the templates as Components.</li> <li>Manage the cache of Templates yourself.</li> </ol> </li> <li> <p>The <code>debug_highlight_components</code> and <code>debug_highlight_slots</code> settings are deprecated. These will be removed in v1.</p> <p>The debug highlighting feature was re-implemented as an extension. As such, the recommended way for enabling it has changed:</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-61-1 name=__codelineno-61-1 href=#__codelineno-61-1></a><span class=n>COMPONENTS</span> <span class=o>=</span> <span class=n>ComponentsSettings</span><span class=p>(</span>
|
|
<a id=__codelineno-61-2 name=__codelineno-61-2 href=#__codelineno-61-2></a> <span class=n>debug_highlight_components</span><span class=o>=</span><span class=kc>True</span><span class=p>,</span>
|
|
<a id=__codelineno-61-3 name=__codelineno-61-3 href=#__codelineno-61-3></a> <span class=n>debug_highlight_slots</span><span class=o>=</span><span class=kc>True</span><span class=p>,</span>
|
|
<a id=__codelineno-61-4 name=__codelineno-61-4 href=#__codelineno-61-4></a><span class=p>)</span>
|
|
</code></pre></div> <p>After:</p> <p>Set <code>extensions_defaults</code> in your <code>settings.py</code> file.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-62-1 name=__codelineno-62-1 href=#__codelineno-62-1></a><span class=n>COMPONENTS</span> <span class=o>=</span> <span class=n>ComponentsSettings</span><span class=p>(</span>
|
|
<a id=__codelineno-62-2 name=__codelineno-62-2 href=#__codelineno-62-2></a> <span class=n>extensions_defaults</span><span class=o>=</span><span class=p>{</span>
|
|
<a id=__codelineno-62-3 name=__codelineno-62-3 href=#__codelineno-62-3></a> <span class=s2>"debug_highlight"</span><span class=p>:</span> <span class=p>{</span>
|
|
<a id=__codelineno-62-4 name=__codelineno-62-4 href=#__codelineno-62-4></a> <span class=s2>"highlight_components"</span><span class=p>:</span> <span class=kc>True</span><span class=p>,</span>
|
|
<a id=__codelineno-62-5 name=__codelineno-62-5 href=#__codelineno-62-5></a> <span class=s2>"highlight_slots"</span><span class=p>:</span> <span class=kc>True</span><span class=p>,</span>
|
|
<a id=__codelineno-62-6 name=__codelineno-62-6 href=#__codelineno-62-6></a> <span class=p>},</span>
|
|
<a id=__codelineno-62-7 name=__codelineno-62-7 href=#__codelineno-62-7></a> <span class=p>},</span>
|
|
<a id=__codelineno-62-8 name=__codelineno-62-8 href=#__codelineno-62-8></a><span class=p>)</span>
|
|
</code></pre></div> <p>Alternatively, you can enable highlighting for specific components by setting <code>Component.DebugHighlight.highlight_components</code> to <code>True</code>:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-63-1 name=__codelineno-63-1 href=#__codelineno-63-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-63-2 name=__codelineno-63-2 href=#__codelineno-63-2></a> <span class=k>class</span><span class=w> </span><span class=nc>DebugHighlight</span><span class=p>:</span>
|
|
<a id=__codelineno-63-3 name=__codelineno-63-3 href=#__codelineno-63-3></a> <span class=n>highlight_components</span> <span class=o>=</span> <span class=kc>True</span>
|
|
<a id=__codelineno-63-4 name=__codelineno-63-4 href=#__codelineno-63-4></a> <span class=n>highlight_slots</span> <span class=o>=</span> <span class=kc>True</span>
|
|
</code></pre></div> </li> </ul> <h4 id=feat_2>Feat<a class=headerlink href=#feat_2 title="Permanent link">¤</a></h4> <ul> <li> <p>New method to render template variables - <code>get_template_data()</code></p> <p><code>get_template_data()</code> behaves the same way as <code>get_context_data()</code>, but has a different function signature to accept also slots and context.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-64-1 name=__codelineno-64-1 href=#__codelineno-64-1></a><span class=k>class</span><span class=w> </span><span class=nc>Button</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-64-2 name=__codelineno-64-2 href=#__codelineno-64-2></a> <span class=k>def</span><span class=w> </span><span class=nf>get_template_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>args</span><span class=p>,</span> <span class=n>kwargs</span><span class=p>,</span> <span class=n>slots</span><span class=p>,</span> <span class=n>context</span><span class=p>):</span>
|
|
<a id=__codelineno-64-3 name=__codelineno-64-3 href=#__codelineno-64-3></a> <span class=k>return</span> <span class=p>{</span>
|
|
<a id=__codelineno-64-4 name=__codelineno-64-4 href=#__codelineno-64-4></a> <span class=s2>"val1"</span><span class=p>:</span> <span class=n>args</span><span class=p>[</span><span class=mi>0</span><span class=p>],</span>
|
|
<a id=__codelineno-64-5 name=__codelineno-64-5 href=#__codelineno-64-5></a> <span class=s2>"val2"</span><span class=p>:</span> <span class=n>kwargs</span><span class=p>[</span><span class=s2>"field"</span><span class=p>],</span>
|
|
<a id=__codelineno-64-6 name=__codelineno-64-6 href=#__codelineno-64-6></a> <span class=p>}</span>
|
|
</code></pre></div> <p>If you define <code>Component.Args</code>, <code>Component.Kwargs</code>, <code>Component.Slots</code>, then the <code>args</code>, <code>kwargs</code>, <code>slots</code> arguments will be instances of these classes:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-65-1 name=__codelineno-65-1 href=#__codelineno-65-1></a><span class=k>class</span><span class=w> </span><span class=nc>Button</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-65-2 name=__codelineno-65-2 href=#__codelineno-65-2></a> <span class=k>class</span><span class=w> </span><span class=nc>Args</span><span class=p>(</span><span class=n>NamedTuple</span><span class=p>):</span>
|
|
<a id=__codelineno-65-3 name=__codelineno-65-3 href=#__codelineno-65-3></a> <span class=n>field1</span><span class=p>:</span> <span class=nb>str</span>
|
|
<a id=__codelineno-65-4 name=__codelineno-65-4 href=#__codelineno-65-4></a>
|
|
<a id=__codelineno-65-5 name=__codelineno-65-5 href=#__codelineno-65-5></a> <span class=k>class</span><span class=w> </span><span class=nc>Kwargs</span><span class=p>(</span><span class=n>NamedTuple</span><span class=p>):</span>
|
|
<a id=__codelineno-65-6 name=__codelineno-65-6 href=#__codelineno-65-6></a> <span class=n>field2</span><span class=p>:</span> <span class=nb>int</span>
|
|
<a id=__codelineno-65-7 name=__codelineno-65-7 href=#__codelineno-65-7></a>
|
|
<a id=__codelineno-65-8 name=__codelineno-65-8 href=#__codelineno-65-8></a> <span class=k>def</span><span class=w> </span><span class=nf>get_template_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>args</span><span class=p>:</span> <span class=n>Args</span><span class=p>,</span> <span class=n>kwargs</span><span class=p>:</span> <span class=n>Kwargs</span><span class=p>,</span> <span class=n>slots</span><span class=p>,</span> <span class=n>context</span><span class=p>):</span>
|
|
<a id=__codelineno-65-9 name=__codelineno-65-9 href=#__codelineno-65-9></a> <span class=k>return</span> <span class=p>{</span>
|
|
<a id=__codelineno-65-10 name=__codelineno-65-10 href=#__codelineno-65-10></a> <span class=s2>"val1"</span><span class=p>:</span> <span class=n>args</span><span class=o>.</span><span class=n>field1</span><span class=p>,</span>
|
|
<a id=__codelineno-65-11 name=__codelineno-65-11 href=#__codelineno-65-11></a> <span class=s2>"val2"</span><span class=p>:</span> <span class=n>kwargs</span><span class=o>.</span><span class=n>field2</span><span class=p>,</span>
|
|
<a id=__codelineno-65-12 name=__codelineno-65-12 href=#__codelineno-65-12></a> <span class=p>}</span>
|
|
</code></pre></div> </li> <li> <p>Input validation is now part of the render process.</p> <p>When you specify the input types (such as <code>Component.Args</code>, <code>Component.Kwargs</code>, etc), the actual inputs to data methods (<code>Component.get_template_data()</code>, etc) will be instances of the types you specified.</p> <p>This practically brings back input validation, because the instantiation of the types will raise an error if the inputs are not valid.</p> <p>Read more on <a href=https://django-components.github.io/django-components/latest/concepts/fundamentals/typing_and_validation/ >Typing and validation</a></p> </li> <li> <p>Render emails or other non-browser HTML with new "dependencies strategies"</p> <p>When rendering a component with <code>Component.render()</code> or <code>Component.render_to_response()</code>, the <code>deps_strategy</code> kwarg (previously <code>type</code>) now accepts additional options:</p> <ul> <li><code>"simple"</code></li> <li><code>"prepend"</code></li> <li><code>"append"</code></li> <li><code>"ignore"</code></li> </ul> <div class=highlight><pre><span></span><code><a id=__codelineno-66-1 name=__codelineno-66-1 href=#__codelineno-66-1></a><span class=n>Calendar</span><span class=o>.</span><span class=n>render_to_response</span><span class=p>(</span>
|
|
<a id=__codelineno-66-2 name=__codelineno-66-2 href=#__codelineno-66-2></a> <span class=n>request</span><span class=o>=</span><span class=n>request</span><span class=p>,</span>
|
|
<a id=__codelineno-66-3 name=__codelineno-66-3 href=#__codelineno-66-3></a> <span class=n>kwargs</span><span class=o>=</span><span class=p>{</span>
|
|
<a id=__codelineno-66-4 name=__codelineno-66-4 href=#__codelineno-66-4></a> <span class=s2>"date"</span><span class=p>:</span> <span class=n>request</span><span class=o>.</span><span class=n>GET</span><span class=o>.</span><span class=n>get</span><span class=p>(</span><span class=s2>"date"</span><span class=p>,</span> <span class=s2>""</span><span class=p>),</span>
|
|
<a id=__codelineno-66-5 name=__codelineno-66-5 href=#__codelineno-66-5></a> <span class=p>},</span>
|
|
<a id=__codelineno-66-6 name=__codelineno-66-6 href=#__codelineno-66-6></a> <span class=n>deps_strategy</span><span class=o>=</span><span class=s2>"append"</span><span class=p>,</span>
|
|
<a id=__codelineno-66-7 name=__codelineno-66-7 href=#__codelineno-66-7></a><span class=p>)</span>
|
|
</code></pre></div> <p>Comparison of dependencies render strategies:</p> <ul> <li><code>"document"</code><ul> <li>Smartly inserts JS / CSS into placeholders or into <code><head></code> and <code><body></code> tags.</li> <li>Inserts extra script to allow <code>fragment</code> strategy to work.</li> <li>Assumes the HTML will be rendered in a JS-enabled browser.</li> </ul> </li> <li><code>"fragment"</code><ul> <li>A lightweight HTML fragment to be inserted into a document with AJAX.</li> <li>Ignores placeholders and any <code><head></code> / <code><body></code> tags.</li> <li>No JS / CSS included.</li> </ul> </li> <li><code>"simple"</code><ul> <li>Smartly insert JS / CSS into placeholders or into <code><head></code> and <code><body></code> tags.</li> <li>No extra script loaded.</li> </ul> </li> <li><code>"prepend"</code><ul> <li>Insert JS / CSS before the rendered HTML.</li> <li>Ignores placeholders and any <code><head></code> / <code><body></code> tags.</li> <li>No extra script loaded.</li> </ul> </li> <li><code>"append"</code><ul> <li>Insert JS / CSS after the rendered HTML.</li> <li>Ignores placeholders and any <code><head></code> / <code><body></code> tags.</li> <li>No extra script loaded.</li> </ul> </li> <li><code>"ignore"</code><ul> <li>Rendered HTML is left as-is. You can still process it with a different strategy later with <code>render_dependencies()</code>.</li> <li>Used for inserting rendered HTML into other components.</li> </ul> </li> </ul> <p>See <a href=https://django-components.github.io/django-components/0.140.1/concepts/advanced/rendering_js_css/ >Dependencies rendering</a> for more info.</p> </li> <li> <p>New <code>Component.args</code>, <code>Component.kwargs</code>, <code>Component.slots</code> attributes available on the component class itself.</p> <p>These attributes are the same as the ones available in <code>Component.get_template_data()</code>.</p> <p>You can use these in other methods like <code>Component.on_render_before()</code> or <code>Component.on_render_after()</code>.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-67-1 name=__codelineno-67-1 href=#__codelineno-67-1></a><span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>Component</span><span class=p>,</span> <span class=n>SlotInput</span>
|
|
<a id=__codelineno-67-2 name=__codelineno-67-2 href=#__codelineno-67-2></a>
|
|
<a id=__codelineno-67-3 name=__codelineno-67-3 href=#__codelineno-67-3></a><span class=k>class</span><span class=w> </span><span class=nc>Table</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-67-4 name=__codelineno-67-4 href=#__codelineno-67-4></a> <span class=k>class</span><span class=w> </span><span class=nc>Args</span><span class=p>(</span><span class=n>NamedTuple</span><span class=p>):</span>
|
|
<a id=__codelineno-67-5 name=__codelineno-67-5 href=#__codelineno-67-5></a> <span class=n>page</span><span class=p>:</span> <span class=nb>int</span>
|
|
<a id=__codelineno-67-6 name=__codelineno-67-6 href=#__codelineno-67-6></a>
|
|
<a id=__codelineno-67-7 name=__codelineno-67-7 href=#__codelineno-67-7></a> <span class=k>class</span><span class=w> </span><span class=nc>Kwargs</span><span class=p>(</span><span class=n>NamedTuple</span><span class=p>):</span>
|
|
<a id=__codelineno-67-8 name=__codelineno-67-8 href=#__codelineno-67-8></a> <span class=n>per_page</span><span class=p>:</span> <span class=nb>int</span>
|
|
<a id=__codelineno-67-9 name=__codelineno-67-9 href=#__codelineno-67-9></a>
|
|
<a id=__codelineno-67-10 name=__codelineno-67-10 href=#__codelineno-67-10></a> <span class=k>class</span><span class=w> </span><span class=nc>Slots</span><span class=p>(</span><span class=n>NamedTuple</span><span class=p>):</span>
|
|
<a id=__codelineno-67-11 name=__codelineno-67-11 href=#__codelineno-67-11></a> <span class=n>content</span><span class=p>:</span> <span class=n>SlotInput</span>
|
|
<a id=__codelineno-67-12 name=__codelineno-67-12 href=#__codelineno-67-12></a>
|
|
<a id=__codelineno-67-13 name=__codelineno-67-13 href=#__codelineno-67-13></a> <span class=k>def</span><span class=w> </span><span class=nf>on_render_before</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>context</span><span class=p>:</span> <span class=n>Context</span><span class=p>,</span> <span class=n>template</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>Template</span><span class=p>])</span> <span class=o>-></span> <span class=kc>None</span><span class=p>:</span>
|
|
<a id=__codelineno-67-14 name=__codelineno-67-14 href=#__codelineno-67-14></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>args</span><span class=o>.</span><span class=n>page</span> <span class=o>==</span> <span class=mi>123</span>
|
|
<a id=__codelineno-67-15 name=__codelineno-67-15 href=#__codelineno-67-15></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>kwargs</span><span class=o>.</span><span class=n>per_page</span> <span class=o>==</span> <span class=mi>10</span>
|
|
<a id=__codelineno-67-16 name=__codelineno-67-16 href=#__codelineno-67-16></a> <span class=n>content_html</span> <span class=o>=</span> <span class=bp>self</span><span class=o>.</span><span class=n>slots</span><span class=o>.</span><span class=n>content</span><span class=p>()</span>
|
|
</code></pre></div> <p>Same as with the parameters in <code>Component.get_template_data()</code>, they will be instances of the <code>Args</code>, <code>Kwargs</code>, <code>Slots</code> classes if defined, or plain lists / dictionaries otherwise.</p> </li> <li> <p>4 attributes that were previously available only under the <code>Component.input</code> attribute are now available directly on the Component instance:</p> <ul> <li><code>Component.raw_args</code></li> <li><code>Component.raw_kwargs</code></li> <li><code>Component.raw_slots</code></li> <li><code>Component.deps_strategy</code></li> </ul> <p>The first 3 attributes are the same as the deprecated <code>Component.input.args</code>, <code>Component.input.kwargs</code>, <code>Component.input.slots</code> properties.</p> <p>Compared to the <code>Component.args</code> / <code>Component.kwargs</code> / <code>Component.slots</code> attributes, these "raw" attributes are not typed and will remain as plain lists / dictionaries even if you define the <code>Args</code>, <code>Kwargs</code>, <code>Slots</code> classes.</p> <p>The <code>Component.deps_strategy</code> attribute is the same as the deprecated <code>Component.input.deps_strategy</code> property.</p> </li> <li> <p>New template variables <code>{{ component_vars.args }}</code>, <code>{{ component_vars.kwargs }}</code>, <code>{{ component_vars.slots }}</code></p> <p>These attributes are the same as the ones available in <code>Component.get_template_data()</code>.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-68-1 name=__codelineno-68-1 href=#__codelineno-68-1></a><span class=c>{# Typed #}</span>
|
|
<a id=__codelineno-68-2 name=__codelineno-68-2 href=#__codelineno-68-2></a><span class=cp>{%</span> <span class=k>if</span> <span class=nv>component_vars.args.page</span> <span class=o>==</span> <span class=m>123</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-68-3 name=__codelineno-68-3 href=#__codelineno-68-3></a><span class=x> <div></span>
|
|
<a id=__codelineno-68-4 name=__codelineno-68-4 href=#__codelineno-68-4></a><span class=x> </span><span class=cp>{%</span> <span class=k>slot</span> <span class=s2>"content"</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-68-5 name=__codelineno-68-5 href=#__codelineno-68-5></a><span class=x> </div></span>
|
|
<a id=__codelineno-68-6 name=__codelineno-68-6 href=#__codelineno-68-6></a><span class=cp>{%</span> <span class=k>endif</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-68-7 name=__codelineno-68-7 href=#__codelineno-68-7></a>
|
|
<a id=__codelineno-68-8 name=__codelineno-68-8 href=#__codelineno-68-8></a><span class=c>{# Untyped #}</span>
|
|
<a id=__codelineno-68-9 name=__codelineno-68-9 href=#__codelineno-68-9></a><span class=cp>{%</span> <span class=k>if</span> <span class=nv>component_vars.args.0</span> <span class=o>==</span> <span class=m>123</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-68-10 name=__codelineno-68-10 href=#__codelineno-68-10></a><span class=x> <div></span>
|
|
<a id=__codelineno-68-11 name=__codelineno-68-11 href=#__codelineno-68-11></a><span class=x> </span><span class=cp>{%</span> <span class=k>slot</span> <span class=s2>"content"</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-68-12 name=__codelineno-68-12 href=#__codelineno-68-12></a><span class=x> </div></span>
|
|
<a id=__codelineno-68-13 name=__codelineno-68-13 href=#__codelineno-68-13></a><span class=cp>{%</span> <span class=k>endif</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>Same as with the parameters in <code>Component.get_template_data()</code>, they will be instances of the <code>Args</code>, <code>Kwargs</code>, <code>Slots</code> classes if defined, or plain lists / dictionaries otherwise.</p> </li> <li> <p>New component lifecycle hook <code>Component.on_render()</code>.</p> <p>This hook is called when the component is being rendered.</p> <p>You can override this method to:</p> <ul> <li>Change what template gets rendered</li> <li>Modify the context</li> <li>Modify the rendered output after it has been rendered</li> <li>Handle errors</li> </ul> <p>See <a href=https://django-components.github.io/django-components/0.140.1/concepts/advanced/hooks/#on_render>on_render</a> for more info.</p> </li> <li> <p><code>get_component_url()</code> now optionally accepts <code>query</code> and <code>fragment</code> arguments.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-69-1 name=__codelineno-69-1 href=#__codelineno-69-1></a><span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>get_component_url</span>
|
|
<a id=__codelineno-69-2 name=__codelineno-69-2 href=#__codelineno-69-2></a>
|
|
<a id=__codelineno-69-3 name=__codelineno-69-3 href=#__codelineno-69-3></a><span class=n>url</span> <span class=o>=</span> <span class=n>get_component_url</span><span class=p>(</span>
|
|
<a id=__codelineno-69-4 name=__codelineno-69-4 href=#__codelineno-69-4></a> <span class=n>MyComponent</span><span class=p>,</span>
|
|
<a id=__codelineno-69-5 name=__codelineno-69-5 href=#__codelineno-69-5></a> <span class=n>query</span><span class=o>=</span><span class=p>{</span><span class=s2>"foo"</span><span class=p>:</span> <span class=s2>"bar"</span><span class=p>},</span>
|
|
<a id=__codelineno-69-6 name=__codelineno-69-6 href=#__codelineno-69-6></a> <span class=n>fragment</span><span class=o>=</span><span class=s2>"baz"</span><span class=p>,</span>
|
|
<a id=__codelineno-69-7 name=__codelineno-69-7 href=#__codelineno-69-7></a><span class=p>)</span>
|
|
<a id=__codelineno-69-8 name=__codelineno-69-8 href=#__codelineno-69-8></a><span class=c1># /components/ext/view/components/c1ab2c3?foo=bar#baz</span>
|
|
</code></pre></div> </li> <li> <p>The <code>BaseNode</code> class has a new <code>contents</code> attribute, which contains the raw contents (string) of the tag body.</p> <p>This is relevant when you define custom template tags with <code>@template_tag</code> decorator or <code>BaseNode</code> class.</p> <p>When you define a custom template tag like so:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-70-1 name=__codelineno-70-1 href=#__codelineno-70-1></a><span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>BaseNode</span><span class=p>,</span> <span class=n>template_tag</span>
|
|
<a id=__codelineno-70-2 name=__codelineno-70-2 href=#__codelineno-70-2></a>
|
|
<a id=__codelineno-70-3 name=__codelineno-70-3 href=#__codelineno-70-3></a><span class=nd>@template_tag</span><span class=p>(</span>
|
|
<a id=__codelineno-70-4 name=__codelineno-70-4 href=#__codelineno-70-4></a> <span class=n>library</span><span class=p>,</span>
|
|
<a id=__codelineno-70-5 name=__codelineno-70-5 href=#__codelineno-70-5></a> <span class=n>tag</span><span class=o>=</span><span class=s2>"mytag"</span><span class=p>,</span>
|
|
<a id=__codelineno-70-6 name=__codelineno-70-6 href=#__codelineno-70-6></a> <span class=n>end_tag</span><span class=o>=</span><span class=s2>"endmytag"</span><span class=p>,</span>
|
|
<a id=__codelineno-70-7 name=__codelineno-70-7 href=#__codelineno-70-7></a> <span class=n>allowed_flags</span><span class=o>=</span><span class=p>[</span><span class=s2>"required"</span><span class=p>]</span>
|
|
<a id=__codelineno-70-8 name=__codelineno-70-8 href=#__codelineno-70-8></a><span class=p>)</span>
|
|
<a id=__codelineno-70-9 name=__codelineno-70-9 href=#__codelineno-70-9></a><span class=k>def</span><span class=w> </span><span class=nf>mytag</span><span class=p>(</span><span class=n>node</span><span class=p>:</span> <span class=n>BaseNode</span><span class=p>,</span> <span class=n>context</span><span class=p>:</span> <span class=n>Context</span><span class=p>,</span> <span class=n>name</span><span class=p>:</span> <span class=nb>str</span><span class=p>,</span> <span class=o>**</span><span class=n>kwargs</span><span class=p>)</span> <span class=o>-></span> <span class=nb>str</span><span class=p>:</span>
|
|
<a id=__codelineno-70-10 name=__codelineno-70-10 href=#__codelineno-70-10></a> <span class=nb>print</span><span class=p>(</span><span class=n>node</span><span class=o>.</span><span class=n>contents</span><span class=p>)</span>
|
|
<a id=__codelineno-70-11 name=__codelineno-70-11 href=#__codelineno-70-11></a> <span class=k>return</span> <span class=sa>f</span><span class=s2>"Hello, </span><span class=si>{</span><span class=n>name</span><span class=si>}</span><span class=s2>!"</span>
|
|
</code></pre></div> <p>And render it like so:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-71-1 name=__codelineno-71-1 href=#__codelineno-71-1></a><span class=cp>{%</span> <span class=k>mytag</span> <span class=nv>name</span><span class=o>=</span><span class=s2>"John"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-71-2 name=__codelineno-71-2 href=#__codelineno-71-2></a><span class=x> Hello, world!</span>
|
|
<a id=__codelineno-71-3 name=__codelineno-71-3 href=#__codelineno-71-3></a><span class=cp>{%</span> <span class=k>endmytag</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>Then, the <code>contents</code> attribute of the <code>BaseNode</code> instance will contain the string <code>"Hello, world!"</code>.</p> </li> <li> <p>The <code>BaseNode</code> class also has two new metadata attributes:</p> <ul> <li><code>template_name</code> - the name of the template that rendered the node.</li> <li><code>template_component</code> - the component class that the template belongs to.</li> </ul> <p>This is useful for debugging purposes.</p> </li> <li> <p><code>Slot</code> class now has 3 new metadata fields:</p> <ol> <li> <p><code>Slot.contents</code> attribute contains the original contents:</p> <ul> <li>If <code>Slot</code> was created from <code>{% fill %}</code> tag, <code>Slot.contents</code> will contain the body of the <code>{% fill %}</code> tag.</li> <li>If <code>Slot</code> was created from string via <code>Slot("...")</code>, <code>Slot.contents</code> will contain that string.</li> <li>If <code>Slot</code> was created from a function, <code>Slot.contents</code> will contain that function.</li> </ul> </li> <li> <p><code>Slot.extra</code> attribute where you can put arbitrary metadata about the slot.</p> </li> <li> <p><code>Slot.fill_node</code> attribute tells where the slot comes from:</p> <ul> <li><code>FillNode</code> instance if the slot was created from <code>{% fill %}</code> tag.</li> <li><code>ComponentNode</code> instance if the slot was created as a default slot from a <code>{% component %}</code> tag.</li> <li><code>None</code> if the slot was created from a string, function, or <code>Slot</code> instance.</li> </ul> </li> </ol> <p>See <a href=https://django-components.github.io/django-components/0.140.1/concepts/fundamentals/slots/#slot-metadata>Slot metadata</a>.</p> </li> <li> <p><code>{% fill %}</code> tag now accepts <code>body</code> kwarg to pass a Slot instance to fill.</p> <p>First pass a <code>Slot</code> instance to the template with the <code>get_template_data()</code> method:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-72-1 name=__codelineno-72-1 href=#__codelineno-72-1></a><span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>component</span><span class=p>,</span> <span class=n>Slot</span>
|
|
<a id=__codelineno-72-2 name=__codelineno-72-2 href=#__codelineno-72-2></a>
|
|
<a id=__codelineno-72-3 name=__codelineno-72-3 href=#__codelineno-72-3></a><span class=k>class</span><span class=w> </span><span class=nc>Table</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-72-4 name=__codelineno-72-4 href=#__codelineno-72-4></a> <span class=k>def</span><span class=w> </span><span class=nf>get_template_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>args</span><span class=p>,</span> <span class=n>kwargs</span><span class=p>,</span> <span class=n>slots</span><span class=p>,</span> <span class=n>context</span><span class=p>):</span>
|
|
<a id=__codelineno-72-5 name=__codelineno-72-5 href=#__codelineno-72-5></a> <span class=k>return</span> <span class=p>{</span>
|
|
<a id=__codelineno-72-6 name=__codelineno-72-6 href=#__codelineno-72-6></a> <span class=s2>"my_slot"</span><span class=p>:</span> <span class=n>Slot</span><span class=p>(</span><span class=k>lambda</span> <span class=n>ctx</span><span class=p>:</span> <span class=s2>"Hello, world!"</span><span class=p>),</span>
|
|
<a id=__codelineno-72-7 name=__codelineno-72-7 href=#__codelineno-72-7></a> <span class=p>}</span>
|
|
</code></pre></div> <p>Then pass the slot to the <code>{% fill %}</code> tag:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-73-1 name=__codelineno-73-1 href=#__codelineno-73-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"table"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-73-2 name=__codelineno-73-2 href=#__codelineno-73-2></a><span class=x> </span><span class=cp>{%</span> <span class=k>fill</span> <span class=s2>"pagination"</span> <span class=nv>body</span><span class=o>=</span><span class=nv>my_slot</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-73-3 name=__codelineno-73-3 href=#__codelineno-73-3></a><span class=cp>{%</span> <span class=k>endcomponent</span> <span class=cp>%}</span>
|
|
</code></pre></div> </li> <li> <p>You can now access the <code>{% component %}</code> tag (<code>ComponentNode</code> instance) from which a Component was created. Use <code>Component.node</code> to access it.</p> <p>This is mostly useful for extensions, which can use this to detect if the given Component comes from a <code>{% component %}</code> tag or from a different source (such as <code>Component.render()</code>).</p> <p><code>Component.node</code> is <code>None</code> if the component is created by <code>Component.render()</code> (but you can pass in the <code>node</code> kwarg yourself).</p> <div class=highlight><pre><span></span><code><a id=__codelineno-74-1 name=__codelineno-74-1 href=#__codelineno-74-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-74-2 name=__codelineno-74-2 href=#__codelineno-74-2></a> <span class=k>def</span><span class=w> </span><span class=nf>get_template_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>context</span><span class=p>,</span> <span class=n>template</span><span class=p>):</span>
|
|
<a id=__codelineno-74-3 name=__codelineno-74-3 href=#__codelineno-74-3></a> <span class=k>if</span> <span class=bp>self</span><span class=o>.</span><span class=n>node</span> <span class=ow>is</span> <span class=ow>not</span> <span class=kc>None</span><span class=p>:</span>
|
|
<a id=__codelineno-74-4 name=__codelineno-74-4 href=#__codelineno-74-4></a> <span class=k>assert</span> <span class=bp>self</span><span class=o>.</span><span class=n>node</span><span class=o>.</span><span class=n>name</span> <span class=o>==</span> <span class=s2>"my_component"</span>
|
|
</code></pre></div> </li> <li> <p>Node classes <code>ComponentNode</code>, <code>FillNode</code>, <code>ProvideNode</code>, and <code>SlotNode</code> are part of the public API.</p> <p>These classes are what is instantiated when you use <code>{% component %}</code>, <code>{% fill %}</code>, <code>{% provide %}</code>, and <code>{% slot %}</code> tags.</p> <p>You can for example use these for type hints:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-75-1 name=__codelineno-75-1 href=#__codelineno-75-1></a><span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>Component</span><span class=p>,</span> <span class=n>ComponentNode</span>
|
|
<a id=__codelineno-75-2 name=__codelineno-75-2 href=#__codelineno-75-2></a>
|
|
<a id=__codelineno-75-3 name=__codelineno-75-3 href=#__codelineno-75-3></a><span class=k>class</span><span class=w> </span><span class=nc>MyTable</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-75-4 name=__codelineno-75-4 href=#__codelineno-75-4></a> <span class=k>def</span><span class=w> </span><span class=nf>get_template_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>args</span><span class=p>,</span> <span class=n>kwargs</span><span class=p>,</span> <span class=n>slots</span><span class=p>,</span> <span class=n>context</span><span class=p>):</span>
|
|
<a id=__codelineno-75-5 name=__codelineno-75-5 href=#__codelineno-75-5></a> <span class=k>if</span> <span class=n>kwargs</span><span class=o>.</span><span class=n>get</span><span class=p>(</span><span class=s2>"show_owner"</span><span class=p>):</span>
|
|
<a id=__codelineno-75-6 name=__codelineno-75-6 href=#__codelineno-75-6></a> <span class=n>node</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>ComponentNode</span><span class=p>]</span> <span class=o>=</span> <span class=bp>self</span><span class=o>.</span><span class=n>node</span>
|
|
<a id=__codelineno-75-7 name=__codelineno-75-7 href=#__codelineno-75-7></a> <span class=n>owner</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=n>Component</span><span class=p>]</span> <span class=o>=</span> <span class=bp>self</span><span class=o>.</span><span class=n>node</span><span class=o>.</span><span class=n>template_component</span>
|
|
<a id=__codelineno-75-8 name=__codelineno-75-8 href=#__codelineno-75-8></a> <span class=k>else</span><span class=p>:</span>
|
|
<a id=__codelineno-75-9 name=__codelineno-75-9 href=#__codelineno-75-9></a> <span class=n>node</span> <span class=o>=</span> <span class=kc>None</span>
|
|
<a id=__codelineno-75-10 name=__codelineno-75-10 href=#__codelineno-75-10></a> <span class=n>owner</span> <span class=o>=</span> <span class=kc>None</span>
|
|
<a id=__codelineno-75-11 name=__codelineno-75-11 href=#__codelineno-75-11></a>
|
|
<a id=__codelineno-75-12 name=__codelineno-75-12 href=#__codelineno-75-12></a> <span class=k>return</span> <span class=p>{</span>
|
|
<a id=__codelineno-75-13 name=__codelineno-75-13 href=#__codelineno-75-13></a> <span class=s2>"owner"</span><span class=p>:</span> <span class=n>owner</span><span class=p>,</span>
|
|
<a id=__codelineno-75-14 name=__codelineno-75-14 href=#__codelineno-75-14></a> <span class=s2>"node"</span><span class=p>:</span> <span class=n>node</span><span class=p>,</span>
|
|
<a id=__codelineno-75-15 name=__codelineno-75-15 href=#__codelineno-75-15></a> <span class=p>}</span>
|
|
</code></pre></div> </li> <li> <p>Component caching can now take slots into account, by setting <code>Component.Cache.include_slots</code> to <code>True</code>.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-76-1 name=__codelineno-76-1 href=#__codelineno-76-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-76-2 name=__codelineno-76-2 href=#__codelineno-76-2></a> <span class=k>class</span><span class=w> </span><span class=nc>Cache</span><span class=p>:</span>
|
|
<a id=__codelineno-76-3 name=__codelineno-76-3 href=#__codelineno-76-3></a> <span class=n>enabled</span> <span class=o>=</span> <span class=kc>True</span>
|
|
<a id=__codelineno-76-4 name=__codelineno-76-4 href=#__codelineno-76-4></a> <span class=n>include_slots</span> <span class=o>=</span> <span class=kc>True</span>
|
|
</code></pre></div> <p>In which case the following two calls will generate separate cache entries:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-77-1 name=__codelineno-77-1 href=#__codelineno-77-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"my_component"</span> <span class=nv>position</span><span class=o>=</span><span class=s2>"left"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-77-2 name=__codelineno-77-2 href=#__codelineno-77-2></a><span class=x> Hello, Alice</span>
|
|
<a id=__codelineno-77-3 name=__codelineno-77-3 href=#__codelineno-77-3></a><span class=cp>{%</span> <span class=k>endcomponent</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-77-4 name=__codelineno-77-4 href=#__codelineno-77-4></a>
|
|
<a id=__codelineno-77-5 name=__codelineno-77-5 href=#__codelineno-77-5></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"my_component"</span> <span class=nv>position</span><span class=o>=</span><span class=s2>"left"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-77-6 name=__codelineno-77-6 href=#__codelineno-77-6></a><span class=x> Hello, Bob</span>
|
|
<a id=__codelineno-77-7 name=__codelineno-77-7 href=#__codelineno-77-7></a><span class=cp>{%</span> <span class=k>endcomponent</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>Same applies to <code>Component.render()</code> with string slots:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-78-1 name=__codelineno-78-1 href=#__codelineno-78-1></a><span class=n>MyComponent</span><span class=o>.</span><span class=n>render</span><span class=p>(</span>
|
|
<a id=__codelineno-78-2 name=__codelineno-78-2 href=#__codelineno-78-2></a> <span class=n>kwargs</span><span class=o>=</span><span class=p>{</span><span class=s2>"position"</span><span class=p>:</span> <span class=s2>"left"</span><span class=p>},</span>
|
|
<a id=__codelineno-78-3 name=__codelineno-78-3 href=#__codelineno-78-3></a> <span class=n>slots</span><span class=o>=</span><span class=p>{</span><span class=s2>"content"</span><span class=p>:</span> <span class=s2>"Hello, Alice"</span><span class=p>}</span>
|
|
<a id=__codelineno-78-4 name=__codelineno-78-4 href=#__codelineno-78-4></a><span class=p>)</span>
|
|
<a id=__codelineno-78-5 name=__codelineno-78-5 href=#__codelineno-78-5></a><span class=n>MyComponent</span><span class=o>.</span><span class=n>render</span><span class=p>(</span>
|
|
<a id=__codelineno-78-6 name=__codelineno-78-6 href=#__codelineno-78-6></a> <span class=n>kwargs</span><span class=o>=</span><span class=p>{</span><span class=s2>"position"</span><span class=p>:</span> <span class=s2>"left"</span><span class=p>},</span>
|
|
<a id=__codelineno-78-7 name=__codelineno-78-7 href=#__codelineno-78-7></a> <span class=n>slots</span><span class=o>=</span><span class=p>{</span><span class=s2>"content"</span><span class=p>:</span> <span class=s2>"Hello, Bob"</span><span class=p>}</span>
|
|
<a id=__codelineno-78-8 name=__codelineno-78-8 href=#__codelineno-78-8></a><span class=p>)</span>
|
|
</code></pre></div> <p>Read more on <a href=https://django-components.github.io/django-components/0.140.1/concepts/advanced/component_caching/ >Component caching</a>.</p> </li> <li> <p>New extension hook <code>on_slot_rendered()</code></p> <p>This hook is called when a slot is rendered, and allows you to access and/or modify the rendered result.</p> <p>This is used by the <a href=https://django-components.github.io/django-components/0.140.1/guides/other/troubleshooting/#component-and-slot-highlighting>"debug highlight" feature</a>.</p> <p>To modify the rendered result, return the new value:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-79-1 name=__codelineno-79-1 href=#__codelineno-79-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyExtension</span><span class=p>(</span><span class=n>ComponentExtension</span><span class=p>):</span>
|
|
<a id=__codelineno-79-2 name=__codelineno-79-2 href=#__codelineno-79-2></a> <span class=k>def</span><span class=w> </span><span class=nf>on_slot_rendered</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>ctx</span><span class=p>:</span> <span class=n>OnSlotRenderedContext</span><span class=p>)</span> <span class=o>-></span> <span class=n>Optional</span><span class=p>[</span><span class=nb>str</span><span class=p>]:</span>
|
|
<a id=__codelineno-79-3 name=__codelineno-79-3 href=#__codelineno-79-3></a> <span class=k>return</span> <span class=n>ctx</span><span class=o>.</span><span class=n>result</span> <span class=o>+</span> <span class=s2>"<!-- Hello, world! -->"</span>
|
|
</code></pre></div> <p>If you don't want to modify the rendered result, return <code>None</code>.</p> <p>See all <a href=https://django-components.github.io/django-components/0.140.1/reference/extension_hooks/ >Extension hooks</a>.</p> </li> <li> <p>When creating extensions, the previous syntax with <code>ComponentExtension.ExtensionClass</code> was causing Mypy errors, because Mypy doesn't allow using class attributes as bases:</p> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-80-1 name=__codelineno-80-1 href=#__codelineno-80-1></a><span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>ComponentExtension</span>
|
|
<a id=__codelineno-80-2 name=__codelineno-80-2 href=#__codelineno-80-2></a>
|
|
<a id=__codelineno-80-3 name=__codelineno-80-3 href=#__codelineno-80-3></a><span class=k>class</span><span class=w> </span><span class=nc>MyExtension</span><span class=p>(</span><span class=n>ComponentExtension</span><span class=p>):</span>
|
|
<a id=__codelineno-80-4 name=__codelineno-80-4 href=#__codelineno-80-4></a> <span class=k>class</span><span class=w> </span><span class=nc>ExtensionClass</span><span class=p>(</span><span class=n>ComponentExtension</span><span class=o>.</span><span class=n>ExtensionClass</span><span class=p>):</span> <span class=c1># Error!</span>
|
|
<a id=__codelineno-80-5 name=__codelineno-80-5 href=#__codelineno-80-5></a> <span class=k>pass</span>
|
|
</code></pre></div> <p>Instead, you can import <code>ExtensionComponentConfig</code> directly:</p> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-81-1 name=__codelineno-81-1 href=#__codelineno-81-1></a><span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>ComponentExtension</span><span class=p>,</span> <span class=n>ExtensionComponentConfig</span>
|
|
<a id=__codelineno-81-2 name=__codelineno-81-2 href=#__codelineno-81-2></a>
|
|
<a id=__codelineno-81-3 name=__codelineno-81-3 href=#__codelineno-81-3></a><span class=k>class</span><span class=w> </span><span class=nc>MyExtension</span><span class=p>(</span><span class=n>ComponentExtension</span><span class=p>):</span>
|
|
<a id=__codelineno-81-4 name=__codelineno-81-4 href=#__codelineno-81-4></a> <span class=k>class</span><span class=w> </span><span class=nc>ComponentConfig</span><span class=p>(</span><span class=n>ExtensionComponentConfig</span><span class=p>):</span>
|
|
<a id=__codelineno-81-5 name=__codelineno-81-5 href=#__codelineno-81-5></a> <span class=k>pass</span>
|
|
</code></pre></div> </li> </ul> <h4 id=refactor_1>Refactor<a class=headerlink href=#refactor_1 title="Permanent link">¤</a></h4> <ul> <li> <p>When a component is being rendered, a proper <code>Component</code> instance is now created.</p> <p>Previously, the <code>Component</code> state was managed as half-instance, half-stack.</p> </li> <li> <p>Component's "Render API" (args, kwargs, slots, context, inputs, request, context data, etc) can now be accessed also outside of the render call. So now its possible to take the component instance out of <code>get_template_data()</code> (although this is not recommended).</p> </li> <li> <p>Components can now be defined without a template.</p> <p>Previously, the following would raise an error:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-82-1 name=__codelineno-82-1 href=#__codelineno-82-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-82-2 name=__codelineno-82-2 href=#__codelineno-82-2></a> <span class=k>pass</span>
|
|
</code></pre></div> <p>"Template-less" components can be used together with <code>Component.on_render()</code> to dynamically pick what to render:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-83-1 name=__codelineno-83-1 href=#__codelineno-83-1></a><span class=k>class</span><span class=w> </span><span class=nc>TableNew</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-83-2 name=__codelineno-83-2 href=#__codelineno-83-2></a> <span class=n>template_file</span> <span class=o>=</span> <span class=s2>"table_new.html"</span>
|
|
<a id=__codelineno-83-3 name=__codelineno-83-3 href=#__codelineno-83-3></a>
|
|
<a id=__codelineno-83-4 name=__codelineno-83-4 href=#__codelineno-83-4></a><span class=k>class</span><span class=w> </span><span class=nc>TableOld</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-83-5 name=__codelineno-83-5 href=#__codelineno-83-5></a> <span class=n>template_file</span> <span class=o>=</span> <span class=s2>"table_old.html"</span>
|
|
<a id=__codelineno-83-6 name=__codelineno-83-6 href=#__codelineno-83-6></a>
|
|
<a id=__codelineno-83-7 name=__codelineno-83-7 href=#__codelineno-83-7></a><span class=k>class</span><span class=w> </span><span class=nc>Table</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-83-8 name=__codelineno-83-8 href=#__codelineno-83-8></a> <span class=k>def</span><span class=w> </span><span class=nf>on_render</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>context</span><span class=p>,</span> <span class=n>template</span><span class=p>):</span>
|
|
<a id=__codelineno-83-9 name=__codelineno-83-9 href=#__codelineno-83-9></a> <span class=k>if</span> <span class=bp>self</span><span class=o>.</span><span class=n>kwargs</span><span class=o>.</span><span class=n>get</span><span class=p>(</span><span class=s2>"feat_table_new_ui"</span><span class=p>):</span>
|
|
<a id=__codelineno-83-10 name=__codelineno-83-10 href=#__codelineno-83-10></a> <span class=k>return</span> <span class=n>TableNew</span><span class=o>.</span><span class=n>render</span><span class=p>(</span><span class=n>args</span><span class=o>=</span><span class=bp>self</span><span class=o>.</span><span class=n>args</span><span class=p>,</span> <span class=n>kwargs</span><span class=o>=</span><span class=bp>self</span><span class=o>.</span><span class=n>kwargs</span><span class=p>,</span> <span class=n>slots</span><span class=o>=</span><span class=bp>self</span><span class=o>.</span><span class=n>slots</span><span class=p>)</span>
|
|
<a id=__codelineno-83-11 name=__codelineno-83-11 href=#__codelineno-83-11></a> <span class=k>else</span><span class=p>:</span>
|
|
<a id=__codelineno-83-12 name=__codelineno-83-12 href=#__codelineno-83-12></a> <span class=k>return</span> <span class=n>TableOld</span><span class=o>.</span><span class=n>render</span><span class=p>(</span><span class=n>args</span><span class=o>=</span><span class=bp>self</span><span class=o>.</span><span class=n>args</span><span class=p>,</span> <span class=n>kwargs</span><span class=o>=</span><span class=bp>self</span><span class=o>.</span><span class=n>kwargs</span><span class=p>,</span> <span class=n>slots</span><span class=o>=</span><span class=bp>self</span><span class=o>.</span><span class=n>slots</span><span class=p>)</span>
|
|
</code></pre></div> <p>"Template-less" components can be also used as a base class for other components, or as mixins.</p> </li> <li> <p>Passing <code>Slot</code> instance to <code>Slot</code> constructor raises an error.</p> </li> <li> <p>Extension hook <code>on_component_rendered</code> now receives <code>error</code> field.</p> <p><code>on_component_rendered</code> now behaves similar to <code>Component.on_render_after</code>:</p> <ul> <li>Raising error in this hook overrides what error will be returned from <code>Component.render()</code>.</li> <li>Returning new string overrides what will be returned from <code>Component.render()</code>.</li> </ul> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-84-1 name=__codelineno-84-1 href=#__codelineno-84-1></a><span class=k>class</span><span class=w> </span><span class=nc>OnComponentRenderedContext</span><span class=p>(</span><span class=n>NamedTuple</span><span class=p>):</span>
|
|
<a id=__codelineno-84-2 name=__codelineno-84-2 href=#__codelineno-84-2></a> <span class=n>component</span><span class=p>:</span> <span class=s2>"Component"</span>
|
|
<a id=__codelineno-84-3 name=__codelineno-84-3 href=#__codelineno-84-3></a> <span class=n>component_cls</span><span class=p>:</span> <span class=n>Type</span><span class=p>[</span><span class=s2>"Component"</span><span class=p>]</span>
|
|
<a id=__codelineno-84-4 name=__codelineno-84-4 href=#__codelineno-84-4></a> <span class=n>component_id</span><span class=p>:</span> <span class=nb>str</span>
|
|
<a id=__codelineno-84-5 name=__codelineno-84-5 href=#__codelineno-84-5></a> <span class=n>result</span><span class=p>:</span> <span class=nb>str</span>
|
|
</code></pre></div> <p>After:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-85-1 name=__codelineno-85-1 href=#__codelineno-85-1></a><span class=k>class</span><span class=w> </span><span class=nc>OnComponentRenderedContext</span><span class=p>(</span><span class=n>NamedTuple</span><span class=p>):</span>
|
|
<a id=__codelineno-85-2 name=__codelineno-85-2 href=#__codelineno-85-2></a> <span class=n>component</span><span class=p>:</span> <span class=s2>"Component"</span>
|
|
<a id=__codelineno-85-3 name=__codelineno-85-3 href=#__codelineno-85-3></a> <span class=n>component_cls</span><span class=p>:</span> <span class=n>Type</span><span class=p>[</span><span class=s2>"Component"</span><span class=p>]</span>
|
|
<a id=__codelineno-85-4 name=__codelineno-85-4 href=#__codelineno-85-4></a> <span class=n>component_id</span><span class=p>:</span> <span class=nb>str</span>
|
|
<a id=__codelineno-85-5 name=__codelineno-85-5 href=#__codelineno-85-5></a> <span class=n>result</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=nb>str</span><span class=p>]</span>
|
|
<a id=__codelineno-85-6 name=__codelineno-85-6 href=#__codelineno-85-6></a> <span class=n>error</span><span class=p>:</span> <span class=n>Optional</span><span class=p>[</span><span class=ne>Exception</span><span class=p>]</span>
|
|
</code></pre></div> </li> </ul> <h4 id=fix_6>Fix<a class=headerlink href=#fix_6 title="Permanent link">¤</a></h4> <ul> <li> <p>Fix bug: Context processors data was being generated anew for each component. Now the data is correctly created once and reused across components with the same request (<a href=https://github.com/django-components/django-components/issues/1165>#1165</a>).</p> </li> <li> <p>Fix KeyError on <code>component_context_cache</code> when slots are rendered outside of the component's render context. (<a href=https://github.com/django-components/django-components/issues/1189>#1189</a>)</p> </li> <li> <p>Component classes now have <code>do_not_call_in_templates=True</code> to prevent them from being called as functions in templates.</p> </li> </ul> <h2 id=v01391>v0.139.1<a class=headerlink href=#v01391 title="Permanent link">¤</a></h2> <h4 id=fix_7>Fix<a class=headerlink href=#fix_7 title="Permanent link">¤</a></h4> <ul> <li>Fix compatibility of component caching with <code>{% extend %}</code> block (<a href=https://github.com/django-components/django-components/issues/1135>#1135</a>)</li> </ul> <h4 id=refactor_2>Refactor<a class=headerlink href=#refactor_2 title="Permanent link">¤</a></h4> <ul> <li> <p>Component ID is now prefixed with <code>c</code>, e.g. <code>c123456</code>.</p> </li> <li> <p>When typing a Component, you can now specify as few or as many parameters as you want.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-86-1 name=__codelineno-86-1 href=#__codelineno-86-1></a><span class=n>Component</span><span class=p>[</span><span class=n>Args</span><span class=p>]</span>
|
|
<a id=__codelineno-86-2 name=__codelineno-86-2 href=#__codelineno-86-2></a><span class=n>Component</span><span class=p>[</span><span class=n>Args</span><span class=p>,</span> <span class=n>Kwargs</span><span class=p>]</span>
|
|
<a id=__codelineno-86-3 name=__codelineno-86-3 href=#__codelineno-86-3></a><span class=n>Component</span><span class=p>[</span><span class=n>Args</span><span class=p>,</span> <span class=n>Kwargs</span><span class=p>,</span> <span class=n>Slots</span><span class=p>]</span>
|
|
<a id=__codelineno-86-4 name=__codelineno-86-4 href=#__codelineno-86-4></a><span class=n>Component</span><span class=p>[</span><span class=n>Args</span><span class=p>,</span> <span class=n>Kwargs</span><span class=p>,</span> <span class=n>Slots</span><span class=p>,</span> <span class=n>Data</span><span class=p>]</span>
|
|
<a id=__codelineno-86-5 name=__codelineno-86-5 href=#__codelineno-86-5></a><span class=n>Component</span><span class=p>[</span><span class=n>Args</span><span class=p>,</span> <span class=n>Kwargs</span><span class=p>,</span> <span class=n>Slots</span><span class=p>,</span> <span class=n>Data</span><span class=p>,</span> <span class=n>JsData</span><span class=p>]</span>
|
|
<a id=__codelineno-86-6 name=__codelineno-86-6 href=#__codelineno-86-6></a><span class=n>Component</span><span class=p>[</span><span class=n>Args</span><span class=p>,</span> <span class=n>Kwargs</span><span class=p>,</span> <span class=n>Slots</span><span class=p>,</span> <span class=n>Data</span><span class=p>,</span> <span class=n>JsData</span><span class=p>,</span> <span class=n>CssData</span><span class=p>]</span>
|
|
</code></pre></div> <p>All omitted parameters will default to <code>Any</code>.</p> </li> <li> <p>Added <code>typing_extensions</code> to the project as a dependency</p> </li> <li> <p>Multiple extensions with the same name (case-insensitive) now raise an error</p> </li> <li> <p>Extension names (case-insensitive) also MUST NOT conflict with existing Component class API.</p> <p>So if you name an extension <code>render</code>, it will conflict with the <code>render()</code> method of the <code>Component</code> class, and thus raise an error.</p> </li> </ul> <h2 id=v01390>v0.139.0<a class=headerlink href=#v01390 title="Permanent link">¤</a></h2> <h4 id=fix_8>Fix<a class=headerlink href=#fix_8 title="Permanent link">¤</a></h4> <ul> <li>Fix bug: Fix compatibility with <code>Finder.find()</code> in Django 5.2 (<a href=https://github.com/django-components/django-components/issues/1119>#1119</a>)</li> </ul> <h2 id=v0138>v0.138<a class=headerlink href=#v0138 title="Permanent link">¤</a></h2> <h4 id=fix_9>Fix<a class=headerlink href=#fix_9 title="Permanent link">¤</a></h4> <ul> <li>Fix bug: Allow components with <code>Url.public = True</code> to be defined before <code>django.setup()</code></li> </ul> <h2 id=v0137>v0.137<a class=headerlink href=#v0137 title="Permanent link">¤</a></h2> <h4 id=feat_3>Feat<a class=headerlink href=#feat_3 title="Permanent link">¤</a></h4> <ul> <li> <p>Each Component class now has a <code>class_id</code> attribute, which is unique to the component subclass.</p> <p>NOTE: This is different from <code>Component.id</code>, which is unique to each rendered instance.</p> <p>To look up a component class by its <code>class_id</code>, use <code>get_component_by_class_id()</code>.</p> </li> <li> <p>It's now easier to create URLs for component views.</p> <p>Before, you had to call <code>Component.as_view()</code> and pass that to <code>urlpatterns</code>.</p> <p>Now this can be done for you if you set <code>Component.Url.public</code> to <code>True</code>:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-87-1 name=__codelineno-87-1 href=#__codelineno-87-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-87-2 name=__codelineno-87-2 href=#__codelineno-87-2></a> <span class=k>class</span><span class=w> </span><span class=nc>Url</span><span class=p>:</span>
|
|
<a id=__codelineno-87-3 name=__codelineno-87-3 href=#__codelineno-87-3></a> <span class=n>public</span> <span class=o>=</span> <span class=kc>True</span>
|
|
<a id=__codelineno-87-4 name=__codelineno-87-4 href=#__codelineno-87-4></a> <span class=o>...</span>
|
|
</code></pre></div> <p>Then, to get the URL for the component, use <code>get_component_url()</code>:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-88-1 name=__codelineno-88-1 href=#__codelineno-88-1></a><span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>get_component_url</span>
|
|
<a id=__codelineno-88-2 name=__codelineno-88-2 href=#__codelineno-88-2></a>
|
|
<a id=__codelineno-88-3 name=__codelineno-88-3 href=#__codelineno-88-3></a><span class=n>url</span> <span class=o>=</span> <span class=n>get_component_url</span><span class=p>(</span><span class=n>MyComponent</span><span class=p>)</span>
|
|
</code></pre></div> <p>This way you don't have to mix your app URLs with component URLs.</p> <p>Read more on <a href=https://django-components.github.io/django-components/0.137/concepts/fundamentals/component_views_urls/ >Component views and URLs</a>.</p> </li> <li> <p>Per-component caching - Set <code>Component.Cache.enabled</code> to <code>True</code> to enable caching for a component.</p> <p>Component caching allows you to store the rendered output of a component. Next time the component is rendered with the same input, the cached output is returned instead of re-rendering the component.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-89-1 name=__codelineno-89-1 href=#__codelineno-89-1></a><span class=k>class</span><span class=w> </span><span class=nc>TestComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-89-2 name=__codelineno-89-2 href=#__codelineno-89-2></a> <span class=n>template</span> <span class=o>=</span> <span class=s2>"Hello"</span>
|
|
<a id=__codelineno-89-3 name=__codelineno-89-3 href=#__codelineno-89-3></a>
|
|
<a id=__codelineno-89-4 name=__codelineno-89-4 href=#__codelineno-89-4></a> <span class=k>class</span><span class=w> </span><span class=nc>Cache</span><span class=p>:</span>
|
|
<a id=__codelineno-89-5 name=__codelineno-89-5 href=#__codelineno-89-5></a> <span class=n>enabled</span> <span class=o>=</span> <span class=kc>True</span>
|
|
<a id=__codelineno-89-6 name=__codelineno-89-6 href=#__codelineno-89-6></a> <span class=n>ttl</span> <span class=o>=</span> <span class=mf>0.1</span> <span class=c1># .1 seconds TTL</span>
|
|
<a id=__codelineno-89-7 name=__codelineno-89-7 href=#__codelineno-89-7></a> <span class=n>cache_name</span> <span class=o>=</span> <span class=s2>"custom_cache"</span>
|
|
<a id=__codelineno-89-8 name=__codelineno-89-8 href=#__codelineno-89-8></a>
|
|
<a id=__codelineno-89-9 name=__codelineno-89-9 href=#__codelineno-89-9></a> <span class=c1># Custom hash method for args and kwargs</span>
|
|
<a id=__codelineno-89-10 name=__codelineno-89-10 href=#__codelineno-89-10></a> <span class=c1># NOTE: The default implementation simply serializes the input into a string.</span>
|
|
<a id=__codelineno-89-11 name=__codelineno-89-11 href=#__codelineno-89-11></a> <span class=c1># As such, it might not be suitable for complex objects like Models.</span>
|
|
<a id=__codelineno-89-12 name=__codelineno-89-12 href=#__codelineno-89-12></a> <span class=k>def</span><span class=w> </span><span class=nf>hash</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=o>*</span><span class=n>args</span><span class=p>,</span> <span class=o>**</span><span class=n>kwargs</span><span class=p>):</span>
|
|
<a id=__codelineno-89-13 name=__codelineno-89-13 href=#__codelineno-89-13></a> <span class=k>return</span> <span class=sa>f</span><span class=s2>"</span><span class=si>{</span><span class=n>json</span><span class=o>.</span><span class=n>dumps</span><span class=p>(</span><span class=n>args</span><span class=p>)</span><span class=si>}</span><span class=s2>:</span><span class=si>{</span><span class=n>json</span><span class=o>.</span><span class=n>dumps</span><span class=p>(</span><span class=n>kwargs</span><span class=p>)</span><span class=si>}</span><span class=s2>"</span>
|
|
</code></pre></div> <p>Read more on <a href=https://django-components.github.io/django-components/0.137/concepts/advanced/component_caching/ >Component caching</a>.</p> </li> <li> <p><code>@djc_test</code> can now be called without first calling <code>django.setup()</code>, in which case it does it for you.</p> </li> <li> <p>Expose <code>ComponentInput</code> class, which is a typing for <code>Component.input</code>.</p> </li> </ul> <h4 id=deprecation_1>Deprecation<a class=headerlink href=#deprecation_1 title="Permanent link">¤</a></h4> <ul> <li> <p>Currently, view request handlers such as <code>get()</code> and <code>post()</code> methods can be defined directly on the <code>Component</code> class:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-90-1 name=__codelineno-90-1 href=#__codelineno-90-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-90-2 name=__codelineno-90-2 href=#__codelineno-90-2></a> <span class=k>def</span><span class=w> </span><span class=nf>get</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>request</span><span class=p>):</span>
|
|
<a id=__codelineno-90-3 name=__codelineno-90-3 href=#__codelineno-90-3></a> <span class=k>return</span> <span class=bp>self</span><span class=o>.</span><span class=n>render_to_response</span><span class=p>()</span>
|
|
</code></pre></div> <p>Or, nested within the <code>Component.View</code> class:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-91-1 name=__codelineno-91-1 href=#__codelineno-91-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-91-2 name=__codelineno-91-2 href=#__codelineno-91-2></a> <span class=k>class</span><span class=w> </span><span class=nc>View</span><span class=p>:</span>
|
|
<a id=__codelineno-91-3 name=__codelineno-91-3 href=#__codelineno-91-3></a> <span class=k>def</span><span class=w> </span><span class=nf>get</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>request</span><span class=p>):</span>
|
|
<a id=__codelineno-91-4 name=__codelineno-91-4 href=#__codelineno-91-4></a> <span class=k>return</span> <span class=bp>self</span><span class=o>.</span><span class=n>render_to_response</span><span class=p>()</span>
|
|
</code></pre></div> <p>In v1, these methods should be defined only on the <code>Component.View</code> class instead.</p> </li> </ul> <h4 id=refactor_3>Refactor<a class=headerlink href=#refactor_3 title="Permanent link">¤</a></h4> <ul> <li><code>Component.get_context_data()</code> can now omit a return statement or return <code>None</code>.</li> </ul> <h2 id=v0136>🚨📢 v0.136<a class=headerlink href=#v0136 title="Permanent link">¤</a></h2> <h4 id=breaking-changes_1>🚨📢 BREAKING CHANGES<a class=headerlink href=#breaking-changes_1 title="Permanent link">¤</a></h4> <ul> <li> <p>Component input validation was moved to a separate extension <a href=https://github.com/django-components/djc-ext-pydantic><code>djc-ext-pydantic</code></a>.</p> <p>If you relied on components raising errors when inputs were invalid, you need to install <code>djc-ext-pydantic</code> and add it to extensions:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-92-1 name=__codelineno-92-1 href=#__codelineno-92-1></a><span class=c1># settings.py</span>
|
|
<a id=__codelineno-92-2 name=__codelineno-92-2 href=#__codelineno-92-2></a><span class=n>COMPONENTS</span> <span class=o>=</span> <span class=p>{</span>
|
|
<a id=__codelineno-92-3 name=__codelineno-92-3 href=#__codelineno-92-3></a> <span class=s2>"extensions"</span><span class=p>:</span> <span class=p>[</span>
|
|
<a id=__codelineno-92-4 name=__codelineno-92-4 href=#__codelineno-92-4></a> <span class=s2>"djc_pydantic.PydanticExtension"</span><span class=p>,</span>
|
|
<a id=__codelineno-92-5 name=__codelineno-92-5 href=#__codelineno-92-5></a> <span class=p>],</span>
|
|
<a id=__codelineno-92-6 name=__codelineno-92-6 href=#__codelineno-92-6></a><span class=p>}</span>
|
|
</code></pre></div> </li> </ul> <h4 id=fix_10>Fix<a class=headerlink href=#fix_10 title="Permanent link">¤</a></h4> <ul> <li>Make it possible to resolve URLs added by extensions by their names</li> </ul> <h2 id=v0135>v0.135<a class=headerlink href=#v0135 title="Permanent link">¤</a></h2> <h4 id=feat_4>Feat<a class=headerlink href=#feat_4 title="Permanent link">¤</a></h4> <ul> <li>Add defaults for the component inputs with the <code>Component.Defaults</code> nested class. Defaults are applied if the argument is not given, or if it set to <code>None</code>.</li> </ul> <p>For lists, dictionaries, or other objects, wrap the value in <code>Default()</code> class to mark it as a factory function:</p> <div class=codehilite><pre><span></span><code><span class=err>```</span><span class=n>python</span>
|
|
<span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>Default</span>
|
|
|
|
<span class=k>class</span><span class=w> </span><span class=nc>Table</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<span class=k>class</span><span class=w> </span><span class=nc>Defaults</span><span class=p>:</span>
|
|
<span class=n>position</span> <span class=o>=</span> <span class=s2>"left"</span>
|
|
<span class=n>width</span> <span class=o>=</span> <span class=s2>"200px"</span>
|
|
<span class=n>options</span> <span class=o>=</span> <span class=n>Default</span><span class=p>(</span><span class=k>lambda</span><span class=p>:</span> <span class=p>[</span><span class=s2>"left"</span><span class=p>,</span> <span class=s2>"right"</span><span class=p>,</span> <span class=s2>"center"</span><span class=p>])</span>
|
|
|
|
<span class=k>def</span><span class=w> </span><span class=nf>get_context_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=n>position</span><span class=p>,</span> <span class=n>width</span><span class=p>,</span> <span class=n>options</span><span class=p>):</span>
|
|
<span class=k>return</span> <span class=p>{</span>
|
|
<span class=s2>"position"</span><span class=p>:</span> <span class=n>position</span><span class=p>,</span>
|
|
<span class=s2>"width"</span><span class=p>:</span> <span class=n>width</span><span class=p>,</span>
|
|
<span class=s2>"options"</span><span class=p>:</span> <span class=n>options</span><span class=p>,</span>
|
|
<span class=p>}</span>
|
|
|
|
<span class=c1># `position` is used as given, `"right"`</span>
|
|
<span class=c1># `width` uses default because it's `None`</span>
|
|
<span class=c1># `options` uses default because it's missing</span>
|
|
<span class=n>Table</span><span class=o>.</span><span class=n>render</span><span class=p>(</span>
|
|
<span class=n>kwargs</span><span class=o>=</span><span class=p>{</span>
|
|
<span class=s2>"position"</span><span class=p>:</span> <span class=s2>"right"</span><span class=p>,</span>
|
|
<span class=s2>"width"</span><span class=p>:</span> <span class=kc>None</span><span class=p>,</span>
|
|
<span class=p>}</span>
|
|
<span class=p>)</span>
|
|
<span class=err>```</span>
|
|
</code></pre></div> <ul> <li> <p><code>{% html_attrs %}</code> now offers a Vue-like granular control over <code>class</code> and <code>style</code> HTML attributes, where each class name or style property can be managed separately.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-94-1 name=__codelineno-94-1 href=#__codelineno-94-1></a><span class=cp>{%</span> <span class=k>html_attrs</span>
|
|
<a id=__codelineno-94-2 name=__codelineno-94-2 href=#__codelineno-94-2></a> <span class=nv>class</span><span class=o>=</span><span class=s2>"foo bar"</span>
|
|
<a id=__codelineno-94-3 name=__codelineno-94-3 href=#__codelineno-94-3></a> <span class=nv>class</span><span class=o>={</span><span class=s2>"baz"</span><span class=o>:</span> <span class=kp>True</span><span class=o>,</span> <span class=s2>"foo"</span><span class=o>:</span> <span class=kp>False</span><span class=o>}</span>
|
|
<a id=__codelineno-94-4 name=__codelineno-94-4 href=#__codelineno-94-4></a> <span class=nv>class</span><span class=o>=</span><span class=s2>"extra"</span>
|
|
<a id=__codelineno-94-5 name=__codelineno-94-5 href=#__codelineno-94-5></a><span class=cp>%}</span>
|
|
</code></pre></div> <div class=highlight><pre><span></span><code><a id=__codelineno-95-1 name=__codelineno-95-1 href=#__codelineno-95-1></a><span class=cp>{%</span> <span class=k>html_attrs</span>
|
|
<a id=__codelineno-95-2 name=__codelineno-95-2 href=#__codelineno-95-2></a> <span class=nv>style</span><span class=o>=</span><span class=s2>"text-align: center; background-color: blue;"</span>
|
|
<a id=__codelineno-95-3 name=__codelineno-95-3 href=#__codelineno-95-3></a> <span class=nv>style</span><span class=o>={</span><span class=s2>"background-color"</span><span class=o>:</span> <span class=s2>"green"</span><span class=o>,</span> <span class=s2>"color"</span><span class=o>:</span> <span class=kp>None</span><span class=o>,</span> <span class=s2>"width"</span><span class=o>:</span> <span class=kp>False</span><span class=o>}</span>
|
|
<a id=__codelineno-95-4 name=__codelineno-95-4 href=#__codelineno-95-4></a> <span class=nv>style</span><span class=o>=</span><span class=s2>"position: absolute; height: 12px;"</span>
|
|
<a id=__codelineno-95-5 name=__codelineno-95-5 href=#__codelineno-95-5></a><span class=cp>%}</span>
|
|
</code></pre></div> <p>Read more on <a href=https://django-components.github.io/django-components/0.135/concepts/fundamentals/html_attributes/ >HTML attributes</a>.</p> </li> </ul> <h4 id=fix_11>Fix<a class=headerlink href=#fix_11 title="Permanent link">¤</a></h4> <ul> <li>Fix compat with Windows when reading component files (<a href=https://github.com/django-components/django-components/issues/1074>#1074</a>)</li> <li>Fix resolution of component media files edge case (<a href=https://github.com/django-components/django-components/issues/1073>#1073</a>)</li> </ul> <h2 id=v0134>v0.134<a class=headerlink href=#v0134 title="Permanent link">¤</a></h2> <h4 id=fix_12>Fix<a class=headerlink href=#fix_12 title="Permanent link">¤</a></h4> <ul> <li>HOTFIX: Fix the use of URLs in <code>Component.Media.js</code> and <code>Component.Media.css</code></li> </ul> <h2 id=v0133>v0.133<a class=headerlink href=#v0133 title="Permanent link">¤</a></h2> <p>⚠️ Attention ⚠️ - Please update to v0.134 to fix bugs introduced in v0.132.</p> <h4 id=fix_13>Fix<a class=headerlink href=#fix_13 title="Permanent link">¤</a></h4> <ul> <li>HOTFIX: Fix the use of URLs in <code>Component.Media.js</code> and <code>Component.Media.css</code></li> </ul> <h2 id=v0132>v0.132<a class=headerlink href=#v0132 title="Permanent link">¤</a></h2> <p>⚠️ Attention ⚠️ - Please update to v0.134 to fix bugs introduced in v0.132.</p> <h4 id=feat_5>Feat<a class=headerlink href=#feat_5 title="Permanent link">¤</a></h4> <ul> <li> <p>Allow to use glob patterns as paths for additional JS / CSS in <code>Component.Media.js</code> and <code>Component.Media.css</code></p> <div class=highlight><pre><span></span><code><a id=__codelineno-96-1 name=__codelineno-96-1 href=#__codelineno-96-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyComponent</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-96-2 name=__codelineno-96-2 href=#__codelineno-96-2></a> <span class=k>class</span><span class=w> </span><span class=nc>Media</span><span class=p>:</span>
|
|
<a id=__codelineno-96-3 name=__codelineno-96-3 href=#__codelineno-96-3></a> <span class=n>js</span> <span class=o>=</span> <span class=p>[</span><span class=s2>"*.js"</span><span class=p>]</span>
|
|
<a id=__codelineno-96-4 name=__codelineno-96-4 href=#__codelineno-96-4></a> <span class=n>css</span> <span class=o>=</span> <span class=p>[</span><span class=s2>"*.css"</span><span class=p>]</span>
|
|
</code></pre></div> </li> </ul> <h4 id=fix_14>Fix<a class=headerlink href=#fix_14 title="Permanent link">¤</a></h4> <ul> <li>Fix installation for Python 3.13 on Windows.</li> </ul> <h2 id=v0131>v0.131<a class=headerlink href=#v0131 title="Permanent link">¤</a></h2> <h4 id=feat_6>Feat<a class=headerlink href=#feat_6 title="Permanent link">¤</a></h4> <ul> <li> <p>Support for extensions (plugins) for django-components!</p> <ul> <li>Hook into lifecycle events of django-components</li> <li>Pre-/post-process component inputs, outputs, and templates</li> <li>Add extra methods or attributes to Components</li> <li>Add custom extension-specific CLI commands</li> <li>Add custom extension-specific URL routes</li> </ul> <p>Read more on <a href=https://django-components.github.io/django-components/0.131/concepts/advanced/extensions/ >Extensions</a>.</p> </li> <li> <p>New CLI commands:</p> <ul> <li><code>components list</code> - List all components</li> <li><code>components create <name></code> - Create a new component (supersedes <code>startcomponent</code>)</li> <li><code>components upgrade</code> - Upgrade a component (supersedes <code>upgradecomponent</code>)</li> <li><code>components ext list</code> - List all extensions</li> <li><code>components ext run <extension> <command></code> - Run a command added by an extension</li> </ul> </li> <li> <p><code>@djc_test</code> decorator for writing tests that involve Components.</p> <ul> <li>The decorator manages global state, ensuring that tests don't leak.</li> <li>If using <code>pytest</code>, the decorator allows you to parametrize Django or Components settings.</li> <li>The decorator also serves as a stand-in for Django's <code>@override_settings</code>.</li> </ul> <p>See the API reference for <a href=https://django-components.github.io/django-components/0.131/reference/testing_api/#django_components.testing.djc_test><code>@djc_test</code></a> for more details.</p> </li> <li> <p><code>ComponentRegistry</code> now has a <code>has()</code> method to check if a component is registered without raising an error.</p> </li> <li> <p>Get all created <code>Component</code> classes with <code>all_components()</code>.</p> </li> <li> <p>Get all created <code>ComponentRegistry</code> instances with <code>all_registries()</code>.</p> </li> </ul> <h4 id=refactor_4>Refactor<a class=headerlink href=#refactor_4 title="Permanent link">¤</a></h4> <ul> <li> <p>The <code>startcomponent</code> and <code>upgradecomponent</code> commands are deprecated, and will be removed in v1.</p> <p>Instead, use <code>components create <name></code> and <code>components upgrade</code>.</p> </li> </ul> <h4 id=internal>Internal<a class=headerlink href=#internal title="Permanent link">¤</a></h4> <ul> <li>Settings are now loaded only once, and thus are considered immutable once loaded. Previously, django-components would load settings from <code>settings.COMPONENTS</code> on each access. The new behavior aligns with Django's settings.</li> </ul> <h2 id=v0130>v0.130<a class=headerlink href=#v0130 title="Permanent link">¤</a></h2> <h4 id=feat_7>Feat<a class=headerlink href=#feat_7 title="Permanent link">¤</a></h4> <ul> <li> <p>Access the HttpRequest object under <code>Component.request</code>.</p> <p>To pass the request object to a component, either: - Render a template or component with <code>RequestContext</code>, - Or set the <code>request</code> kwarg to <code>Component.render()</code> or <code>Component.render_to_response()</code>.</p> <p>Read more on <a href=https://django-components.github.io/django-components/0.130/concepts/fundamentals/http_request/ >HttpRequest</a>.</p> </li> <li> <p>Access the context processors data under <code>Component.context_processors_data</code>.</p> <p>Context processors data is available only when the component has access to the <code>request</code> object, either by: - Passing the request to <code>Component.render()</code> or <code>Component.render_to_response()</code>, - Or by rendering a template or component with <code>RequestContext</code>, - Or being nested in another component that has access to the request object.</p> <p>The data from context processors is automatically available within the component's template.</p> <p>Read more on <a href=https://django-components.github.io/django-components/0.130/concepts/fundamentals/http_request/ >HttpRequest</a>.</p> </li> </ul> <h2 id=v0129>v0.129<a class=headerlink href=#v0129 title="Permanent link">¤</a></h2> <h4 id=fix_15>Fix<a class=headerlink href=#fix_15 title="Permanent link">¤</a></h4> <ul> <li>Fix thread unsafe media resolve validation by moving it to ComponentMedia <code>__post_init</code> (<a href=https://github.com/django-components/django-components/pull/977>#977</a></li> <li>Fix bug: Relative path in extends and include does not work when using template_file (<a href=https://github.com/django-components/django-components/pull/976>#976</a></li> <li>Fix error when template cache setting (<code>template_cache_size</code>) is set to 0 (<a href=https://github.com/django-components/django-components/pull/974>#974</a></li> </ul> <h2 id=v0128>v0.128<a class=headerlink href=#v0128 title="Permanent link">¤</a></h2> <h4 id=feat_8>Feat<a class=headerlink href=#feat_8 title="Permanent link">¤</a></h4> <ul> <li> <p>Configurable cache - Set <a href=https://django-components.github.io/django-components/0.128/reference/settings/#django_components.app_settings.ComponentsSettings.cache><code>COMPONENTS.cache</code></a> to change where and how django-components caches JS and CSS files. (<a href=https://github.com/django-components/django-components/pull/946>#946</a>)</p> <p>Read more on <a href=https://django-components.github.io/django-components/0.128/guides/setup/caching>Caching</a>.</p> </li> <li> <p>Highlight coponents and slots in the UI - We've added two boolean settings <a href=https://django-components.github.io/django-components/0.128/reference/settings/#django_components.app_settings.ComponentsSettings.debug_highlight_components><code>COMPONENTS.debug_highlight_components</code></a> and <a href=https://django-components.github.io/django-components/0.128/reference/settings/#django_components.app_settings.ComponentsSettings.debug_highlight_slots><code>COMPONENTS.debug_highlight_slots</code></a>, which can be independently set to <code>True</code>. First will wrap components in a blue border, the second will wrap slots in a red border. (<a href=https://github.com/django-components/django-components/pull/942>#942</a>)</p> <p>Read more on <a href=https://django-components.github.io/django-components/0.128/guides/other/troubleshooting/#component-and-slot-highlighting>Troubleshooting</a>.</p> </li> </ul> <h4 id=refactor_5>Refactor<a class=headerlink href=#refactor_5 title="Permanent link">¤</a></h4> <ul> <li>Removed use of eval for node validation (<a href=https://github.com/django-components/django-components/pull/944>#944</a>)</li> </ul> <h4 id=perf>Perf<a class=headerlink href=#perf title="Permanent link">¤</a></h4> <ul> <li> <p>Components can now be infinitely nested. (<a href=https://github.com/django-components/django-components/pull/936>#936</a>)</p> </li> <li> <p>Component input validation is now 6-7x faster on CPython and PyPy. This previously made up 10-30% of the total render time. (<a href=https://github.com/django-components/django-components/pull/945>#945</a>)</p> </li> </ul> <h2 id=v0127>v0.127<a class=headerlink href=#v0127 title="Permanent link">¤</a></h2> <h4 id=fix_16>Fix<a class=headerlink href=#fix_16 title="Permanent link">¤</a></h4> <ul> <li>Fix component rendering when using <code>{% cache %}</code> with remote cache and multiple web servers (<a href=https://github.com/django-components/django-components/issues/930>#930</a>)</li> </ul> <h2 id=v0126>v0.126<a class=headerlink href=#v0126 title="Permanent link">¤</a></h2> <h4 id=refactor_6>Refactor<a class=headerlink href=#refactor_6 title="Permanent link">¤</a></h4> <ul> <li>Replaced <a href=https://www.crummy.com/software/BeautifulSoup/bs4/doc/ >BeautifulSoup4</a> with a custom HTML parser.</li> <li>The heuristic for inserting JS and CSS dependenies into the default place has changed.<ul> <li>JS is still inserted at the end of the <code><body></code>, and CSS at the end of <code><head></code>.</li> <li>However, we find end of <code><body></code> by searching for <strong>last</strong> occurrence of <code></body></code></li> <li>And for the end of <code><head></code> we search for the <strong>first</strong> occurrence of <code></head></code></li> </ul> </li> </ul> <h2 id=v0125>v0.125<a class=headerlink href=#v0125 title="Permanent link">¤</a></h2> <p>⚠️ Attention ⚠️ - We migrated from <code>EmilStenstrom/django-components</code> to <code>django-components/django-components</code>.</p> <p><strong>Repo name and documentation URL changed. Package name remains the same.</strong></p> <p>If you see any broken links or other issues, please report them in <a href=https://github.com/django-components/django-components/issues/922>#922</a>.</p> <h4 id=feat_9>Feat<a class=headerlink href=#feat_9 title="Permanent link">¤</a></h4> <ul> <li><code>@template_tag</code> and <code>BaseNode</code> - A decorator and a class that allow you to define custom template tags that will behave similarly to django-components' own template tags.</li> </ul> <p>Read more on <a href=https://django-components.github.io/django-components/0.125/concepts/advanced/template_tags/ >Template tags</a>.</p> <p>Template tags defined with <code>@template_tag</code> and <code>BaseNode</code> will have the following features:</p> <ul> <li> <p>Accepting args, kwargs, and flags.</p> </li> <li> <p>Allowing literal lists and dicts as inputs as:</p> <p><code>key=[1, 2, 3]</code> or <code>key={"a": 1, "b": 2}</code> - Using template tags tag inputs as:</p> <p><code>{% my_tag key="{% lorem 3 w %}" / %}</code> - Supporting the flat dictionary definition:</p> <p><code>attr:key=value</code> - Spreading args and kwargs with <code>...</code>:</p> <p><code>{% my_tag ...args ...kwargs / %}</code> - Being able to call the template tag as:</p> <p><code>{% my_tag %} ... {% endmy_tag %}</code> or <code>{% my_tag / %}</code></p> </li> </ul> <h4 id=refactor_7>Refactor<a class=headerlink href=#refactor_7 title="Permanent link">¤</a></h4> <ul> <li> <p>Refactored template tag input validation. When you now call template tags like <code>{% slot %}</code>, <code>{% fill %}</code>, <code>{% html_attrs %}</code>, and others, their inputs are now validated the same way as Python function inputs are.</p> <p>So, for example</p> <div class=highlight><pre><span></span><code><a id=__codelineno-97-1 name=__codelineno-97-1 href=#__codelineno-97-1></a><span class=cp>{%</span> <span class=k>slot</span> <span class=s2>"my_slot"</span> <span class=nv>name</span><span class=o>=</span><span class=s2>"content"</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>will raise an error, because the positional argument <code>name</code> is given twice.</p> <p>NOTE: Special kwargs whose keys are not valid Python variable names are not affected by this change. So when you define:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-98-1 name=__codelineno-98-1 href=#__codelineno-98-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=nv>data-id</span><span class=o>=</span><span class=m>123</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>The <code>data-id</code> will still be accepted as a valid kwarg, assuming that your <code>get_context_data()</code> accepts <code>**kwargs</code>:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-99-1 name=__codelineno-99-1 href=#__codelineno-99-1></a><span class=k>def</span><span class=w> </span><span class=nf>get_context_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=o>**</span><span class=n>kwargs</span><span class=p>):</span>
|
|
<a id=__codelineno-99-2 name=__codelineno-99-2 href=#__codelineno-99-2></a> <span class=k>return</span> <span class=p>{</span>
|
|
<a id=__codelineno-99-3 name=__codelineno-99-3 href=#__codelineno-99-3></a> <span class=s2>"data_id"</span><span class=p>:</span> <span class=n>kwargs</span><span class=p>[</span><span class=s2>"data-id"</span><span class=p>],</span>
|
|
<a id=__codelineno-99-4 name=__codelineno-99-4 href=#__codelineno-99-4></a> <span class=p>}</span>
|
|
</code></pre></div> </li> </ul> <h2 id=v0124>v0.124<a class=headerlink href=#v0124 title="Permanent link">¤</a></h2> <h4 id=feat_10>Feat<a class=headerlink href=#feat_10 title="Permanent link">¤</a></h4> <ul> <li> <p>Instead of inlining the JS and CSS under <code>Component.js</code> and <code>Component.css</code>, you can move them to their own files, and link the JS/CSS files with <code>Component.js_file</code> and <code>Component.css_file</code>.</p> <p>Even when you specify the JS/CSS with <code>Component.js_file</code> or <code>Component.css_file</code>, then you can still access the content under <code>Component.js</code> or <code>Component.css</code> - behind the scenes, the content of the JS/CSS files will be set to <code>Component.js</code> / <code>Component.css</code> upon first access.</p> <p>The same applies to <code>Component.template_file</code>, which will populate <code>Component.template</code> upon first access.</p> <p>With this change, the role of <code>Component.js/css</code> and the JS/CSS in <code>Component.Media</code> has changed:</p> <ul> <li>The JS/CSS defined in <code>Component.js/css</code> or <code>Component.js/css_file</code> is the "main" JS/CSS</li> <li>The JS/CSS defined in <code>Component.Media.js/css</code> are secondary or additional</li> </ul> <p>See the updated <a href=https://django-components.github.io/django-components/0.124/getting_started/adding_js_and_css/ >"Getting Started" tutorial</a></p> </li> </ul> <h4 id=refactor_8>Refactor<a class=headerlink href=#refactor_8 title="Permanent link">¤</a></h4> <ul> <li> <p>The canonical way to define a template file was changed from <code>template_name</code> to <code>template_file</code>, to align with the rest of the API.</p> <p><code>template_name</code> remains for backwards compatibility. When you get / set <code>template_name</code>, internally this is proxied to <code>template_file</code>.</p> </li> <li> <p>The undocumented <code>Component.component_id</code> was removed. Instead, use <code>Component.id</code>. Changes:</p> <ul> <li>While <code>component_id</code> was unique every time you instantiated <code>Component</code>, the new <code>id</code> is unique every time you render the component (e.g. with <code>Component.render()</code>)</li> <li>The new <code>id</code> is available only during render, so e.g. from within <code>get_context_data()</code></li> </ul> </li> <li> <p>Component's HTML / CSS / JS are now resolved and loaded lazily. That is, if you specify <code>template_name</code>/<code>template_file</code>, <code>js_file</code>, <code>css_file</code>, or <code>Media.js/css</code>, the file paths will be resolved only once you:</p> <ol> <li>Try to access component's HTML / CSS / JS, or</li> <li>Render the component.</li> </ol> <p>Read more on <a href=https://django-components.github.io/django-components/0.124/concepts/fundamentals/defining_js_css_html_files/#customize-how-paths-are-rendered-into-html-tags>Accessing component's HTML / JS / CSS</a>.</p> </li> <li> <p>Component inheritance:</p> <ul> <li>When you subclass a component, the JS and CSS defined on parent's <code>Media</code> class is now inherited by the child component.</li> <li>You can disable or customize Media inheritance by setting <code>extend</code> attribute on the <code>Component.Media</code> nested class. This work similarly to Django's <a href=https://docs.djangoproject.com/en/5.2/topics/forms/media/#extend><code>Media.extend</code></a>.</li> <li>When child component defines either <code>template</code> or <code>template_file</code>, both of parent's <code>template</code> and <code>template_file</code> are ignored. The same applies to <code>js_file</code> and <code>css_file</code>.</li> </ul> </li> <li> <p>Autodiscovery now ignores files and directories that start with an underscore (<code>_</code>), except <code>__init__.py</code></p> </li> <li> <p>The <a href=https://docs.djangoproject.com/en/5.2/topics/signals/ >Signals</a> emitted by or during the use of django-components are now documented, together the <code>template_rendered</code> signal.</p> </li> </ul> <h2 id=v0123>v0.123<a class=headerlink href=#v0123 title="Permanent link">¤</a></h2> <h4 id=fix_17>Fix<a class=headerlink href=#fix_17 title="Permanent link">¤</a></h4> <ul> <li>Fix edge cases around rendering components whose templates used the <code>{% extends %}</code> template tag (<a href=https://github.com/django-components/django-components/pull/859>#859</a>)</li> </ul> <h2 id=v0122>v0.122<a class=headerlink href=#v0122 title="Permanent link">¤</a></h2> <h4 id=feat_11>Feat<a class=headerlink href=#feat_11 title="Permanent link">¤</a></h4> <ul> <li>Add support for HTML fragments. HTML fragments can be rendered by passing <code>type="fragment"</code> to <code>Component.render()</code> or <code>Component.render_to_response()</code>. Read more on how to <a href=https://django-components.github.io/django-components/latest/concepts/advanced/html_fragments>use HTML fragments with HTMX, AlpineJS, or vanillaJS</a>.</li> </ul> <h2 id=v0121>v0.121<a class=headerlink href=#v0121 title="Permanent link">¤</a></h2> <h4 id=fix_18>Fix<a class=headerlink href=#fix_18 title="Permanent link">¤</a></h4> <ul> <li>Fix the use of Django template filters (<code>|lower:"etc"</code>) with component inputs <a href=https://github.com/django-components/django-components/pull/855>#855</a>.</li> </ul> <h2 id=v0120>v0.120<a class=headerlink href=#v0120 title="Permanent link">¤</a></h2> <p>⚠️ Attention ⚠️ - Please update to v0.121 to fix bugs introduced in v0.119.</p> <h4 id=fix_19>Fix<a class=headerlink href=#fix_19 title="Permanent link">¤</a></h4> <ul> <li>Fix the use of translation strings <code>_("bla")</code> as inputs to components <a href=https://github.com/django-components/django-components/pull/849>#849</a>.</li> </ul> <h2 id=v0119>v0.119<a class=headerlink href=#v0119 title="Permanent link">¤</a></h2> <p>⚠️ Attention ⚠️ - This release introduced bugs <a href=https://github.com/django-components/django-components/pull/849>#849</a>, <a href=https://github.com/django-components/django-components/pull/855>#855</a>. Please update to v0.121.</p> <h4 id=fix_20>Fix<a class=headerlink href=#fix_20 title="Permanent link">¤</a></h4> <ul> <li>Fix compatibility with custom subclasses of Django's <code>Template</code> that need to access <code>origin</code> or other initialization arguments. (<a href=https://github.com/django-components/django-components/pull/828>https://github.com/django-components/django-components/pull/828</a>)</li> </ul> <h4 id=refactor_9>Refactor<a class=headerlink href=#refactor_9 title="Permanent link">¤</a></h4> <ul> <li>Compatibility with <code>django-debug-toolbar-template-profiler</code>:</li> <li> <p>Monkeypatching of Django's <code>Template</code> now happens at <code>AppConfig.ready()</code> (<a href=https://github.com/django-components/django-components/pull/825>https://github.com/django-components/django-components/pull/825</a>)</p> </li> <li> <p>Internal parsing of template tags tag was updated. No API change. (<a href=https://github.com/django-components/django-components/pull/827>https://github.com/django-components/django-components/pull/827</a>)</p> </li> </ul> <h2 id=v0118>v0.118<a class=headerlink href=#v0118 title="Permanent link">¤</a></h2> <h4 id=feat_12>Feat<a class=headerlink href=#feat_12 title="Permanent link">¤</a></h4> <ul> <li>Add support for <code>context_processors</code> and <code>RenderContext</code> inside component templates</li> </ul> <p><code>Component.render()</code> and <code>Component.render_to_response()</code> now accept an extra kwarg <code>request</code>.</p> <div class=codehilite><pre><span></span><code>```py
|
|
def my_view(request)
|
|
return MyTable.render_to_response(
|
|
request=request
|
|
)
|
|
```
|
|
</code></pre></div> <ul> <li> <p>When you pass in <code>request</code>, the component will use <code>RenderContext</code> instead of <code>Context</code>. Thus the context processors will be applied to the context.</p> </li> <li> <p>NOTE: When you pass in both <code>request</code> and <code>context</code> to <code>Component.render()</code>, and <code>context</code> is already an instance of <code>Context</code>, the <code>request</code> kwarg will be ignored.</p> </li> </ul> <h2 id=v0117>v0.117<a class=headerlink href=#v0117 title="Permanent link">¤</a></h2> <h4 id=fix_21>Fix<a class=headerlink href=#fix_21 title="Permanent link">¤</a></h4> <ul> <li>The HTML parser no longer erronously inserts <code><html><head><body></code> on some occasions, and no longer tries to close unclosed HTML tags.</li> </ul> <h4 id=refactor_10>Refactor<a class=headerlink href=#refactor_10 title="Permanent link">¤</a></h4> <ul> <li>Replaced <a href=https://github.com/rushter/selectolax>Selectolax</a> with <a href=https://www.crummy.com/software/BeautifulSoup/bs4/doc/ >BeautifulSoup4</a> as project dependencies.</li> </ul> <h2 id=v0116>v0.116<a class=headerlink href=#v0116 title="Permanent link">¤</a></h2> <p>⚠️ Attention ⚠️ - Please update to v0.117 to fix known bugs. See <a href=https://github.com/django-components/django-components/issues/791>#791</a> and <a href=https://github.com/django-components/django-components/issues/789>#789</a> and <a href=https://github.com/django-components/django-components/issues/818>#818</a>.</p> <h4 id=fix_22>Fix<a class=headerlink href=#fix_22 title="Permanent link">¤</a></h4> <ul> <li>Fix the order of execution of JS scripts:</li> <li>Scripts in <code>Component.Media.js</code> are executed in the order they are defined</li> <li> <p>Scripts in <code>Component.js</code> are executed AFTER <code>Media.js</code> scripts</p> </li> <li> <p>Fix compatibility with AlpineJS</p> </li> <li>Scripts in <code>Component.Media.js</code> are now again inserted as <code><script></code> tags</li> <li>By default, <code>Component.Media.js</code> are inserted as synchronous <code><script></code> tags, so the AlpineJS components registered in the <code>Media.js</code> scripts will now again run BEFORE the core AlpineJS script.</li> </ul> <p>AlpineJS can be configured like so:</p> <p>Option 1 - AlpineJS loaded in <code><head></code> with <code>defer</code> attribute: <div class=highlight><pre><span></span><code><a id=__codelineno-101-1 name=__codelineno-101-1 href=#__codelineno-101-1></a><span class=p><</span><span class=nt>html</span><span class=p>></span>
|
|
<a id=__codelineno-101-2 name=__codelineno-101-2 href=#__codelineno-101-2></a> <span class=p><</span><span class=nt>head</span><span class=p>></span>
|
|
<a id=__codelineno-101-3 name=__codelineno-101-3 href=#__codelineno-101-3></a> {% component_css_dependencies %}
|
|
<a id=__codelineno-101-4 name=__codelineno-101-4 href=#__codelineno-101-4></a> <span class=p><</span><span class=nt>script</span> <span class=na>defer</span> <span class=na>src</span><span class=o>=</span><span class=s>"https://unpkg.com/alpinejs"</span><span class=p>></</span><span class=nt>script</span><span class=p>></span>
|
|
<a id=__codelineno-101-5 name=__codelineno-101-5 href=#__codelineno-101-5></a> <span class=p></</span><span class=nt>head</span><span class=p>></span>
|
|
<a id=__codelineno-101-6 name=__codelineno-101-6 href=#__codelineno-101-6></a> <span class=p><</span><span class=nt>body</span><span class=p>></span>
|
|
<a id=__codelineno-101-7 name=__codelineno-101-7 href=#__codelineno-101-7></a> {% component 'my_alpine_component' / %}
|
|
<a id=__codelineno-101-8 name=__codelineno-101-8 href=#__codelineno-101-8></a> {% component_js_dependencies %}
|
|
<a id=__codelineno-101-9 name=__codelineno-101-9 href=#__codelineno-101-9></a> <span class=p></</span><span class=nt>body</span><span class=p>></span>
|
|
<a id=__codelineno-101-10 name=__codelineno-101-10 href=#__codelineno-101-10></a><span class=p></</span><span class=nt>html</span><span class=p>></span>
|
|
</code></pre></div></p> <p>Option 2 - AlpineJS loaded in <code><body></code> AFTER <code>{% component_js_depenencies %}</code>: <div class=highlight><pre><span></span><code><a id=__codelineno-102-1 name=__codelineno-102-1 href=#__codelineno-102-1></a><span class=p><</span><span class=nt>html</span><span class=p>></span>
|
|
<a id=__codelineno-102-2 name=__codelineno-102-2 href=#__codelineno-102-2></a> <span class=p><</span><span class=nt>head</span><span class=p>></span>
|
|
<a id=__codelineno-102-3 name=__codelineno-102-3 href=#__codelineno-102-3></a> {% component_css_dependencies %}
|
|
<a id=__codelineno-102-4 name=__codelineno-102-4 href=#__codelineno-102-4></a> <span class=p></</span><span class=nt>head</span><span class=p>></span>
|
|
<a id=__codelineno-102-5 name=__codelineno-102-5 href=#__codelineno-102-5></a> <span class=p><</span><span class=nt>body</span><span class=p>></span>
|
|
<a id=__codelineno-102-6 name=__codelineno-102-6 href=#__codelineno-102-6></a> {% component 'my_alpine_component' / %}
|
|
<a id=__codelineno-102-7 name=__codelineno-102-7 href=#__codelineno-102-7></a> {% component_js_dependencies %}
|
|
<a id=__codelineno-102-8 name=__codelineno-102-8 href=#__codelineno-102-8></a>
|
|
<a id=__codelineno-102-9 name=__codelineno-102-9 href=#__codelineno-102-9></a> <span class=p><</span><span class=nt>script</span> <span class=na>src</span><span class=o>=</span><span class=s>"https://unpkg.com/alpinejs"</span><span class=p>></</span><span class=nt>script</span><span class=p>></span>
|
|
<a id=__codelineno-102-10 name=__codelineno-102-10 href=#__codelineno-102-10></a> <span class=p></</span><span class=nt>body</span><span class=p>></span>
|
|
<a id=__codelineno-102-11 name=__codelineno-102-11 href=#__codelineno-102-11></a><span class=p></</span><span class=nt>html</span><span class=p>></span>
|
|
</code></pre></div></p> <h2 id=v0115>v0.115<a class=headerlink href=#v0115 title="Permanent link">¤</a></h2> <p>⚠️ Attention ⚠️ - Please update to v0.117 to fix known bugs. See <a href=https://github.com/django-components/django-components/issues/791>#791</a> and <a href=https://github.com/django-components/django-components/issues/789>#789</a> and <a href=https://github.com/django-components/django-components/issues/818>#818</a>.</p> <h4 id=fix_23>Fix<a class=headerlink href=#fix_23 title="Permanent link">¤</a></h4> <ul> <li>Fix integration with ManifestStaticFilesStorage on Windows by resolving component filepaths (like <code>Component.template_name</code>) to POSIX paths.</li> </ul> <h2 id=v0114>v0.114<a class=headerlink href=#v0114 title="Permanent link">¤</a></h2> <p>⚠️ Attention ⚠️ - Please update to v0.117 to fix known bugs. See <a href=https://github.com/django-components/django-components/issues/791>#791</a> and <a href=https://github.com/django-components/django-components/issues/789>#789</a> and <a href=https://github.com/django-components/django-components/issues/818>#818</a>.</p> <h4 id=fix_24>Fix<a class=headerlink href=#fix_24 title="Permanent link">¤</a></h4> <ul> <li>Prevent rendering Slot tags during fill discovery stage to fix a case when a component inside a slot fill tried to access provided data too early.</li> </ul> <h2 id=v0113>v0.113<a class=headerlink href=#v0113 title="Permanent link">¤</a></h2> <p>⚠️ Attention ⚠️ - Please update to v0.117 to fix known bugs. See <a href=https://github.com/django-components/django-components/issues/791>#791</a> and <a href=https://github.com/django-components/django-components/issues/789>#789</a> and <a href=https://github.com/django-components/django-components/issues/818>#818</a>.</p> <h4 id=fix_25>Fix<a class=headerlink href=#fix_25 title="Permanent link">¤</a></h4> <ul> <li>Ensure consistent order of scripts in <code>Component.Media.js</code></li> </ul> <h2 id=v0112>v0.112<a class=headerlink href=#v0112 title="Permanent link">¤</a></h2> <p>⚠️ Attention ⚠️ - Please update to v0.117 to fix known bugs. See <a href=https://github.com/django-components/django-components/issues/791>#791</a> and <a href=https://github.com/django-components/django-components/issues/789>#789</a> and <a href=https://github.com/django-components/django-components/issues/818>#818</a>.</p> <h4 id=fix_26>Fix<a class=headerlink href=#fix_26 title="Permanent link">¤</a></h4> <ul> <li>Allow components to accept default fill even if no default slot was encountered during rendering</li> </ul> <h2 id=v0111>v0.111<a class=headerlink href=#v0111 title="Permanent link">¤</a></h2> <p>⚠️ Attention ⚠️ - Please update to v0.117 to fix known bugs. See <a href=https://github.com/django-components/django-components/issues/791>#791</a> and <a href=https://github.com/django-components/django-components/issues/789>#789</a> and <a href=https://github.com/django-components/django-components/issues/818>#818</a>.</p> <h4 id=fix_27>Fix<a class=headerlink href=#fix_27 title="Permanent link">¤</a></h4> <ul> <li>Prevent rendering Component tags during fill discovery stage to fix a case when a component inside the default slot tried to access provided data too early.</li> </ul> <h2 id=v0110>🚨📢 v0.110<a class=headerlink href=#v0110 title="Permanent link">¤</a></h2> <p>⚠️ Attention ⚠️ - Please update to v0.117 to fix known bugs. See <a href=https://github.com/django-components/django-components/issues/791>#791</a> and <a href=https://github.com/django-components/django-components/issues/789>#789</a> and <a href=https://github.com/django-components/django-components/issues/818>#818</a>.</p> <h3 id=general>General<a class=headerlink href=#general title="Permanent link">¤</a></h3> <h4 id=breaking-changes_2>🚨📢 BREAKING CHANGES<a class=headerlink href=#breaking-changes_2 title="Permanent link">¤</a></h4> <ul> <li> <p>Installation changes:</p> <ul> <li>If your components include JS or CSS, you now must use the middleware and add django-components' URLs to your <code>urlpatterns</code> (See "<a href=https://github.com/django-components/django-components#adding-support-for-js-and-css>Adding support for JS and CSS</a>")</li> </ul> </li> <li> <p>Component typing signature changed from</p> <div class=highlight><pre><span></span><code><a id=__codelineno-103-1 name=__codelineno-103-1 href=#__codelineno-103-1></a><span class=n>Component</span><span class=p>[</span><span class=n>Args</span><span class=p>,</span> <span class=n>Kwargs</span><span class=p>,</span> <span class=n>Data</span><span class=p>,</span> <span class=n>Slots</span><span class=p>]</span>
|
|
</code></pre></div> <p>to</p> <div class=highlight><pre><span></span><code><a id=__codelineno-104-1 name=__codelineno-104-1 href=#__codelineno-104-1></a><span class=n>Component</span><span class=p>[</span><span class=n>Args</span><span class=p>,</span> <span class=n>Kwargs</span><span class=p>,</span> <span class=n>Slots</span><span class=p>,</span> <span class=n>Data</span><span class=p>,</span> <span class=n>JsData</span><span class=p>,</span> <span class=n>CssData</span><span class=p>]</span>
|
|
</code></pre></div> </li> <li> <p>If you rendered a component A with <code>Component.render()</code> and then inserted that into another component B, now you must pass <code>render_dependencies=False</code> to component A:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-105-1 name=__codelineno-105-1 href=#__codelineno-105-1></a><span class=n>prerendered_a</span> <span class=o>=</span> <span class=n>CompA</span><span class=o>.</span><span class=n>render</span><span class=p>(</span>
|
|
<a id=__codelineno-105-2 name=__codelineno-105-2 href=#__codelineno-105-2></a> <span class=n>args</span><span class=o>=</span><span class=p>[</span><span class=o>...</span><span class=p>],</span>
|
|
<a id=__codelineno-105-3 name=__codelineno-105-3 href=#__codelineno-105-3></a> <span class=n>kwargs</span><span class=o>=</span><span class=p>{</span><span class=o>...</span><span class=p>},</span>
|
|
<a id=__codelineno-105-4 name=__codelineno-105-4 href=#__codelineno-105-4></a> <span class=n>render_dependencies</span><span class=o>=</span><span class=kc>False</span><span class=p>,</span>
|
|
<a id=__codelineno-105-5 name=__codelineno-105-5 href=#__codelineno-105-5></a><span class=p>)</span>
|
|
<a id=__codelineno-105-6 name=__codelineno-105-6 href=#__codelineno-105-6></a>
|
|
<a id=__codelineno-105-7 name=__codelineno-105-7 href=#__codelineno-105-7></a><span class=n>html</span> <span class=o>=</span> <span class=n>CompB</span><span class=o>.</span><span class=n>render</span><span class=p>(</span>
|
|
<a id=__codelineno-105-8 name=__codelineno-105-8 href=#__codelineno-105-8></a> <span class=n>kwargs</span><span class=o>=</span><span class=p>{</span>
|
|
<a id=__codelineno-105-9 name=__codelineno-105-9 href=#__codelineno-105-9></a> <span class=n>content</span><span class=o>=</span><span class=n>prerendered_a</span><span class=p>,</span>
|
|
<a id=__codelineno-105-10 name=__codelineno-105-10 href=#__codelineno-105-10></a> <span class=p>},</span>
|
|
<a id=__codelineno-105-11 name=__codelineno-105-11 href=#__codelineno-105-11></a><span class=p>)</span>
|
|
</code></pre></div> </li> </ul> <h4 id=feat_13>Feat<a class=headerlink href=#feat_13 title="Permanent link">¤</a></h4> <ul> <li>Intellisense and mypy validation for settings:</li> </ul> <p>Instead of defining the <code>COMPONENTS</code> settings as a plain dict, you can use <code>ComponentsSettings</code>:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-106-1 name=__codelineno-106-1 href=#__codelineno-106-1></a><span class=c1># settings.py</span>
|
|
<a id=__codelineno-106-2 name=__codelineno-106-2 href=#__codelineno-106-2></a><span class=kn>from</span><span class=w> </span><span class=nn>django_components</span><span class=w> </span><span class=kn>import</span> <span class=n>ComponentsSettings</span>
|
|
<a id=__codelineno-106-3 name=__codelineno-106-3 href=#__codelineno-106-3></a>
|
|
<a id=__codelineno-106-4 name=__codelineno-106-4 href=#__codelineno-106-4></a><span class=n>COMPONENTS</span> <span class=o>=</span> <span class=n>ComponentsSettings</span><span class=p>(</span>
|
|
<a id=__codelineno-106-5 name=__codelineno-106-5 href=#__codelineno-106-5></a> <span class=n>autodiscover</span><span class=o>=</span><span class=kc>True</span><span class=p>,</span>
|
|
<a id=__codelineno-106-6 name=__codelineno-106-6 href=#__codelineno-106-6></a> <span class=o>...</span>
|
|
<a id=__codelineno-106-7 name=__codelineno-106-7 href=#__codelineno-106-7></a><span class=p>)</span>
|
|
</code></pre></div> <ul> <li>Use <code>get_component_dirs()</code> and <code>get_component_files()</code> to get the same list of dirs / files that would be imported by <code>autodiscover()</code>, but without actually importing them.</li> </ul> <h4 id=refactor_11>Refactor<a class=headerlink href=#refactor_11 title="Permanent link">¤</a></h4> <ul> <li> <p>For advanced use cases, use can omit the middleware and instead manage component JS and CSS dependencies yourself with <a href=https://github.com/django-components/django-components#render_dependencies-and-deep-dive-into-rendering-js--css-without-the-middleware><code>render_dependencies</code></a></p> </li> <li> <p>The <a href=../api#django_components.ComponentRegistry><code>ComponentRegistry</code></a> settings <a href=../api#django_components.RegistrySettings><code>RegistrySettings</code></a> were lowercased to align with the global settings:</p> </li> <li><code>RegistrySettings.CONTEXT_BEHAVIOR</code> -> <code>RegistrySettings.context_behavior</code></li> <li><code>RegistrySettings.TAG_FORMATTER</code> -> <code>RegistrySettings.tag_formatter</code></li> </ul> <p>The old uppercase settings <code>CONTEXT_BEHAVIOR</code> and <code>TAG_FORMATTER</code> are deprecated and will be removed in v1.</p> <ul> <li> <p>The setting <code>reload_on_template_change</code> was renamed to <a href=../settings#django_components.app_settings.ComponentsSettings#reload_on_file_change><code>reload_on_file_change</code></a>. And now it properly triggers server reload when any file in the component dirs change. The old name <code>reload_on_template_change</code> is deprecated and will be removed in v1.</p> </li> <li> <p>The setting <code>forbidden_static_files</code> was renamed to <a href=../settings#django_components.app_settings.ComponentsSettings#static_files_forbidden><code>static_files_forbidden</code></a> to align with <a href=../settings#django_components.app_settings.ComponentsSettings#static_files_allowed><code>static_files_allowed</code></a> The old name <code>forbidden_static_files</code> is deprecated and will be removed in v1.</p> </li> </ul> <h3 id=tags>Tags<a class=headerlink href=#tags title="Permanent link">¤</a></h3> <h4 id=breaking-changes_3>🚨📢 BREAKING CHANGES<a class=headerlink href=#breaking-changes_3 title="Permanent link">¤</a></h4> <ul> <li> <p><code>{% component_dependencies %}</code> tag was removed. Instead, use <code>{% component_js_dependencies %}</code> and <code>{% component_css_dependencies %}</code></p> <ul> <li> <p>The combined tag was removed to encourage the best practice of putting JS scripts at the end of <code><body></code>, and CSS styles inside <code><head></code>.</p> <p>On the other hand, co-locating JS script and CSS styles can lead to a <a href=https://en.wikipedia.org/wiki/Flash_of_unstyled_content>flash of unstyled content</a>, as either JS scripts will block the rendering, or CSS will load too late.</p> </li> </ul> </li> <li> <p>The undocumented keyword arg <code>preload</code> of <code>{% component_js_dependencies %}</code> and <code>{% component_css_dependencies %}</code> tags was removed. This will be replaced with HTML fragment support.</p> </li> </ul> <h4 id=fix_28>Fix<a class=headerlink href=#fix_28 title="Permanent link">¤</a></h4> <ul> <li>Allow using forward slash (<code>/</code>) when defining custom TagFormatter, e.g. <code>{% MyComp %}..{% /MyComp %}</code>.</li> </ul> <h4 id=refactor_12>Refactor<a class=headerlink href=#refactor_12 title="Permanent link">¤</a></h4> <ul> <li><code>{% component_dependencies %}</code> tags are now OPTIONAL - If your components use JS and CSS, but you don't use <code>{% component_dependencies %}</code> tags, the JS and CSS will now be, by default, inserted at the end of <code><body></code> and at the end of <code><head></code> respectively.</li> </ul> <h3 id=slots>Slots<a class=headerlink href=#slots title="Permanent link">¤</a></h3> <h4 id=feat_14>Feat<a class=headerlink href=#feat_14 title="Permanent link">¤</a></h4> <ul> <li>Fills can now be defined within loops (<code>{% for %}</code>) or other tags (like <code>{% with %}</code>), or even other templates using <code>{% include %}</code>.</li> </ul> <p>Following is now possible</p> <div class=highlight><pre><span></span><code><a id=__codelineno-107-1 name=__codelineno-107-1 href=#__codelineno-107-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"table"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-107-2 name=__codelineno-107-2 href=#__codelineno-107-2></a><span class=x> </span><span class=cp>{%</span> <span class=k>for</span> <span class=nv>slot_name</span> <span class=k>in</span> <span class=nv>slots</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-107-3 name=__codelineno-107-3 href=#__codelineno-107-3></a><span class=x> </span><span class=cp>{%</span> <span class=k>fill</span> <span class=nv>name</span><span class=o>=</span><span class=nv>slot_name</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-107-4 name=__codelineno-107-4 href=#__codelineno-107-4></a><span class=x> </span><span class=cp>{%</span> <span class=k>endfill</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-107-5 name=__codelineno-107-5 href=#__codelineno-107-5></a><span class=x> </span><span class=cp>{%</span> <span class=k>endfor</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-107-6 name=__codelineno-107-6 href=#__codelineno-107-6></a><span class=cp>{%</span> <span class=k>endcomponent</span> <span class=cp>%}</span>
|
|
</code></pre></div> <ul> <li>If you need to access the data or the default content of a default fill, you can set the <code>name</code> kwarg to <code>"default"</code>.</li> </ul> <p>Previously, a default fill would be defined simply by omitting the <code>{% fill %}</code> tags:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-108-1 name=__codelineno-108-1 href=#__codelineno-108-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"child"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-108-2 name=__codelineno-108-2 href=#__codelineno-108-2></a><span class=x> Hello world</span>
|
|
<a id=__codelineno-108-3 name=__codelineno-108-3 href=#__codelineno-108-3></a><span class=cp>{%</span> <span class=k>endcomponent</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>But in that case you could not access the slot data or the default content, like it's possible for named fills:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-109-1 name=__codelineno-109-1 href=#__codelineno-109-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"child"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-109-2 name=__codelineno-109-2 href=#__codelineno-109-2></a><span class=x> </span><span class=cp>{%</span> <span class=k>fill</span> <span class=nv>name</span><span class=o>=</span><span class=s2>"header"</span> <span class=nv>data</span><span class=o>=</span><span class=s2>"data"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-109-3 name=__codelineno-109-3 href=#__codelineno-109-3></a><span class=x> Hello </span><span class=cp>{{</span> <span class=nv>data.user.name</span> <span class=cp>}}</span>
|
|
<a id=__codelineno-109-4 name=__codelineno-109-4 href=#__codelineno-109-4></a><span class=x> </span><span class=cp>{%</span> <span class=k>endfill</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-109-5 name=__codelineno-109-5 href=#__codelineno-109-5></a><span class=cp>{%</span> <span class=k>endcomponent</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>Now, you can specify default tag by using <code>name="default"</code>:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-110-1 name=__codelineno-110-1 href=#__codelineno-110-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"child"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-110-2 name=__codelineno-110-2 href=#__codelineno-110-2></a><span class=x> </span><span class=cp>{%</span> <span class=k>fill</span> <span class=nv>name</span><span class=o>=</span><span class=s2>"default"</span> <span class=nv>data</span><span class=o>=</span><span class=s2>"data"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-110-3 name=__codelineno-110-3 href=#__codelineno-110-3></a><span class=x> Hello </span><span class=cp>{{</span> <span class=nv>data.user.name</span> <span class=cp>}}</span>
|
|
<a id=__codelineno-110-4 name=__codelineno-110-4 href=#__codelineno-110-4></a><span class=x> </span><span class=cp>{%</span> <span class=k>endfill</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-110-5 name=__codelineno-110-5 href=#__codelineno-110-5></a><span class=cp>{%</span> <span class=k>endcomponent</span> <span class=cp>%}</span>
|
|
</code></pre></div> <ul> <li>When inside <code>get_context_data()</code> or other component methods, the default fill can now be accessed as <code>Component.input.slots["default"]</code>, e.g.:</li> </ul> <div class=highlight><pre><span></span><code><a id=__codelineno-111-1 name=__codelineno-111-1 href=#__codelineno-111-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyTable</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-111-2 name=__codelineno-111-2 href=#__codelineno-111-2></a> <span class=k>def</span><span class=w> </span><span class=nf>get_context_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=o>*</span><span class=n>args</span><span class=p>,</span> <span class=o>**</span><span class=n>kwargs</span><span class=p>):</span>
|
|
<a id=__codelineno-111-3 name=__codelineno-111-3 href=#__codelineno-111-3></a> <span class=n>default_slot</span> <span class=o>=</span> <span class=bp>self</span><span class=o>.</span><span class=n>input</span><span class=o>.</span><span class=n>slots</span><span class=p>[</span><span class=s2>"default"</span><span class=p>]</span>
|
|
<a id=__codelineno-111-4 name=__codelineno-111-4 href=#__codelineno-111-4></a> <span class=o>...</span>
|
|
</code></pre></div> <ul> <li>You can now dynamically pass all slots to a child component. This is similar to <a href=https://vue-land.github.io/faq/forwarding-slots#passing-all-slots>passing all slots in Vue</a>:</li> </ul> <div class=highlight><pre><span></span><code><a id=__codelineno-112-1 name=__codelineno-112-1 href=#__codelineno-112-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyTable</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-112-2 name=__codelineno-112-2 href=#__codelineno-112-2></a> <span class=k>def</span><span class=w> </span><span class=nf>get_context_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=o>*</span><span class=n>args</span><span class=p>,</span> <span class=o>**</span><span class=n>kwargs</span><span class=p>):</span>
|
|
<a id=__codelineno-112-3 name=__codelineno-112-3 href=#__codelineno-112-3></a> <span class=k>return</span> <span class=p>{</span>
|
|
<a id=__codelineno-112-4 name=__codelineno-112-4 href=#__codelineno-112-4></a> <span class=s2>"slots"</span><span class=p>:</span> <span class=bp>self</span><span class=o>.</span><span class=n>input</span><span class=o>.</span><span class=n>slots</span><span class=p>,</span>
|
|
<a id=__codelineno-112-5 name=__codelineno-112-5 href=#__codelineno-112-5></a> <span class=p>}</span>
|
|
<a id=__codelineno-112-6 name=__codelineno-112-6 href=#__codelineno-112-6></a>
|
|
<a id=__codelineno-112-7 name=__codelineno-112-7 href=#__codelineno-112-7></a> <span class=n>template</span><span class=p>:</span> <span class=s2>"""</span>
|
|
<a id=__codelineno-112-8 name=__codelineno-112-8 href=#__codelineno-112-8></a><span class=s2> <div></span>
|
|
<a id=__codelineno-112-9 name=__codelineno-112-9 href=#__codelineno-112-9></a><span class=s2> {</span><span class=si>% c</span><span class=s2>omponent "child" %}</span>
|
|
<a id=__codelineno-112-10 name=__codelineno-112-10 href=#__codelineno-112-10></a><span class=s2> {</span><span class=si>% f</span><span class=s2>or slot_name in slots %}</span>
|
|
<a id=__codelineno-112-11 name=__codelineno-112-11 href=#__codelineno-112-11></a><span class=s2> {</span><span class=si>% f</span><span class=s2>ill name=slot_name data="data" %}</span>
|
|
<a id=__codelineno-112-12 name=__codelineno-112-12 href=#__codelineno-112-12></a><span class=s2> {</span><span class=si>% s</span><span class=s2>lot name=slot_name ...data / %}</span>
|
|
<a id=__codelineno-112-13 name=__codelineno-112-13 href=#__codelineno-112-13></a><span class=s2> {</span><span class=si>% e</span><span class=s2>ndfill %}</span>
|
|
<a id=__codelineno-112-14 name=__codelineno-112-14 href=#__codelineno-112-14></a><span class=s2> {</span><span class=si>% e</span><span class=s2>ndfor %}</span>
|
|
<a id=__codelineno-112-15 name=__codelineno-112-15 href=#__codelineno-112-15></a><span class=s2> {</span><span class=si>% e</span><span class=s2>ndcomponent %}</span>
|
|
<a id=__codelineno-112-16 name=__codelineno-112-16 href=#__codelineno-112-16></a><span class=s2> </div></span>
|
|
<a id=__codelineno-112-17 name=__codelineno-112-17 href=#__codelineno-112-17></a><span class=s2> """</span>
|
|
</code></pre></div> <h4 id=fix_29>Fix<a class=headerlink href=#fix_29 title="Permanent link">¤</a></h4> <ul> <li> <p>Slots defined with <code>{% fill %}</code> tags are now properly accessible via <code>self.input.slots</code> in <code>get_context_data()</code></p> </li> <li> <p>Do not raise error if multiple slots with same name are flagged as default</p> </li> <li> <p>Slots can now be defined within loops (<code>{% for %}</code>) or other tags (like <code>{% with %}</code>), or even other templates using <code>{% include %}</code>.</p> </li> </ul> <p>Previously, following would cause the kwarg <code>name</code> to be an empty string:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-113-1 name=__codelineno-113-1 href=#__codelineno-113-1></a><span class=cp>{%</span> <span class=k>for</span> <span class=nv>slot_name</span> <span class=k>in</span> <span class=nv>slots</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-113-2 name=__codelineno-113-2 href=#__codelineno-113-2></a><span class=x> </span><span class=cp>{%</span> <span class=k>slot</span> <span class=nv>name</span><span class=o>=</span><span class=nv>slot_name</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-113-3 name=__codelineno-113-3 href=#__codelineno-113-3></a><span class=cp>{%</span> <span class=k>endfor</span> <span class=cp>%}</span>
|
|
</code></pre></div> <h4 id=refactor_13>Refactor<a class=headerlink href=#refactor_13 title="Permanent link">¤</a></h4> <ul> <li>When you define multiple slots with the same name inside a template, you now have to set the <code>default</code> and <code>required</code> flags individually.</li> </ul> <div class=highlight><pre><span></span><code><a id=__codelineno-114-1 name=__codelineno-114-1 href=#__codelineno-114-1></a><span class=p><</span><span class=nt>div</span> <span class=na>class</span><span class=o>=</span><span class=s>"calendar-component"</span><span class=p>></span>
|
|
<a id=__codelineno-114-2 name=__codelineno-114-2 href=#__codelineno-114-2></a> <span class=p><</span><span class=nt>div</span> <span class=na>class</span><span class=o>=</span><span class=s>"header"</span><span class=p>></span>
|
|
<a id=__codelineno-114-3 name=__codelineno-114-3 href=#__codelineno-114-3></a> <span class=cp>{%</span> <span class=k>slot</span> <span class=s2>"image"</span> <span class=nv>default</span> <span class=nv>required</span> <span class=cp>%}</span>Image here<span class=cp>{%</span> <span class=k>endslot</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-114-4 name=__codelineno-114-4 href=#__codelineno-114-4></a> <span class=p></</span><span class=nt>div</span><span class=p>></span>
|
|
<a id=__codelineno-114-5 name=__codelineno-114-5 href=#__codelineno-114-5></a> <span class=p><</span><span class=nt>div</span> <span class=na>class</span><span class=o>=</span><span class=s>"body"</span><span class=p>></span>
|
|
<a id=__codelineno-114-6 name=__codelineno-114-6 href=#__codelineno-114-6></a> <span class=cp>{%</span> <span class=k>slot</span> <span class=s2>"image"</span> <span class=nv>default</span> <span class=nv>required</span> <span class=cp>%}</span>Image here<span class=cp>{%</span> <span class=k>endslot</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-114-7 name=__codelineno-114-7 href=#__codelineno-114-7></a> <span class=p></</span><span class=nt>div</span><span class=p>></span>
|
|
<a id=__codelineno-114-8 name=__codelineno-114-8 href=#__codelineno-114-8></a><span class=p></</span><span class=nt>div</span><span class=p>></span>
|
|
</code></pre></div> <p>This means you can also have multiple slots with the same name but different conditions.</p> <p>E.g. in this example, we have a component that renders a user avatar - a small circular image with a profile picture of name initials.</p> <p>If the component is given <code>image_src</code> or <code>name_initials</code> variables, the <code>image</code> slot is optional. But if neither of those are provided, you MUST fill the <code>image</code> slot.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-115-1 name=__codelineno-115-1 href=#__codelineno-115-1></a><span class=p><</span><span class=nt>div</span> <span class=na>class</span><span class=o>=</span><span class=s>"avatar"</span><span class=p>></span>
|
|
<a id=__codelineno-115-2 name=__codelineno-115-2 href=#__codelineno-115-2></a> <span class=cp>{%</span> <span class=k>if</span> <span class=nv>image_src</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-115-3 name=__codelineno-115-3 href=#__codelineno-115-3></a> <span class=cp>{%</span> <span class=k>slot</span> <span class=s2>"image"</span> <span class=nv>default</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-115-4 name=__codelineno-115-4 href=#__codelineno-115-4></a> <span class=p><</span><span class=nt>img</span> <span class=na>src</span><span class=o>=</span><span class=s>"</span><span class=cp>{{</span> <span class=nv>image_src</span> <span class=cp>}}</span><span class=s>"</span> <span class=p>/></span>
|
|
<a id=__codelineno-115-5 name=__codelineno-115-5 href=#__codelineno-115-5></a> <span class=cp>{%</span> <span class=k>endslot</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-115-6 name=__codelineno-115-6 href=#__codelineno-115-6></a> <span class=cp>{%</span> <span class=k>elif</span> <span class=nv>name_initials</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-115-7 name=__codelineno-115-7 href=#__codelineno-115-7></a> <span class=cp>{%</span> <span class=k>slot</span> <span class=s2>"image"</span> <span class=nv>default</span> <span class=nv>required</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-115-8 name=__codelineno-115-8 href=#__codelineno-115-8></a> <span class=p><</span><span class=nt>div</span> <span class=na>style</span><span class=o>=</span><span class=s>"</span>
|
|
<a id=__codelineno-115-9 name=__codelineno-115-9 href=#__codelineno-115-9></a><span class=s> border-radius: 25px;</span>
|
|
<a id=__codelineno-115-10 name=__codelineno-115-10 href=#__codelineno-115-10></a><span class=s> width: 50px;</span>
|
|
<a id=__codelineno-115-11 name=__codelineno-115-11 href=#__codelineno-115-11></a><span class=s> height: 50px;</span>
|
|
<a id=__codelineno-115-12 name=__codelineno-115-12 href=#__codelineno-115-12></a><span class=s> background: blue;</span>
|
|
<a id=__codelineno-115-13 name=__codelineno-115-13 href=#__codelineno-115-13></a><span class=s> "</span><span class=p>></span>
|
|
<a id=__codelineno-115-14 name=__codelineno-115-14 href=#__codelineno-115-14></a> <span class=cp>{{</span> <span class=nv>name_initials</span> <span class=cp>}}</span>
|
|
<a id=__codelineno-115-15 name=__codelineno-115-15 href=#__codelineno-115-15></a> <span class=p></</span><span class=nt>div</span><span class=p>></span>
|
|
<a id=__codelineno-115-16 name=__codelineno-115-16 href=#__codelineno-115-16></a> <span class=cp>{%</span> <span class=k>endslot</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-115-17 name=__codelineno-115-17 href=#__codelineno-115-17></a> <span class=cp>{%</span> <span class=k>else</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-115-18 name=__codelineno-115-18 href=#__codelineno-115-18></a> <span class=cp>{%</span> <span class=k>slot</span> <span class=s2>"image"</span> <span class=nv>default</span> <span class=nv>required</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-115-19 name=__codelineno-115-19 href=#__codelineno-115-19></a> <span class=cp>{%</span> <span class=k>endif</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-115-20 name=__codelineno-115-20 href=#__codelineno-115-20></a><span class=p></</span><span class=nt>div</span><span class=p>></span>
|
|
</code></pre></div> <ul> <li>The slot fills that were passed to a component and which can be accessed as <code>Component.input.slots</code> can now be passed through the Django template, e.g. as inputs to other tags.</li> </ul> <p>Internally, django-components handles slot fills as functions.</p> <p>Previously, if you tried to pass a slot fill within a template, Django would try to call it as a function.</p> <p>Now, something like this is possible:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-116-1 name=__codelineno-116-1 href=#__codelineno-116-1></a><span class=k>class</span><span class=w> </span><span class=nc>MyTable</span><span class=p>(</span><span class=n>Component</span><span class=p>):</span>
|
|
<a id=__codelineno-116-2 name=__codelineno-116-2 href=#__codelineno-116-2></a> <span class=k>def</span><span class=w> </span><span class=nf>get_context_data</span><span class=p>(</span><span class=bp>self</span><span class=p>,</span> <span class=o>*</span><span class=n>args</span><span class=p>,</span> <span class=o>**</span><span class=n>kwargs</span><span class=p>):</span>
|
|
<a id=__codelineno-116-3 name=__codelineno-116-3 href=#__codelineno-116-3></a> <span class=k>return</span> <span class=p>{</span>
|
|
<a id=__codelineno-116-4 name=__codelineno-116-4 href=#__codelineno-116-4></a> <span class=s2>"child_slot"</span><span class=p>:</span> <span class=bp>self</span><span class=o>.</span><span class=n>input</span><span class=o>.</span><span class=n>slots</span><span class=p>[</span><span class=s2>"child_slot"</span><span class=p>],</span>
|
|
<a id=__codelineno-116-5 name=__codelineno-116-5 href=#__codelineno-116-5></a> <span class=p>}</span>
|
|
<a id=__codelineno-116-6 name=__codelineno-116-6 href=#__codelineno-116-6></a>
|
|
<a id=__codelineno-116-7 name=__codelineno-116-7 href=#__codelineno-116-7></a> <span class=n>template</span><span class=p>:</span> <span class=s2>"""</span>
|
|
<a id=__codelineno-116-8 name=__codelineno-116-8 href=#__codelineno-116-8></a><span class=s2> <div></span>
|
|
<a id=__codelineno-116-9 name=__codelineno-116-9 href=#__codelineno-116-9></a><span class=s2> {</span><span class=si>% c</span><span class=s2>omponent "child" content=child_slot / %}</span>
|
|
<a id=__codelineno-116-10 name=__codelineno-116-10 href=#__codelineno-116-10></a><span class=s2> </div></span>
|
|
<a id=__codelineno-116-11 name=__codelineno-116-11 href=#__codelineno-116-11></a><span class=s2> """</span>
|
|
</code></pre></div> <p>NOTE: Using <code>{% slot %}</code> and <code>{% fill %}</code> tags is still the preferred method, but the approach above may be necessary in some complex or edge cases.</p> <ul> <li>The <code>is_filled</code> variable (and the <code>{{ component_vars.is_filled }}</code> context variable) now returns <code>False</code> when you try to access a slot name which has not been defined:</li> </ul> <p>Before:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-117-1 name=__codelineno-117-1 href=#__codelineno-117-1></a><span class=cp>{{</span> <span class=nv>component_vars.is_filled.header</span> <span class=cp>}}</span><span class=x> -> True</span>
|
|
<a id=__codelineno-117-2 name=__codelineno-117-2 href=#__codelineno-117-2></a><span class=cp>{{</span> <span class=nv>component_vars.is_filled.footer</span> <span class=cp>}}</span><span class=x> -> False</span>
|
|
<a id=__codelineno-117-3 name=__codelineno-117-3 href=#__codelineno-117-3></a><span class=cp>{{</span> <span class=nv>component_vars.is_filled.nonexist</span> <span class=cp>}}</span><span class=x> -> "" (empty string)</span>
|
|
</code></pre></div> <p>After: <div class=highlight><pre><span></span><code><a id=__codelineno-118-1 name=__codelineno-118-1 href=#__codelineno-118-1></a><span class=cp>{{</span> <span class=nv>component_vars.is_filled.header</span> <span class=cp>}}</span><span class=x> -> True</span>
|
|
<a id=__codelineno-118-2 name=__codelineno-118-2 href=#__codelineno-118-2></a><span class=cp>{{</span> <span class=nv>component_vars.is_filled.footer</span> <span class=cp>}}</span><span class=x> -> False</span>
|
|
<a id=__codelineno-118-3 name=__codelineno-118-3 href=#__codelineno-118-3></a><span class=cp>{{</span> <span class=nv>component_vars.is_filled.nonexist</span> <span class=cp>}}</span><span class=x> -> False</span>
|
|
</code></pre></div></p> <ul> <li> <p>Components no longer raise an error if there are extra slot fills</p> </li> <li> <p>Components will raise error when a slot is doubly-filled. </p> </li> </ul> <p>E.g. if we have a component with a default slot:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-119-1 name=__codelineno-119-1 href=#__codelineno-119-1></a><span class=cp>{%</span> <span class=k>slot</span> <span class=nv>name</span><span class=o>=</span><span class=s2>"content"</span> <span class=nv>default</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>Now there is two ways how we can target this slot: Either using <code>name="default"</code> or <code>name="content"</code>.</p> <p>In case you specify BOTH, the component will raise an error:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-120-1 name=__codelineno-120-1 href=#__codelineno-120-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"child"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-120-2 name=__codelineno-120-2 href=#__codelineno-120-2></a><span class=x> </span><span class=cp>{%</span> <span class=k>fill</span> <span class=nv>slot</span><span class=o>=</span><span class=s2>"default"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-120-3 name=__codelineno-120-3 href=#__codelineno-120-3></a><span class=x> Hello from default slot</span>
|
|
<a id=__codelineno-120-4 name=__codelineno-120-4 href=#__codelineno-120-4></a><span class=x> </span><span class=cp>{%</span> <span class=k>endfill</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-120-5 name=__codelineno-120-5 href=#__codelineno-120-5></a><span class=x> </span><span class=cp>{%</span> <span class=k>fill</span> <span class=nv>slot</span><span class=o>=</span><span class=s2>"content"</span> <span class=nv>data</span><span class=o>=</span><span class=s2>"data"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-120-6 name=__codelineno-120-6 href=#__codelineno-120-6></a><span class=x> Hello from content slot</span>
|
|
<a id=__codelineno-120-7 name=__codelineno-120-7 href=#__codelineno-120-7></a><span class=x> </span><span class=cp>{%</span> <span class=k>endfill</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-120-8 name=__codelineno-120-8 href=#__codelineno-120-8></a><span class=cp>{%</span> <span class=k>endcomponent</span> <span class=cp>%}</span>
|
|
</code></pre></div> <h2 id=v0100>🚨📢 v0.100<a class=headerlink href=#v0100 title="Permanent link">¤</a></h2> <h4 id=breaking-changes_4>BREAKING CHANGES<a class=headerlink href=#breaking-changes_4 title="Permanent link">¤</a></h4> <ul> <li> <p><code>django_components.safer_staticfiles</code> app was removed. It is no longer needed.</p> </li> <li> <p>Installation changes:</p> <ul> <li>Instead of defining component directories in <code>STATICFILES_DIRS</code>, set them to <a href=https://github.com/django-components/django-components#dirs><code>COMPONENTS.dirs</code></a>.</li> <li> <p>You now must define <code>STATICFILES_FINDERS</code></p> </li> <li> <p><a href=https://github.com/django-components/django-components/blob/master/docs/migrating_from_safer_staticfiles.md>See here how to migrate your settings.py</a></p> </li> </ul> </li> </ul> <h4 id=feat_15>Feat<a class=headerlink href=#feat_15 title="Permanent link">¤</a></h4> <ul> <li>Beside the top-level <code>/components</code> directory, you can now define also app-level components dirs, e.g. <code>[app]/components</code> (See <a href=https://github.com/django-components/django-components#app_dirs><code>COMPONENTS.app_dirs</code></a>).</li> </ul> <h4 id=refactor_14>Refactor<a class=headerlink href=#refactor_14 title="Permanent link">¤</a></h4> <ul> <li>When you call <code>as_view()</code> on a component instance, that instance will be passed to <code>View.as_view()</code></li> </ul> <h2 id=v097>v0.97<a class=headerlink href=#v097 title="Permanent link">¤</a></h2> <h4 id=fix_30>Fix<a class=headerlink href=#fix_30 title="Permanent link">¤</a></h4> <ul> <li>Fixed template caching. You can now also manually create cached templates with <a href=https://github.com/django-components/django-components#template_cache_size---tune-the-template-cache><code>cached_template()</code></a></li> </ul> <h4 id=refactor_15>Refactor<a class=headerlink href=#refactor_15 title="Permanent link">¤</a></h4> <ul> <li> <p>The previously undocumented <code>get_template</code> was made private.</p> </li> <li> <p>In it's place, there's a new <code>get_template</code>, which supersedes <code>get_template_string</code> (will be removed in v1). The new <code>get_template</code> is the same as <code>get_template_string</code>, except it allows to return either a string or a Template instance.</p> </li> <li> <p>You now must use only one of <code>template</code>, <code>get_template</code>, <code>template_name</code>, or <code>get_template_name</code>.</p> </li> </ul> <h2 id=v096>v0.96<a class=headerlink href=#v096 title="Permanent link">¤</a></h2> <h4 id=feat_16>Feat<a class=headerlink href=#feat_16 title="Permanent link">¤</a></h4> <ul> <li> <p>Run-time type validation for Python 3.11+ - If the <code>Component</code> class is typed, e.g. <code>Component[Args, Kwargs, ...]</code>, the args, kwargs, slots, and data are validated against the given types. (See <a href=https://github.com/django-components/django-components#runtime-input-validation-with-types>Runtime input validation with types</a>)</p> </li> <li> <p>Render hooks - Set <code>on_render_before</code> and <code>on_render_after</code> methods on <code>Component</code> to intercept or modify the template or context before rendering, or the rendered result afterwards. (See <a href=https://github.com/django-components/django-components#component-hooks>Component hooks</a>)</p> </li> <li> <p><code>component_vars.is_filled</code> context variable can be accessed from within <code>on_render_before</code> and <code>on_render_after</code> hooks as <code>self.is_filled.my_slot</code></p> </li> </ul> <h2 id=095>0.95<a class=headerlink href=#095 title="Permanent link">¤</a></h2> <h4 id=feat_17>Feat<a class=headerlink href=#feat_17 title="Permanent link">¤</a></h4> <ul> <li>Added support for dynamic components, where the component name is passed as a variable. (See <a href=https://github.com/django-components/django-components#dynamic-components>Dynamic components</a>)</li> </ul> <h4 id=refactor_16>Refactor<a class=headerlink href=#refactor_16 title="Permanent link">¤</a></h4> <ul> <li>Changed <code>Component.input</code> to raise <code>RuntimeError</code> if accessed outside of render context. Previously it returned <code>None</code> if unset.</li> </ul> <h2 id=v094>v0.94<a class=headerlink href=#v094 title="Permanent link">¤</a></h2> <h4 id=feat_18>Feat<a class=headerlink href=#feat_18 title="Permanent link">¤</a></h4> <ul> <li> <p>django_components now automatically configures Django to support multi-line tags. (See <a href=https://github.com/django-components/django-components#multi-line-tags>Multi-line tags</a>)</p> </li> <li> <p>New setting <code>reload_on_template_change</code>. Set this to <code>True</code> to reload the dev server on changes to component template files. (See <a href=https://github.com/django-components/django-components#reload-dev-server-on-component-file-changes>Reload dev server on component file changes</a>)</p> </li> </ul> <h2 id=v093>v0.93<a class=headerlink href=#v093 title="Permanent link">¤</a></h2> <h4 id=feat_19>Feat<a class=headerlink href=#feat_19 title="Permanent link">¤</a></h4> <ul> <li> <p>Spread operator <code>...dict</code> inside template tags. (See <a href=https://github.com/django-components/django-components#spread-operator>Spread operator</a>)</p> </li> <li> <p>Use template tags inside string literals in component inputs. (See <a href=https://github.com/django-components/django-components#use-template-tags-inside-component-inputs>Use template tags inside component inputs</a>)</p> </li> <li> <p>Dynamic slots, fills and provides - The <code>name</code> argument for these can now be a variable, a template expression, or via spread operator</p> </li> <li> <p>Component library authors can now configure <code>CONTEXT_BEHAVIOR</code> and <code>TAG_FORMATTER</code> settings independently from user settings.</p> </li> </ul> <h2 id=v092>🚨📢 v0.92<a class=headerlink href=#v092 title="Permanent link">¤</a></h2> <h4 id=breaking-changes_5>BREAKING CHANGES<a class=headerlink href=#breaking-changes_5 title="Permanent link">¤</a></h4> <ul> <li><code>Component</code> class is no longer a subclass of <code>View</code>. To configure the <code>View</code> class, set the <code>Component.View</code> nested class. HTTP methods like <code>get</code> or <code>post</code> can still be defined directly on <code>Component</code> class, and <code>Component.as_view()</code> internally calls <code>Component.View.as_view()</code>. (See <a href=https://github.com/django-components/django-components#modifying-the-view-class>Modifying the View class</a>)</li> </ul> <h4 id=feat_20>Feat<a class=headerlink href=#feat_20 title="Permanent link">¤</a></h4> <ul> <li> <p>The inputs (args, kwargs, slots, context, ...) that you pass to <code>Component.render()</code> can be accessed from within <code>get_context_data</code>, <code>get_template</code> and <code>get_template_name</code> via <code>self.input</code>. (See <a href=https://github.com/django-components/django-components#accessing-data-passed-to-the-component>Accessing data passed to the component</a>)</p> </li> <li> <p>Typing: <code>Component</code> class supports generics that specify types for <code>Component.render</code> (See <a href=https://github.com/django-components/django-components#adding-type-hints-with-generics>Adding type hints with Generics</a>)</p> </li> </ul> <h2 id=v090>v0.90<a class=headerlink href=#v090 title="Permanent link">¤</a></h2> <h4 id=feat_21>Feat<a class=headerlink href=#feat_21 title="Permanent link">¤</a></h4> <ul> <li> <p>All tags (<code>component</code>, <code>slot</code>, <code>fill</code>, ...) now support "self-closing" or "inline" form, where you can omit the closing tag:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-121-1 name=__codelineno-121-1 href=#__codelineno-121-1></a><span class=c>{# Before #}</span>
|
|
<a id=__codelineno-121-2 name=__codelineno-121-2 href=#__codelineno-121-2></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"button"</span> <span class=cp>%}{%</span> <span class=k>endcomponent</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-121-3 name=__codelineno-121-3 href=#__codelineno-121-3></a><span class=c>{# After #}</span>
|
|
<a id=__codelineno-121-4 name=__codelineno-121-4 href=#__codelineno-121-4></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"button"</span> <span class=o>/</span> <span class=cp>%}</span>
|
|
</code></pre></div> </li> <li> <p>All tags now support the "dictionary key" or "aggregate" syntax (<code>kwarg:key=val</code>):</p> <div class=highlight><pre><span></span><code><a id=__codelineno-122-1 name=__codelineno-122-1 href=#__codelineno-122-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"button"</span> <span class=nv>attrs</span><span class=o>:</span><span class=nv>class</span><span class=o>=</span><span class=s2>"hidden"</span> <span class=cp>%}</span>
|
|
</code></pre></div> </li> <li> <p>You can change how the components are written in the template with <a href=https://github.com/django-components/django-components#customizing-component-tags-with-tagformatter>TagFormatter</a>.</p> <p>The default is <code>django_components.component_formatter</code>:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-123-1 name=__codelineno-123-1 href=#__codelineno-123-1></a><span class=cp>{%</span> <span class=k>component</span> <span class=s2>"button"</span> <span class=nv>href</span><span class=o>=</span><span class=s2>"..."</span> <span class=nv>disabled</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-123-2 name=__codelineno-123-2 href=#__codelineno-123-2></a><span class=x> Click me!</span>
|
|
<a id=__codelineno-123-3 name=__codelineno-123-3 href=#__codelineno-123-3></a><span class=cp>{%</span> <span class=k>endcomponent</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>While <code>django_components.shorthand_component_formatter</code> allows you to write components like so:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-124-1 name=__codelineno-124-1 href=#__codelineno-124-1></a><span class=cp>{%</span> <span class=k>button</span> <span class=nv>href</span><span class=o>=</span><span class=s2>"..."</span> <span class=nv>disabled</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-124-2 name=__codelineno-124-2 href=#__codelineno-124-2></a><span class=x> Click me!</span>
|
|
<a id=__codelineno-124-3 name=__codelineno-124-3 href=#__codelineno-124-3></a><span class=cp>{%</span> <span class=k>endbutton</span> <span class=cp>%}</span>
|
|
</code></pre></div> </li> </ul> <h2 id=v085>🚨📢 v0.85<a class=headerlink href=#v085 title="Permanent link">¤</a></h2> <h4 id=breaking-changes_6>BREAKING CHANGES<a class=headerlink href=#breaking-changes_6 title="Permanent link">¤</a></h4> <ul> <li> <p>Autodiscovery module resolution changed. Following undocumented behavior was removed:</p> <ul> <li> <p>Previously, autodiscovery also imported any <code>[app]/components.py</code> files, and used <code>SETTINGS_MODULE</code> to search for component dirs.</p> <p>To migrate from:</p> <ul> <li> <p><code>[app]/components.py</code> - Define each module in <code>COMPONENTS.libraries</code> setting, or import each module inside the <code>AppConfig.ready()</code> hook in respective <code>apps.py</code> files.</p> </li> <li> <p><code>SETTINGS_MODULE</code> - Define component dirs using <code>STATICFILES_DIRS</code></p> </li> </ul> </li> <li> <p>Previously, autodiscovery handled relative files in <code>STATICFILES_DIRS</code>. To align with Django, <code>STATICFILES_DIRS</code> now must be full paths (<a href=https://docs.djangoproject.com/en/5.2/ref/settings/#std-setting-STATICFILES_DIRS>Django docs</a>).</p> </li> </ul> </li> </ul> <h2 id=v081>🚨📢 v0.81<a class=headerlink href=#v081 title="Permanent link">¤</a></h2> <h4 id=breaking-changes_7>BREAKING CHANGES<a class=headerlink href=#breaking-changes_7 title="Permanent link">¤</a></h4> <ul> <li>The order of arguments to <code>render_to_response</code> has changed, to align with the (now public) <code>render</code> method of <code>Component</code> class.</li> </ul> <h4 id=feat_22>Feat<a class=headerlink href=#feat_22 title="Permanent link">¤</a></h4> <ul> <li> <p><code>Component.render()</code> is public and documented</p> </li> <li> <p>Slots passed <code>render_to_response</code> and <code>render</code> can now be rendered also as functions.</p> </li> </ul> <h2 id=v080>v0.80<a class=headerlink href=#v080 title="Permanent link">¤</a></h2> <h4 id=feat_23>Feat<a class=headerlink href=#feat_23 title="Permanent link">¤</a></h4> <ul> <li>Vue-like provide/inject with the <code>{% provide %}</code> tag and <code>inject()</code> method.</li> </ul> <h2 id=v079>🚨📢 v0.79<a class=headerlink href=#v079 title="Permanent link">¤</a></h2> <h4 id=breaking-changes_8>BREAKING CHANGES<a class=headerlink href=#breaking-changes_8 title="Permanent link">¤</a></h4> <ul> <li>Default value for the <code>COMPONENTS.context_behavior</code> setting was changes from <code>"isolated"</code> to <code>"django"</code>. If you did not set this value explicitly before, this may be a breaking change. See the rationale for change <a href=https://github.com/django-components/django-components/issues/498>here</a>.</li> </ul> <h2 id=v077>🚨📢 v0.77<a class=headerlink href=#v077 title="Permanent link">¤</a></h2> <h4 id=breaking>BREAKING<a class=headerlink href=#breaking title="Permanent link">¤</a></h4> <ul> <li> <p>The syntax for accessing default slot content has changed from</p> <div class=highlight><pre><span></span><code><a id=__codelineno-125-1 name=__codelineno-125-1 href=#__codelineno-125-1></a><span class=cp>{%</span> <span class=k>fill</span> <span class=s2>"my_slot"</span> <span class=k>as</span> <span class=s2>"alias"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-125-2 name=__codelineno-125-2 href=#__codelineno-125-2></a><span class=x> </span><span class=cp>{{</span> <span class=nv>alias.default</span> <span class=cp>}}</span>
|
|
<a id=__codelineno-125-3 name=__codelineno-125-3 href=#__codelineno-125-3></a><span class=cp>{%</span> <span class=k>endfill</span> <span class=cp>%}</span>
|
|
</code></pre></div> <p>to</p> <div class=highlight><pre><span></span><code><a id=__codelineno-126-1 name=__codelineno-126-1 href=#__codelineno-126-1></a><span class=cp>{%</span> <span class=k>fill</span> <span class=s2>"my_slot"</span> <span class=nv>default</span><span class=o>=</span><span class=s2>"alias"</span> <span class=cp>%}</span>
|
|
<a id=__codelineno-126-2 name=__codelineno-126-2 href=#__codelineno-126-2></a><span class=x> </span><span class=cp>{{</span> <span class=nv>alias</span> <span class=cp>}}</span>
|
|
<a id=__codelineno-126-3 name=__codelineno-126-3 href=#__codelineno-126-3></a><span class=cp>{%</span> <span class=k>endfill</span> <span class=cp>%}</span>
|
|
</code></pre></div> </li> </ul> <h2 id=v074>v0.74<a class=headerlink href=#v074 title="Permanent link">¤</a></h2> <h4 id=feat_24>Feat<a class=headerlink href=#feat_24 title="Permanent link">¤</a></h4> <ul> <li> <p><code>{% html_attrs %}</code> tag for formatting data as HTML attributes</p> </li> <li> <p><code>prefix:key=val</code> construct for passing dicts to components</p> </li> </ul> <h2 id=v070>🚨📢 v0.70<a class=headerlink href=#v070 title="Permanent link">¤</a></h2> <h4 id=breaking-changes_9>BREAKING CHANGES<a class=headerlink href=#breaking-changes_9 title="Permanent link">¤</a></h4> <ul> <li> <p><code>{% if_filled "my_slot" %}</code> tags were replaced with <code>{{ component_vars.is_filled.my_slot }}</code> variables.</p> </li> <li> <p>Simplified settings - <code>slot_context_behavior</code> and <code>context_behavior</code> were merged. See the <a href=https://github.com/django-components/django-components#context-behavior>documentation</a> for more details.</p> </li> </ul> <h2 id=v067>v0.67<a class=headerlink href=#v067 title="Permanent link">¤</a></h2> <h4 id=refactor_17>Refactor<a class=headerlink href=#refactor_17 title="Permanent link">¤</a></h4> <ul> <li>Changed the default way how context variables are resolved in slots. See the <a href=https://github.com/django-components/django-components/tree/0.67#isolate-components-slots>documentation</a> for more details.</li> </ul> <h2 id=v050>🚨📢 v0.50<a class=headerlink href=#v050 title="Permanent link">¤</a></h2> <h4 id=breaking-changes_10>BREAKING CHANGES<a class=headerlink href=#breaking-changes_10 title="Permanent link">¤</a></h4> <ul> <li> <p><code>{% component_block %}</code> is now <code>{% component %}</code>, and <code>{% component %}</code> blocks need an ending <code>{% endcomponent %}</code> tag.</p> <p>The new <code>python manage.py upgradecomponent</code> command can be used to upgrade a directory (use <code>--path</code> argument to point to each dir) of templates that use components to the new syntax automatically.</p> <p>This change is done to simplify the API in anticipation of a 1.0 release of django_components. After 1.0 we intend to be stricter with big changes like this in point releases.</p> </li> </ul> <h2 id=v034>v0.34<a class=headerlink href=#v034 title="Permanent link">¤</a></h2> <h4 id=feat_25>Feat<a class=headerlink href=#feat_25 title="Permanent link">¤</a></h4> <ul> <li>Components as views, which allows you to handle requests and render responses from within a component. See the <a href=https://github.com/django-components/django-components#use-components-as-views>documentation</a> for more details.</li> </ul> <h2 id=v028>v0.28<a class=headerlink href=#v028 title="Permanent link">¤</a></h2> <h4 id=feat_26>Feat<a class=headerlink href=#feat_26 title="Permanent link">¤</a></h4> <ul> <li>'implicit' slot filling and the <code>default</code> option for <code>slot</code> tags.</li> </ul> <h2 id=v027>v0.27<a class=headerlink href=#v027 title="Permanent link">¤</a></h2> <h4 id=feat_27>Feat<a class=headerlink href=#feat_27 title="Permanent link">¤</a></h4> <ul> <li>A second installable app <code>django_components.safer_staticfiles</code>. It provides the same behavior as <code>django.contrib.staticfiles</code> but with extra security guarantees (more info below in <a href=https://github.com/django-components/django-components#security-notes>Security Notes</a>).</li> </ul> <h2 id=v026>🚨📢 v0.26<a class=headerlink href=#v026 title="Permanent link">¤</a></h2> <h4 id=breaking-changes_11>BREAKING CHANGES<a class=headerlink href=#breaking-changes_11 title="Permanent link">¤</a></h4> <ul> <li> <p>Changed the syntax for <code>{% slot %}</code> tags. From now on, we separate defining a slot (<code>{% slot %}</code>) from filling a slot with content (<code>{% fill %}</code>). This means you will likely need to change a lot of slot tags to fill.</p> <p>We understand this is annoying, but it's the only way we can get support for nested slots that fill in other slots, which is a very nice feature to have access to. Hoping that this will feel worth it!</p> </li> </ul> <h2 id=v022>v0.22<a class=headerlink href=#v022 title="Permanent link">¤</a></h2> <h4 id=feat_28>Feat<a class=headerlink href=#feat_28 title="Permanent link">¤</a></h4> <ul> <li> <p>All files inside components subdirectores are autoimported to simplify setup.</p> <p>An existing project might start to get <code>AlreadyRegistered</code> errors because of this. To solve this, either remove your custom loading of components, or set <code>"autodiscover": False</code> in <code>settings.COMPONENTS</code>.</p> </li> </ul> <h2 id=v017>v0.17<a class=headerlink href=#v017 title="Permanent link">¤</a></h2> <h4 id=breaking-changes_12>BREAKING CHANGES<a class=headerlink href=#breaking-changes_12 title="Permanent link">¤</a></h4> <ul> <li> <p>Renamed <code>Component.context</code> and <code>Component.template</code> to <code>get_context_data</code> and <code>get_template_name</code>. The old methods still work, but emit a deprecation warning.</p> <p>This change was done to sync naming with Django's class based views, and make using django-components more familiar to Django users. <code>Component.context</code> and <code>Component.template</code> will be removed when version 1.0 is released.</p> </li> </ul> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-timeago" title="December 3, 2024 11:32:21 UTC"><span class=timeago datetime=2024-12-03T11:32:21+00:00 locale=en></span></span><span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-iso_date" title="December 3, 2024 11:32:21 UTC">2024-12-03</span> </span> <span class=md-source-file__fact> <span class=md-icon title=Contributors> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 4a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4"/></svg> </span> <nav> <a href=mailto:juraj.oravec.josefson@gmail.com>Juro Oravec</a> </nav> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../reference/testing_api/ class="md-footer__link md-footer__link--prev" aria-label="Previous: Testing API"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> Testing API </div> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> Made with <a href=https://squidfunk.github.io/mkdocs-material/ target=_blank rel=noopener> Material for MkDocs </a> </div> <div class=md-social> <a href=https://github.com/django-components/django-components target=_blank rel=noopener title=github.com class=md-social__link> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill=currentColor d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg> </a> <a href=https://pypi.org/project/django-components/ target=_blank rel=noopener title=pypi.org class=md-social__link> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 448 512"><!-- Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill=currentColor d="M439.8 200.5c-7.7-30.9-22.3-54.2-53.4-54.2h-40.1v47.4c0 36.8-31.2 67.8-66.8 67.8H172.7c-29.2 0-53.4 25-53.4 54.3v101.8c0 29 25.2 46 53.4 54.3 33.8 9.9 66.3 11.7 106.8 0 26.9-7.8 53.4-23.5 53.4-54.3v-40.7H226.2v-13.6h160.2c31.1 0 42.6-21.7 53.4-54.2 11.2-33.5 10.7-65.7 0-108.6M286.2 444.7a20.4 20.4 0 1 1 0-40.7 20.4 20.4 0 1 1 0 40.7M167.8 248.1h106.8c29.7 0 53.4-24.5 53.4-54.3V91.9c0-29-24.4-50.7-53.4-55.6-35.8-5.9-74.7-5.6-106.8.1-45.2 8-53.4 24.7-53.4 55.6v40.7h106.9v13.6h-147c-31.1 0-58.3 18.7-66.8 54.2-9.8 40.7-10.2 66.1 0 108.6 7.6 31.6 25.7 54.2 56.8 54.2H101v-48.8c0-35.3 30.5-66.4 66.8-66.4m-6.6-183.4a20.4 20.4 0 1 1 0 40.8 20.4 20.4 0 1 1 0-40.8"/></svg> </a> </div> </div> </div> </footer> </div> <div class=md-dialog data-md-component=dialog> <div class="md-dialog__inner md-typeset"></div> </div> <div class=md-progress data-md-component=progress role=progressbar></div> <script id=__config type=application/json>{"base": "..", "features": ["content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tabs.link", "navigation.expand", "navigation.footer", "navigation.instant", "navigation.instant.progress", "navigation.indexes", "navigation.sections", "navigation.tabs", "navigation.tracking", "navigation.top", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"alias": true, "default": ["dev"], "provider": "mike"}}</script> <script src=../assets/javascripts/bundle.50899def.min.js></script> <script src=../assets/_markdown_exec_pyodide.js></script> <script src=../js/timeago.min.js></script> <script src=../js/timeago_mkdocs_material.js></script> </body> </html> |