Comet ===== Comet is a template system for Picomet. The ``picomet.backends.picomet.PicometTemplates`` class implements the template backend for Django. The :ref:`picomet/comet.js ` module provides comet templates it's client side SPA(Single Page Application) capabilities with the help of `Alpinejs `_. Layout ------ A ``Layout`` is used by a page or a nested layout .. code-block:: html :emphasize-lines: 10
.. code-block:: text :emphasize-lines: 2,9 About

This is the about page

.. warning:: Everything outside of ``Layout`` tag will be ignored. Variable -------- To embed any data into a template, use the ``{$ $}`` syntax or ``s-text`` attribute. .. code-block:: html {$ request.method $} or Expression in ``s-text`` and ``{$ $}`` is evaluated using the python's built in ``eval`` function. DTL --- If the comet syntax is not enough for you, Picomet provides ``Django Template Language``'s two features in comet template. Variable ~~~~~~~~ You can use ``DTL``'s double curly braces syntax if you want to use any filter. .. code-block:: django
{{ request.method|lower }}
Tag ~~~ You can use single ``DTL`` tags inside comet templates. .. code-block:: django
{% url 'core:index' %}
.. warning:: Comet template doesn't support multi tags like ``{% comment %}{% endcomment %}`` .. _targets: Targets ------- ``Targets`` is a list of strings, sent as a request header which picomet uses to partially render a page. .. _s-group: s-group ~~~~~~~ Picomet uses the ``s-group`` attribute to partially render multiple elements on a page with the same group name. See how to use ``s-group`` in the :doc:`/action` guide. s-param ~~~~~~~ When you navigate from ``/&bookmarksPage=1`` to ``/&bookmarksPage=2``, Picomet will partially render elements with ``s-param="bookmarksPage"`` attribute in that page. Navigation ---------- For navigation Picomet provides a custom Alpine.js directive named ``x-link`` .. code-block:: html
About
When navigating from a page to another page, picomet partially renders and updates the block using a common layout. Form ---- For submitting forms, Picomet provides a custom Alpine.js directive named ``x-form`` When the form is submitted, only the form element is partially rendered on the server. .. code-block:: html
{% csrf_token %}
.. code-block:: python # apps/core/views.py from django.contrib.auth import authenticate, login from django.contrib.auth.forms import AuthenticationForm from django.http import HttpRequest from picomet.decorators import template from picomet.views import render @template("Login") def login(request: HttpRequest): context = {} form = AuthenticationForm(request.user) if request.method == "POST" and not request.action: form = AuthenticationForm(request.POST) if form.is_valid(): username = form.cleaned_data.get("username") password = form.cleaned_data.get("password") user = authenticate(request, username=username, password=password) if user is not None: login(request, user) context["form"] = form return render(request, context) Head ---- Put content inside the ``head`` tag from outside. Helmet ~~~~~~ Put ``title`` and ``meta`` tags inside the ``head`` tag .. code-block:: text Home
Home page
.. warning:: Tags supported inside the ``Helmet`` tag are ``title`` and ``meta``. .. _group: Group ~~~~~ Define a place for a group of :ref:`Css ` or :ref:`Scss ` files .. code-block:: html ... ... Assets ------ .. _css: Css ~~~ .. code-block:: css /* apps/core/comets/Page.css or apps/core/assets/Page.css */ div a { color: red; } Load it in a :ref:`Group ` .. code-block:: text :emphasize-lines: 2 To use a remote css file, use the ``http`` url. .. code-block:: text .. _scss: Sass ~~~~ .. code-block:: scss // apps/core/comets/Page.scss or apps/core/assets/Page.scss div { a { color: red; } } Load it in a :ref:`Group ` .. code-block:: text :emphasize-lines: 2 .. important:: ``Sass`` requires `sass `_ and `javascript `_. Run ``npm i sass`` and ``uv add javascript`` Js ~~~ To load any javascript es module. .. code-block:: javascript /* apps/core/comets/Page.js or apps/core/assets/Page.js */ export say(value){ alert(value); } .. code-block:: text :emphasize-lines: 2 To use a remote js esm, use the ``http`` url. .. code-block:: text Ts ~~~ To load any typescript es module.. .. code-block:: typescript // apps/core/comets/Page.ts or apps/core/assets/Page.ts export say(value: string){ alert(value); } .. code-block:: text :emphasize-lines: 2 .. important:: ``Ts`` requires `esbuild `_ and `javascript `_. Run ``npm i esbuild`` and ``uv add javascript`` s-asset: ~~~~~~~~ Import any asset from ``app/assets`` or :ref:`ASSETFILES_DIRS ` .. code-block:: html Directive --------- s-context ~~~~~~~~~ Set a context for a block .. code-block:: html
{$ message $}
.. code-block:: python # apps/core/contexts.py def get_message(context): return { "message": f"hi, {context['user'].username}", } s-bind: ~~~~~~~ Bind data to an attribute .. code-block:: html {$ blog.title $} s-toggle: ~~~~~~~~~ Toggle boolean attribute .. code-block:: html s-csrf ~~~~~~ Set the ``csrftoken`` cookie for :doc:`/action` calls .. code-block:: html s-static: ~~~~~~~~~ Import any static file from ``app/static`` or ``STATICFILES_DIRS`` .. code-block:: html Component --------- Defining a component .. code-block:: text
Using the component .. code-block:: text or Children ~~~~~~~~ Defining a component with children .. code-block:: html
Using the component .. code-block:: text card body or card body Default ~~~~~~~ Setting default context props in a component .. code-block:: html
add to cart
Using the component .. code-block:: text or .. note:: Use dot(.) prefix to provide a context variable to a component. s-props ~~~~~~~ Pass normal attributes to a component .. code-block:: html .. code-block:: text Condition --------- .. code-block:: html
hi admin
hi user
please login
.. code-block:: html
hi admin
Loop ---- .. code-block:: html
{$ blog.title $}
No blogs found
Since django ORM querysets are lazy, we can also fetch a single object from the database and partially render a list item. To partially update any element in a list item, picomet requires ``s-of``, ``s-key`` and ``s-keys`` attributes. See how to use ``s-of``, ``s-key`` and ``s-keys`` in the :doc:`/action` guide. Fragment -------- Wrap multiple elements in a single conditional block. .. code-block:: html

hi

, {$ user.username $}
With ---- Pass a variable to a part of template .. code-block:: html {$ username $} Debug ----- Contents inside the ``Debug`` tag will only be parsed when ``Debug=True`` in ``settings``. .. code-block:: text Pro --- Contents inside the ``Pro`` tag will only be parsed when ``Debug=False`` in ``settings``. .. code-block:: text Tailwind -------- Currently, picomet supports tailwindcss v3. .. code-block:: text :emphasize-lines: 6 ... ... ... .. warning:: The ``Tailwind`` tag must be inside the head tag. .. important:: ``Tailwind`` requires `tailwindcss `_ and `javascript `_. Run ``npm i tailwindcss`` and ``uv add javascript`` .. note:: To minify the css bundle on production, just do ``npm i cssnano`` For tailwind to work, picomet requires 3 files. .. code-block:: css /* comets/base.tailwind.css */ @tailwind base; @tailwind components; @tailwind utilities; .. code-block:: javascript /** comets/base.tailwind.js */ /** @type {import('tailwindcss').Config} */ module.exports = { theme: {}, plugins: [], }; .. code-block:: javascript /** comets/base.postcss.js */ const tailwindcss = require("tailwindcss"); module.exports = { plugins: [tailwindcss], }; .. _cometjs: Comet.js -------- The ``picomet/comet.js`` module provides comet templates it's client side **routing**, **partial updating** etc capabilities. It also provides some utility functions to help you update your pages. go ~~~ Use this function to navigate to a page .. code-block:: typescript go(path: string, scrollToTop?: boolean): Promise .. list-table:: :header-rows: 1 * - Parameter - Default - Description * - path: string - - Path to navigate to * - scrollToTop?: boolean - false - Whether to scroll to the top of the page update ~~~~~~ Use this function to partially update a page .. code-block:: typescript update( targets: string[], url?: string, scrollToTop?: boolean ): Promise .. list-table:: :header-rows: 1 * - Parameter - Default - Description * - targets: string[] - - Targets list * - url?: string - location.toString() - Url to navigate to * - scrollToTop?: boolean - false - Whether to scroll to the top of the page call ~~~~ Use this function to call an action Learn more about ``call`` and ``actions`` in the :doc:`/action` guide. Alpinejs SSR ------------ The cool thing about picomet is it's ability to render some Alpine.js directives on the server. Although you can build simple SPA websites without any Alpinejs server side rendering, but if you want to build a SPA website with interactive and complex client side logics, then you might need to use Alpinejs SSR. The client will be able to update ui after the initial server render. .. note:: Alpine.js directives supported on the server are ``x-data``, ``x-show``, ``x-text``, ``x-bind``. Learn more about these on `alpinejs.dev `_ .. important:: To render Alpinejs syntax on the server Picomet requires `mini-racer `_. Run ``uv add mini-racer`` $S ~~~ To access any data from the python context dictionary to the server javascript context, use the ``$S`` function. .. code-block:: python # apps/core/views.py from picomet.decorators import template from picomet.views import render @template("Page") def page(request): context = {"variable": "hello world"} return render(request, context) .. code-block:: html
.. important:: The ``server`` attribute is required to know if the alpine directives inside a block should be rendered on the server. The ``client`` attribute can be used inside a ``server`` block to exclude a block from being rendered on the server. isServer ~~~~~~~~ Check if alpine is being rendered on server or client. .. code-block:: html
visible on server
visible on client
Builtins -------- Picomet provides some helpful builtins to use inside templates. safe ~~~~ Mark a string as safe for use as raw HTML. .. code-block:: html
{$ safe(blog.content) $} or
csrf_token ~~~~~~~~~~ Get the CSRF input. .. code-block:: django
{% csrf_token %}
csrf_input ~~~~~~~~~~ Get the CSRF input value. .. code-block:: html