Rustango docs
← Cookbook

Chapter 10 — Templates + static

3 tests on the Tera template surface that the admin (Chapter 8) + operator console use. No DB needed. Run with cargo test --test cookbook_chapter10_templates.

  • §10.119 tera::Tera::default() + add_raw_template + render(name, ctx)tera_template_renders_with_context
  • §10.119 t.autoescape_on(vec!["html"]) — HTML special chars in context get escaped. → tera_template_autoescapes_html
  • §10.122 {% extends %} + {% block %} template inheritance — child blocks override parent fallbacks. → tera_extends_inherits_blocks_from_base

The render_generic_fk_link helper (§10.121) is exercised live in Chapter 2's generic_fk_schema_and_content_type_lookup.

Sub-section 10.120 (Tera rendering from view handlers) and 10.123 (static-file serving) queued for Slice 10b.

Auto-mounting /static — no boilerplate (v0.29.9)

Same builder shape as with_health():

rustango::manage::Cli::new()
    .api(urls::api())
    .with_static("/static", "./assets")        // CSS, JS, images
    .with_static("/uploads", "./var/uploads")  // user-uploaded media
    .run().await

Repeating with_static mounts more than one directory. Mount order is preserved — the first registered prefix is checked first when paths overlap. Defaults from StaticFiles::new apply: Cache-Control: public, max-age=3600, dotfiles 404, symlink escapes blocked, traversal rejected.

For finer control (immutable hash-named bundles, .well-known whitelisting), keep mounting static_router directly on your own router and skip the shortcut.

Auto-mounting CSRF — for form-driven CBVs (v0.29.10)

template_views CreateView / UpdateView / DeleteView need the _csrf cookie + form field cycle wired. Same shape:

rustango::manage::Cli::new()
    .api(urls::api())
    .with_csrf()                                // default config
    .run().await

// Or with overrides for production HTTPS / cross-framework hosting:
rustango::manage::Cli::new()
    .api(urls::api())
    .with_csrf_config(rustango::forms::csrf::CsrfConfig {
        secure: true,
        ..Default::default()
    })
    .run().await

Pure JSON APIs that authenticate via Authorization: Bearer ... don't need this — with_csrf() is opt-in for that reason.