rustango 0.40.0

Django-shaped batteries-included web framework for Rust: ORM + migrations + auto-admin + multi-tenancy + audit log + auth (sessions, JWT, OAuth2/OIDC, HMAC) + APIs (ViewSet, OpenAPI auto-derive, JSON:API) + jobs (in-mem + Postgres) + email + media (S3 / R2 / B2 / MinIO + presigned uploads + collections + tags) + production middleware (CSRF, CSP, rate-limiting, compression, idempotency, etc.).
Documentation
{% extends "base.html" %}
{% block title %}{{ title }} — rustango admin{% endblock title %}
{% block body %}
<nav class="breadcrumb" aria-label="breadcrumb">
  <ol>
    <li><a href="{{ admin_prefix }}/">{{ admin_title }}</a></li>
    <li><a href="{{ admin_prefix }}/{{ model.table }}">{{ model.name }}</a></li>
    {% if edit_pk %}<li><a href="{{ admin_prefix }}/{{ model.table }}/{{ edit_pk }}">#{{ edit_pk }}</a></li>{% endif %}
    <li><strong>{{ title }}</strong></li>
  </ol>
</nav>
<h1>{{ title }}</h1>
{% if error %}
<p class="error">{{ error }}</p>
{% endif %}
<form method="post" action="{{ action }}">
{% for set in fieldsets %}
  <fieldset class="form-fieldset">
    {% if set.title %}<legend>{{ set.title }}</legend>{% endif %}
    <table>
    {% for row in set.rows %}
      <tr>
        <th><label for="{{ row.label }}">{{ row.label }}{{ row.extra | safe }}</label></th>
        <td>
          {{ row.input | safe }}
          {# Django-shape help text rendered as a muted caption under
             the input. `None` (no `#[rustango(help_text = "…")]`) is
             falsy in Tera so nothing renders. #}
          {% if row.help_text %}<p class="help-text">{{ row.help_text }}</p>{% endif %}
        </td>
      </tr>
    {% endfor %}
    </table>
  </fieldset>
{% endfor %}
{# #50 slice 2 — editable inline panels. Mirrors the read-only
   layout in `_inline_panels.html` but each cell renders an <input>
   and each panel carries the FormSet management form. #}
{% if inline_form_panels and inline_form_panels | length > 0 %}
  {% for panel in inline_form_panels %}
    <section class="admin-inline-form admin-inline-form-{{ panel.kind }}"
             data-child-table="{{ panel.child_table }}">
      <h2>{{ panel.label }}</h2>
      <input type="hidden" name="{{ panel.prefix }}-TOTAL_FORMS" value="{{ panel.total_forms }}">
      <input type="hidden" name="{{ panel.prefix }}-INITIAL_FORMS" value="{{ panel.initial_forms }}">
      <input type="hidden" name="{{ panel.prefix }}-MAX_NUM_FORMS"
             value="{% if panel.max_num %}{{ panel.max_num }}{% endif %}">
      {% if panel.kind == "tabular" %}
        <table class="inline-form-table">
          <thead>
            <tr>
              {% for label in panel.field_labels %}<th>{{ label }}</th>{% endfor %}
            </tr>
          </thead>
          <tbody>
            {% for row in panel.rows %}
              <tr>
                {% for cell in row.cells %}<td>{{ cell.input_html | safe }}</td>{% endfor %}
                {% if row.pk %}<td>{{ row.delete_input_html | safe }}{{ row.hidden_pk | safe }}</td>{% endif %}
                {% if not row.pk and panel.initial_forms > 0 %}<td></td>{% endif %}
              </tr>
            {% endfor %}
          </tbody>
        </table>
      {% else %}
        {# stacked #}
        {% for row in panel.rows %}
          <fieldset class="inline-form-stacked">
            {% if row.pk %}
              <legend>#{{ row.pk }}</legend>
              {{ row.hidden_pk | safe }}
            {% else %}
              <legend>New</legend>
            {% endif %}
            <dl>
              {% for cell in row.cells %}
                <dt>{{ cell.label }}</dt>
                <dd>{{ cell.input_html | safe }}</dd>
              {% endfor %}
              {% if row.pk %}
                <dt>Delete</dt>
                <dd>{{ row.delete_input_html | safe }}</dd>
              {% endif %}
            </dl>
          </fieldset>
        {% endfor %}
      {% endif %}
    </section>
  {% endfor %}
{% endif %}
  <div class="action-row form-submit-row">
    <button type="submit" name="_save" class="btn btn-primary">Save</button>
    <button type="submit" name="_continue" class="btn btn-secondary">Save and continue editing</button>
    <button type="submit" name="_addanother" class="btn btn-secondary">Save and add another</button>
  </div>
</form>
{% endblock body %}