Django CMS vs Wagtail vs Plone:
Which Python CMS in 2026?

Three mature Python CMS platforms, three very different philosophies. After building production systems on all of them, here's the honest comparison — including who should use each one and who should run in the opposite direction.

If you've already ruled out WordPress and PHP — good decision — you'll quickly find yourself looking at the Python ecosystem, where three platforms dominate the conversation: Wagtail, Django CMS, and Plone. They're all open source, all Python, and all capable of running a real production website. Beyond that, the similarities thin out quickly.

We've built client projects on all three. We've also migrated teams off all three. This post is what we tell prospective clients when they ask us which one to pick, based on what we've actually encountered in the field rather than what the marketing sites say.

Origins and philosophy

Understanding why each platform was built explains a lot about where they excel and where they frustrate.

Plone is the oldest, dating to 2001. It was built on Zope and ZODB — a completely different architectural lineage from Django. Plone was a genuine enterprise CMS a decade before "enterprise CMS" was a common phrase, and it was used by governments, universities, and large organisations who needed workflow, permissions, and content governance that nothing else at the time could match. That heritage shows: Plone's security model and permission system remain world-class. Its technology choices, however, are increasingly exotic by modern standards.

Django CMS appeared in 2009 as a natural companion to the rapidly growing Django ecosystem. Its defining idea is the placeholder: a region on a page that editors can fill with plugins (rich text, images, forms, custom blocks) via an in-page drag-and-drop interface. The goal was to give front-end editors a WYSIWYG experience while developers retained control of the page structure in code. It's a clean philosophy, and for its original use case it still works well.

Wagtail arrived in 2014, built by the digital agency Torchbox initially for the Royal College of Art's website, then open-sourced. It learned from what Django CMS got right and wrong. Rather than in-page editing, Wagtail centres the editorial experience in a clean admin interface. Rather than a plugin-and-placeholder model, Wagtail uses StreamField — a structured, typed approach to page content that produces real data rather than serialised HTML blobs. It hit maturity fast and is now maintained by a foundation with corporate sponsors including Google, Torchbox, and several universities.

Content modelling: where the real differences live

How each platform models content is the single most important factor for most projects, because the content model is the thing you live with forever. Getting it wrong means painful migrations later.

Django CMS uses placeholders — named slots in a template where plugins are dropped. Each plugin is a Django model. It's flexible in the sense that you can put almost anything anywhere, but it means your content is inherently tied to its presentation. If you want to display the same content in a different context — an API response, a PDF, a mobile app — you're fighting the architecture rather than working with it. The data is stored per-plugin-instance, not as a coherent typed document.

Wagtail models content as Django models with a StreamField for the flexible body. The critical difference is that StreamField blocks are typed Python classes — not HTML fragments. A QuoteBlock stores a quote and an attribution separately; a SpeakerBlock stores a name, bio, and photo as distinct fields. This means you can query, filter, and render the content in any format, not just the original template.

class CaseStudyPage(Page):
    client_name  = models.CharField(max_length=200)
    sector       = models.ForeignKey('taxonomy.Sector', on_delete=models.PROTECT)
    published_at = models.DateField()

    body = StreamField([
        ('intro',     blocks.RichTextBlock()),
        ('challenge', blocks.RichTextBlock()),
        ('outcome',   OutcomeBlock()),   # custom StructBlock
        ('quote',     PullQuoteBlock()),
        ('metric',    MetricRowBlock()), # e.g. "40% increase in…"
    ])

    content_panels = Page.content_panels + [
        FieldPanel('client_name'),
        FieldPanel('sector'),
        FieldPanel('body'),
    ]

This produces a clean JSON representation in the database that's queryable and renderable independently of any template.

Plone uses Dexterity content types — Python classes that define fields using the zope.schema library. It's typed, it's validated, and for complex document-centric content it's genuinely powerful. The issue is the underlying object database (ZODB) rather than a relational database, which makes ad-hoc querying and analytics significantly harder. RelStorage — available since Plone 4 — provides a PostgreSQL or Oracle backend as an alternative to ZODB, which helps, but it's still not a first-class relational model.

Content modelling verdict Wagtail's StreamField is the most developer-ergonomic and output-format-agnostic. Django CMS's plugin model works for simple page-building but doesn't scale to complex structured content. Plone's Dexterity is technically sound but comes with the Zope overhead.

Editorial experience

This is often the question clients ask first, because their non-technical editorial teams are the ones using the CMS every day.

Django CMS's in-page editing is its most distinctive feature. Editors click directly on page content to edit it in place, adding and rearranging plugins via a toolbar overlaid on the live page. For marketing teams who want a visual relationship between editing and publishing, this is genuinely compelling. The downside is that the experience degrades on complex layouts, the toolbar interface feels dated in 2026, and the approach makes the admin interface feel like a secondary afterthought rather than a proper editorial workspace.

Wagtail's editorial interface is a clean, dedicated admin. There's no in-page editing — you work in a panel-based form that's designed to match your content model. This takes a brief adjustment for editors used to WYSIWYG tools, but in our experience they consistently prefer it within weeks. The reason is reliability: the form is always predictable, the revision history is accessible, and the workflow features (moderation, scheduled publishing, content locking) are properly surfaced rather than hidden in menus.

Wagtail 6 added a redesigned "slim sidebar" admin and improved image/document management. The block-level chooser interface for StreamField has improved significantly. It's genuinely pleasant to use.

Plone has a split personality. The classic Plone interface is from another era: it works, but feels heavy and unfamiliar to anyone who grew up on modern web UIs. Plone 6's new Volto frontend — a React-based editorial interface — is a complete overhaul that looks modern and performs well. The catch is that Volto is effectively a separate project that Plone now depends on, which adds frontend complexity. Teams choosing Plone for the editorial UX alone face a significant React dependency on top of an already complex backend.

Editorial UX verdict Wagtail for teams who want a reliable, structured editorial workflow. Django CMS for teams who specifically need in-page WYSIWYG editing. Plone 6 with Volto is promising but requires React expertise to maintain and extend.

Headless and API-first capability

Decoupled architectures — where the CMS manages content and exposes an API that a separate frontend consumes — are increasingly the default for anything beyond a simple brochure site. All three platforms support headless operation, but the quality of the experience varies considerably.

Wagtail has first-class headless support via the Wagtail API v2, which exposes all page types as JSON endpoints. The wagtail-grapple package adds a full GraphQL API. Critically, preview works headlessly — your Next.js frontend can preview unpublished Wagtail content using Wagtail's preview tokens. This is the detail that most headless CMS setups get wrong, and Wagtail gets it right. ISR (Incremental Static Regeneration) with Next.js is well-documented and works reliably.

# Declare which fields the Wagtail API v2 exposes — on the model itself
from wagtail.api import APIField

class CaseStudyPage(Page):
    # ... field definitions as above ...

    # StreamField is automatically serialised to JSON by the API
    api_fields = [
        APIField('client_name'),
        APIField('sector'),
        APIField('published_at'),
        APIField('body'),  # blocks serialised as typed JSON objects
    ]

Django CMS's headless story is weaker. Because content lives in plugin instances rather than typed model fields, serialising it into a clean API response is non-trivial. The djangocms-rest package exists and is improving, but you're working against the architecture rather than with it. If headless is a requirement, Django CMS requires considerably more custom engineering to produce a clean API layer.

Plone ships with a mature REST API — plone.restapi — that's well-designed and well-maintained. It predates Volto and is what Volto itself uses to communicate with the backend. For headless Plone with a custom frontend, the API layer is one of the platform's genuine strengths. The difficulty is on the other side: the Plone backend is complex to operate, and teams choosing Plone purely for its API — ignoring the admin interface — are paying a significant complexity tax for what they're getting.

Headless verdict Wagtail is the clear choice for headless or hybrid architectures. Plone's REST API is solid but the platform is over-specified for API-only use. Django CMS is the weakest option for decoupled frontends.

Security

Security is where the three platforms diverge most sharply from their shared Python foundation.

Wagtail and Django CMS inherit Django's baseline protections: parameterised queries preventing SQL injection, CSRF tokens, and XSS-safe template engines. Plone's Zope foundation provides CSRF protection and XSS-safe templating; its default ZODB store is not SQL-based at all, so SQL injection isn't a relevant attack vector — though with RelStorage (PostgreSQL) it inherits standard SQL protections. But the baseline is just the baseline.

Plone has the strongest security track record of the three, full stop. Its fine-grained permissions system — roles, groups, workflows, and object-level permissions — is more sophisticated than anything Django ships with by default. Plone is used by government agencies and financial institutions where security is non-negotiable. The Plone Security Team has a serious CVE process and responds quickly. If your threat model requires formal access controls at the content object level — who can view, edit, submit, approve, and publish each individual piece of content independently — Plone is in a different league.

Wagtail has a clean security posture: a small codebase, a well-maintained dependency graph, an active security team, and Django's underlying protections. Its page-level permission system (view restrictions, collection permissions, workflow groups) handles the majority of real-world access control requirements. It's not Plone's enterprise-grade permissions engine, but it's more than sufficient for most organisations.

Django CMS is similarly sound at the Django level. Its plugin architecture does create a wider attack surface than Wagtail — more third-party packages in the dependency chain — but this is manageable with good dependency hygiene.

Security verdict Plone for organisations that need fine-grained, object-level content governance. Wagtail and Django CMS are secure platforms for the vast majority of use cases. Plone's security model is overkill — and expensive to maintain — unless you actually need it.

Performance and scalability

Raw performance depends heavily on infrastructure and implementation quality, but the platforms have meaningfully different scaling characteristics.

Wagtail is a Django application and benefits from everything the Django ecosystem offers: database connection pooling, Django's built-in cache framework backed by Redis or Memcached, Celery for async tasks, and a clean path to horizontal scaling. Wagtail's page serving is lightweight — a cached page response is fast. The headless architecture allows full static generation, which eliminates server-side rendering cost entirely for most visitors.

Django CMS performs similarly to Wagtail at the Django layer. The placeholder/plugin model can generate more database queries per page than a comparable Wagtail page — each plugin requires its own query — which can become a performance concern on plugin-heavy pages without careful caching configuration. The django-cms toolbar adds JavaScript overhead to every page for authenticated users.

Plone's performance story is its most significant weakness for modern workloads. The Zope application server and ZODB object database have different scaling characteristics from a PostgreSQL-backed Django app. Plone has always required careful tuning — Zope's ZEO clustering, Varnish caching, load balancers — to handle real traffic. Plone 6 with RelStorage (PostgreSQL backend) improves things considerably, but the operational knowledge required to run a high-traffic Plone site is specialised and increasingly rare.

Community, ecosystem and longevity

The health of the community around a CMS matters as much as its current feature set — especially for a platform you'll be maintaining in three years.

Wagtail is the fastest-growing of the three by any metric: GitHub stars (currently ~20k), PyPI downloads, job postings, and conference talks. The Wagtail core team is active, releases are regular and well-managed, and the Wagtail Space conferences attract a genuinely broad developer community. Corporate investment from Google and Torchbox provides long-term sustainability. The package ecosystem — wagtailmenus, wagtail-grapple, wagtail-storages, wagtail-cache, and dozens more — is healthy and maintained.

Django CMS remains active, backed primarily by Divio (the company that built it). The community is smaller than Wagtail's and the pace of core development has slowed relative to 2015–2020. It remains a stable, maintained platform — it's not going anywhere — but it's not where the energy in the Python CMS world currently sits.

Plone is the most complex trajectory of the three. The community is small but deeply committed — people who use Plone tend to really use Plone, often in large organisations that have built significant institutional knowledge around it. The shift to Volto (React) as the default frontend in Plone 6 was a bold architectural move that split the community somewhat. There are far fewer Python developers with current Plone expertise than there were a decade ago, which has direct implications for hiring and long-term maintenance costs.

Developer experience

How painful is it to build and extend each platform?

Wagtail is a joy to extend. It follows Django conventions so closely that any Django developer can pick it up quickly. The hooks system for customising the admin, the documented StreamField block API, and the clear page model inheritance all feel natural. The official documentation is excellent. Onboarding a new developer onto a Wagtail project is straightforward.

Django CMS is reasonably approachable for Django developers. Writing a custom plugin is well-documented and follows a consistent pattern. The placeholder and toolbar JavaScript API is dated and can be fidgety. The configuration surface area is larger than Wagtail's — there are more settings to understand before you have a working site.

Plone has the steepest learning curve by a significant margin. Even experienced Django developers face weeks of orientation before they're productive on a Plone codebase. Zope's component architecture (adapters, utilities, interfaces, named views) is a different mental model from standard Django class-based views. ZCML configuration files. Zope's traversal mechanism. The GenericSetup profiles system. These are all learnable, but they represent a substantial up-front investment that has no transferable value outside the Plone/Zope world.

Developer experience verdict Wagtail is the most accessible for Django developers and produces the most maintainable codebases. Django CMS is workable. Plone requires specialist knowledge that's becoming genuinely hard to hire for.

When to choose each platform

Choose Wagtail when:

  • Your content has genuine structure — distinct typed fields, not just a body editor
  • You need or may need a headless or hybrid architecture (Next.js, Nuxt, mobile app)
  • You want a modern editorial interface your team will actually enjoy using
  • You need workflow, revision history, and scheduled publishing as first-class features
  • Your developers know Django, or you want to hire developers who do
  • You want a large, active community and long-term platform confidence
  • Multi-site from a single install is a requirement

Choose Django CMS when:

  • In-page editing is a hard requirement — editors insist on seeing their changes in context
  • You're building a marketing site or landing-page-heavy site where the page-builder model fits naturally
  • The content model is relatively simple (mostly rich text, images, and straightforward custom blocks)
  • You have an existing Django CMS codebase to maintain or extend
  • You don't anticipate needing a headless or API layer

Choose Plone when:

  • Fine-grained, object-level content permissions are a genuine requirement — not just "nice to have"
  • You're in a government, academic, or regulated-industry context where Plone's compliance track record matters
  • You already have Plone expertise in-house and are extending an existing installation
  • The content governance model (workflow states, transitions, role-based access per document) directly maps to your organisation's real processes
  • You're prepared to invest in specialist Plone developers, or have them already

Our recommendation for new projects in 2026

For the overwhelming majority of new Python CMS projects in 2026, Wagtail is the right choice. It has the healthiest community, the most modern architecture, the best headless story, and the most maintainable developer experience. It handles 90% of content management requirements well, and the 10% it doesn't handle natively can be addressed with well-maintained third-party packages or custom StreamField blocks.

We'd recommend Django CMS only when in-page editing is a genuine hard requirement, or when a team has existing expertise and a codebase to extend. For new projects, Wagtail's architectural advantages compound over time — Django CMS's plugin model creates constraints that become painful as content requirements grow.

We'd recommend Plone in a narrow set of situations: existing Plone installations with in-house expertise, or organisations where the enterprise-grade permissions and workflow model directly matches their governance requirements. For everyone else, Plone's operational complexity, specialist hiring requirements, and Zope learning curve are costs that Wagtail simply doesn't impose.

If you're migrating away from an existing platform to any of these three, the content model migration is almost always the hardest part — not the platform configuration. That's where we'd want to start the conversation.

Work with us

Choosing a Python CMS for your project?

We've built production systems on all three platforms. Tell us about your content model and team, and we'll give you a straight answer about which one fits.