Rust 2026-06-29·Ievgenii Svyryd

Rustango CMS: system CMS w Ruście w stylu Wagtail

System zarządzania treścią zbudowany na Rustango, który przenosi drzewo stron, StreamField, snippety i renditiony obrazów z Wagtaila do Rusta - wielodostępny (multi-tenant), bezpieczny typowo i szybki.

Rustango CMS: system CMS w Ruście w stylu Wagtail

Rustango dał mi Django w Ruscie. Naturalne kolejne pytanie było tym, które programiści Django zawsze zadają, gdy modele są już na miejscu: gdzie jest Wagtail? Wagtail to system zarządzania treścią, który zamienia projekt Django w coś, czym zespół marketingowy może faktycznie zarządzać - drzewo stron, bogata ustrukturyzowana treść, biblioteka mediów oraz interfejs edytora, który uwielbiają osoby niebędące programistami.

Rustango CMS to właśnie ta warstwa dla Rustango: CMS w stylu Wagtail, który przenosi drzewo stron, StreamField, snippety i renditiony obrazów do Rusta - wielodzierżawcowy i bezpieczny typowo od góry do dołu.

Strony jako typowane modele

Każdy typ strony to struktura w Ruście, która wyprowadza zarówno Model, jak i PageType. Pola struktury stają się edytowalnym formularzem w panelu administracyjnym za pośrednictwem widżetów pól; strona żyje w drzewie (cms_page), a jej typowane dane w tabeli rozszerzeń. Deklarujesz dozwolonych rodziców i dzieci, szablon oraz ikonę - a CMS łączy routing, okruszki nawigacyjne i edytor.

#[derive(Model, PageType, Default, Serialize, Deserialize)]
#[rustango(table = "blog_post_ext", app = "blog")]
#[page_type(
    type_name = "BlogPost", template = "blog_post.html", icon = "article",
    allowed_parents(BlogIndex),
)]
pub struct BlogPost {
    #[rustango(primary_key)]
    pub id: Auto<i64>,
    #[rustango(fk = "cms_page", on = "id", unique)]
    pub page_id: i64,
    #[field(widget = RichText, label = "Intro")]
    pub intro: String,
    #[field(widget = Stream, allowed(heading, paragraph, image, code, quote))]
    pub body: Option<String>,
}

StreamField: uporządkowana treść, a nie zupa z HTML-a

Silnik bloków to najlepszy pomysł Wagtail: zamiast jednego wielkiego pola rich-text, treść jest uporządkowanym strumieniem typowanych bloków - nagłówka, akapitu, obrazu, próbki kodu, cytatu lub własnego bloku, który sam rejestrujesz. Redaktorzy komponują strony z klocków; szablony renderują każdy blok za pomocą jego własnego fragmentu. Wpis, który czytasz, jest polem StreamField.

Snippety, biblioteka multimediów i prawdziwe renditiony obrazów

Treści wielokrotnego użytku, które nie są stroną - autorzy, kategorie, branding witryny - żyją jako snippety w Bibliotece, z folderami, wyszukiwaniem, wersjami i tłumaczeniami. Obrazy przechodzą przez bibliotekę mediów z renditami na żądanie: poproś o rozmiar i format, a CMS zmieni rozmiar, przytnie do punktu ogniskowego i ponownie zakoduje do WebP lub AVIF, buforując wynik.

{# Responsywne, negocjowane pod względem formatu obrazy prosto z szablonu #}
{{ rcms_picture(media_id=hero, filters=["fill-1200x630"],
                formats=["avif", "webp"], alt=page.title) | safe }}

SEO, i18n i obsługa wielu najemców w standardzie

Każda strona niesie pola SEO i Open Graph, a pojedynczy pomocnik szablonu emituje tagi canonical, description, OG oraz Twitter-card; mapa witryny jest udostępniana automatycznie. Panel administracyjny jest w pełni zlokalizowany, treść można tłumaczyć per-locale, a - ponieważ opiera się na Rustango - pojedyncze wdrożenie obsługuje wielu najemców, z których każdy ma własną bazę danych, strony, motyw i media.

CMS to obietnica dana ludziom, którzy nie są inżynierami: że mogą zmieniać stronę bez zakładania zgłoszenia. Rustango CMS dotrzymuje tej obietnicy w języku, który zwykle zapomina, że tacy ludzie w ogóle istnieją.

Dokąd to zmierza

Rustango CMS już teraz obsługuje tego bloga - drzewo stron, treści StreamField, generowane obrazy okładek, tagi SEO i treści per-lokalizacja - wszystko to z niego pochodzi. Jest to dowód na to, że Rust nie musi oznaczać rezygnacji z doświadczenia edytora, które sprawiło, że Django i Wagtail były tak produktywne. Możesz mieć zarówno ergonomię, jak i gwarancje.

Kontakt →