167 comments

[ 4.1 ms ] story [ 226 ms ] thread
How come Plain looks so much like Django?
It's a fork of Django. It says clearly on the docs.
Third sentence on the page.

Third sentence.

I usually click through to the repo, and it isn't in the README for some reason. I don't blame GP for missing it. https://github.com/dropseed/plain

Of course, GP would've noticed it's like Django on the web page. The screenshot containing Django-like example code is above the fold, though - the Django mention is below the fold.

This looks pretty cool! Would be nice to see an integration with Tetra
Tbh why should I use this over Django? Less docs and knowledge around it. Less maintainers. Idk seems like a business risk to invest real time in it for me
I feel the About page would be better for the audience who clearly already knows Django: https://plainframework.com/about/
Thanks! This helps me understand his motivations for forking. I still don’t have a clear sense of how Plain is different or what the different approach is
I also found this but I have to say I don’t really understand still.

I’ve used flask on projects but I’ve never started a project in flask and then migrated it to Django - I’m not really sure why you would do this. If I think a project would need admin panel or other Django features, I just make it in Django. That’s usually a pretty easy call to make when you start.

It seems like the fork is largely political? E.g. he just doesn’t like the way the mailing list is run, which is totally valid. I just don’t know what architecture he is building or what is different. I wish him well, though!

https://plainframework.com/faqs/

> Plain is a fork of Django

Why. This makes me sad. Plain looks great, but Django's strength is its maturity and amazing, enduring community built on contributions from thousands. Forking it will at best split contributions and mean infrequent merges, and at worst means Plain users lose out on Django improvements and Django users lose out on Plain patches.

It seems like Plain could be just a set of Django packages known to work together, and perhaps a new wrapper script replacing `django-admin`, but instead it appears it is a true fork.

Plain basically looks great. I love Django, and this is a long list of things that I'd need on top of Django anyway. Would I use a framework on top of a framework like this? I'm not sure. I just wish it was built in a way that contributed to the Django community instead of one that divides it.

I don't get it, if you don't like it, don't use it, but why feel sad about it? Someone is developing something new and giving it out for free.
They aren’t sad about being forced to use something. They are expressing their opinion about split efforts in the Django community.
Exactly. I look at things like this and contrast with what friends like Adam Johnson do[0] with their community contributions. Adam has many Django packages, along with many other non-Django Python packages. Crucially though, they're not forks that reduce the focus of the community, they're contributions that increase what the community can do collectively.

[0]: https://github.com/adamchainz?tab=repositories&q=django-&typ...

I think it's perfectly fine to have split effort when you have differing views and goals on something. Developing two exact same things with same goal and purpose might not be fruitful, but variety and options don't usually hurt
The author actually addresses all of those points in the about page https://plainframework.com/about/
I understand the frustrating with Django progress (and, to be honest, I would like for Django to more agressively upstream stuff).

I'm curious about what he would want to get into Django that feels like he couldn't though. Since this _is_ a fork of Django, he's still gonna hit a lot of issues that people wanting to improve Django hit.

Backwards compat is an issue, but "all of this code within the library is built off of existing assumptions" is _also_ an issue.

If all the improvements could be third party packages, just making plain be a big third party omnipackage that also has a helper to "fix" settings feels like it would go a long way.

The author discusses these points in the about page, but for me, does not sufficiently address them.

My experience of contributing to Django does not match theirs, and I don't feel this page sufficiently justifies this being a fork. In fact it actually makes me suspect that Plain will/has diverged enough that it won't be able to pull in changes from Django. As a user this would concern me, as Django ships meaningful changes regularly, as well as having a mature approach to security disclosures.

I have disclosed vulnerabilities in Django and they were handled very well and quickly. I actually went to see if Plain was vulnerable to the issue I disclosed, but my issue was around the memcached integration, and it seems Plain has completely removed all caching (except from a database-backed cache), making it in one way less batteries-included than regular Django. This puzzles me, for a project that is all about including more batteries, and as a potential user would lead me to further question the project.

Upstreaming to Django becomes very hard because he's moved stuff around. Also, switching to plain just to try it out becomes super hard because of this same thing. The idea of having a faster moving fork makes sense, but this isn't it.
Agreed. The about page also says that the plan is to update Plain to include new Django changes, but that would also be hard.

Django has a "contrib" package. I could see a fork with a fast moving contrib directory, or even just the Django project doing that with an explicit call-out for that package having a different set of breaking change expectations. A bunch of features started in contrib and graduated out of it over time, would be nice to keep that going.

It'd have been better to see some concrete examples of things he could only achieve with a fork
Has no mention of it being a fork of Django in the README. https://github.com/dropseed/plain

I guess the author didn't think credit was due: https://plainframework.com/about/#credit-where-credits-due

Right up near the top of the front page: "Plain is a fork of Django, bringing new ideas to established patterns in the Python landscape. Build a new business, an internal tool, or something for yourself."

It's clearly a minimal readme, a tiny bit of frontmatter and a feature list. I see no reason to tar them for not including that everywhere.

At this point, seems like the server is mostly a data access layer spitting out JSON for JavaScript, Java and Swift clients.
That is the trend, but just because something is popular doesn't make it optimal. Developers are also excited about marginal gains from LLMs. The reality though is that most of those same teams could 2x their productivity by going back to a more retro stack, without losing quality, and also lowering costs in hosting and devops. The move to multi-service was for scale, but somewhere along the line people forgot to measure whether they needed that complexity at all.
Don't forget Flutter :-)

But seriously there has been a movement back towards rending on the server-side. This underpinnings of Next.JS and HTMX

Django's origins in content probably made it hopelessly "thick" in today's world which on the server is mostly just taking in a spitting out JSON.
I think there’s a counter movement here, whether it’s Hotwire/Turbo in Ruby or the Django community adopting htmx.
This is a valid debate to be had (and I disagree), but I don't think Plain is changing any of that. It's roughly similar in structure.
An app fixes that bettter than a fork. E.g: django ninja.
I think Django is good enough to eat its babies but not good enough to evolve smoothly. It's been mentioned already but the task queue situation and the REST situation which are handled by Celery and DRF are not very ergonomic and well integrated than a default well designed system builtin into the framework like Phoenix gives you out of the box.

My main complaint is having used something like Wagtail (which builds on and extends Django) to quickly spin up a CRM is that if you come along years later to update a project you find the path very painful since Wagtail and Django updates diverge and you are left to your own bad choice of picking the path of least resistance. I'd rather just spend time building something in Django and then maintain that long term than try to keep two out of sync projects in sync while building on top of that mess.

I'm a Django user and I'm happy to see a fork because while Django is mature, it's also stagnating because the project isn't able to break things by introducing new features.

I don't think Plain will replace Django anytime soon but it might help guide decisions.

Plain being backed by a for-profit company is also great because projects like Django could use more marketing. Vercel figured this out a long time ago.

I'm not sure Django is stagnating. It recently added task queues as a concept, which was desperately needed, but there's not a lot else that's truly necessary. The important thing for me here is that Django has a very mature extension model – apps, packages, backends, etc – that mean that most functionality can and should be implemented as separate packages that plug in well. Almost all the Plain features are either built-in to Django already, or would do better as separate packages, and would likely receive push-back from being included in Django for that reason. Is that stagnation? To me that's maturity, and something I appreciate in a framework.
In fact Laravel is constantly lending stuff from Django and RoR. Like model attributes.
> It recently added task queues as a concept

It took me a while to find any information on this, so for others:

https://forum.djangoproject.com/t/django-tasks-bringing-back...

https://github.com/django/deps/blob/main/accepted/0014-backg...

It's definitely stagnating. Compare how easy it was to add the admin interface when the framework was still young, vs adding the background workers feature you mentioned.

A lot more testing needs to be done before adding anything. The community should welcome projects like Plain, that can move fast and break things, which in turn might inspire Django.

Weird to see “it’s like Vercel” as a virtue.

The times for-profit dev tooling has worked, it’s almost always when the profit is a means to providing value (e.g. Jetbrains), but that’s very rare.

For profit is generally a stronger signal of an impending rug pull than longevity.

It definitly could be a set of different libs, apps, config sets and command. I've seen no feature you can't provide that way.

The fork is a bad take here as it will be super costly to maintain for no gain.

Now, if you were to change a deep layer like the ORM, that would justify it. But I don't see it here.

But let's not be negative here, someone wants to spend time, energy and resources to explore innovation for a great legacy foss project.

This is good news.

Because late stage open source capitalism is now bypassing the messy business of building something popular and going straight open-core/vercel-model on the back of already popular libraries and frameworks. The emerging playbook is:

- Find successful open source project - Fork with "reasons" - Pour VC into helpful features, great docs, DX and evangelism - Run the Vercel playbook

We're gonna see a lot more of this.

- Create a marketplace with pro (payed) version of all packages
Interesting. Got more examples of this playbook?
I can think of:

  Sqlite -> Turso  
  PostgreSQL -> Neon  
  Chromium -> Arc browser
not exactly fork, but aimed at riding popularity of an already-established thing:

  Nodejs -> Bun
IRC -> Discord
IRC -> Slack

Early slack actually supported being used by 3rd party IRC clients

>- Find successful open source project - Fork with "reasons"

To be fair, Vercel did not 'find&fork' Next.JS, they are the authors of the framework.

they probably intend its relation to React.
“late stage open source capitalism”

Considering the GNU manifesto is from 1985 I guess we’ve gone through multiple stages quickly. What were they?

I've successfully replaced django.contrib.auth multiple times. It it not easy, but it is not too hard either. Honestly, everything else they do could be a regular Django app. Looks to me like forking a big project became a marketing move rather than technology necessity.
100% agree. Let's hope they maintain compatibility so stuff developed for Plain works with Django.
In the FAQ they said that extensions would not be compatible
Yes. This is a bad idea.

A better way to do this is as a cookiecutter template. Go ahead and include everything you need as INSTALLED_APPS. Auth is pluggable, middleware is configurable, his support module is a classic use case for a pluggable app... Include pytest and Python-Allauth with sane defaults.

I'm struggling to see anything that wouldn't work better—benefiting from all the good work in the Jazzband universe and automatically getting the upstream security upgrades—without a fork.

(comment deleted)
I really don't understand why every time a big project is forked People are so upset. IMO, one of the great things about open source software is that a fork is possible. Maybe it will go nowhere, maybe some good ideas will be fed back to Django, maybe it will become the new standard. Most of the time , we will end up with better software overall.
No one is upset.
The top comment literally starts with „this makes me sad.“
(comment deleted)
As a guy with a lot of hours into Django, I will echo that I don’t quite understand the “why” here.

I think there’s a number of areas where Django falls a bit short and other web frameworks excel. For example, task workers are not first class citizens and require Celery or another task manager. REST APIs are a similar situation. Celery and Django REST are great, but they do feel a little ham handed. I’ve seen other frameworks handle this in ways that really seem to work great.

I guess auth is prioritized here? But I actually like the barebones Django auth and find it useful in many situations where I don’t need full OAuth.

I’m not saying this isn’t needed and it looks cool and nice - but for the use cases where I’ve struggled with Django, it seems like this would actually increase complexity, as the 3rd party ecosystem would obviously not be robust.

It looks like the author has a perfectly good workflow and use case for this, but it’s not clear from the homepage or the “about” page linked elsewhere in the comments exactly what this is for

Django have been by bread and butter work for a long time, and I do not really get the point of this.

There are bits I agree with but nothing like enough to be worth losing compatibility with third party packages.

I'm still waiting for a truly cross-platform framework using Python that builds natively and beautifully on ANY platform - from the Apple IIGS to MacOS M4 to web to Windows to Linux. With a click of a button. So I wasn't pleased to read how limited this framework is. Still waiting, I guess?
I’m not sure that happens in any language, but my sense is that it probably will not happen in Python.
yeah - suggest you look at https://harcstack.org - raku is an open goal for doing new stuff like this
Looks interesting! I will take a look. I think Zig and Zap look pretty cool too.

Seems like compiling to and deploying to Apple 2 is still a stretch

Django still lacks typing support. Does Plain improve on this at all? I didn't see typing mentioned in the docs..
If you want strong typing in a web framework, why wouldn’t you just use a language with strong typing?
Because people want strong typing, but also want other things. It's possible to want multiple things, and bemoan that whwat you use is still missing things you want.

Concretely, Django is way more usable than basically any web framework from the "strongly typed" space, especially for "dumb" CRUD stuff. And you're not hit with making decisions about how to do a bunch of things (though you can swap out mostly any part of Django for something else if you want to).

That makes sense! My personal feeling is that a web framework is not the right place in the stack to introduce typing.

There’s also probably an argument to be made that part of the reason for Django’s “batteries included” success and wide adoption is in part because it is built on an untyped language.

I get wanting both, though.

In my own work, I find most of the benefit of static types to be ensuring correctness at compile time, so I just don’t expect that in Python. I also have just not lost that many cycles to type errors. But I know some have strong preferences here.

The main benefit in the developer workflow is autocompletion and feature discovery in the IDE. Having to guess which methods and properties an object exposes, or jump to the documentation every time, is really frustrating. Compare that to e.g. Typescript, which excels in this area.
Yeah, exactly this. Django is just brilliant and sometimes I'd like to use it with typing.
if you seek strong typing, but not all the time, in a language suited to web dev suggest you take a look at raku … for example https://harcstack.org
Type annotations have nothing to do with whether a language is weakly or strongly typed
I can’t use something else, since my job is working with Python, and type linting is a reasonable alternative in this case.
Python is a strongly typed language. But Python is not statically typed; Python is dynamically typed, with optional type declarations which enables static type checking (by third-party software).
Relatedly, in case it's useful, the django-stubs package provides mypy compatible type stubs for Django:

https://github.com/typeddjango/django-stubs

While it's truly a great ongoing effort and I am grateful to all the contributors, it's not nearly complete. You may think you're using the correct type until, surprise, you are not.
I personally like lack of typing which makes things MUCH easier. I'm curious the benefits of typing?
Trying to run the starter kit, it tries to download mkcert, but that download fails with a ssl.SSLCertVerificationError... how ironic :)

brew install mkcert fixes this.

Also, a starter kit that asks for my password right away is a bit too intrusive for me:

    Downloads/new-project [master {origin/master}|]: uv run plain dev
    Generating SSL certificates for app.localhost...
    Created a new local CA 
    Note: the local CA is not installed in the system trust store.
    Note: the local CA is not installed in the Firefox trust store.
    Run "mkcert -install" for certificates to be trusted automatically 

    Created a new certificate valid for the following names 
     - "app.localhost"

    The certificate is at "/Users/me/Downloads/new-project/.plain/dev/certs/app.localhost-cert.pem" and the key at "/Users/me/Downloads/new-project/.plain/dev/certs/app.localhost-key.pem" 

    It will expire on 29 June 2027 

    Adding app.localhost to /etc/hosts file. You may be prompted for your password.

    Password:
I generally don't like to rely on ssl for development anyway. Make it optional maybe ?
I don't know if Plain has a chance to succeed but I understand why it is a fork. Django leadership haven't been able to move Django forward outside of its old paradigms and every attempt, be it a fork or third-party app, counts.
Can you elaborate on this? What paradigms do you think are outdated?

Generally speaking, I think Django has lagged a bit behind other frameworks. However, the continued advantage of being Python driven has left it useful in my book when working with Python data utilities in the back end. What’s your perspective here?

Not the previous poster, but my biggest gripe with Django is all the silent failures. It was a bad idea 20 years ago, it's a bad idea now, it's just a very very bad idea.
It would be a long list. I will post some examples but you can summarize it as "Django is not ideal choice to build a modern SAAS applications" and "Django developer experience is lacking".

1. REST/HTTP API building needs to be built in for a batteries included framework. In 2025 it is already so so late. REST Framework is "finished" and even if it wasn't the third-party extensions including Ninja feel alien. They need their own routing (why?), their own serialization, have their own extensions or features (rate limiting) that should just be more generic.

2. Python optional typing is always rejected or postponed. Same with any effort to just make starting a project easier because Django doesn't want to ship any dependencies even if it means better outcomes. Recent discussions about shortening django-admin to django can give you enough information about how community decision making is difficult for bringing new (and great) ideas in.

3. Better approach for template components. Django should have good primitives so that people can built UI libraries on top. You can see 10+ third-party packages now but I think it should be included batteries.

4. Authorization. The whole authorization framework assumes that you run a website like the original newspaper. It absolutely cannot work with a multi-tenant SAAS apps that everyone wants to build.

5. Not being able to correct past mistakes or outdated stuff. For example still Django's user model is bad. I really don't understand how something so important cannot be fixed.

(comment deleted)
Regarding #3, you can already do this with Jinja2 template functions perfectly well. You can also do it with template tags, but it isnt as nice.

100% agree with #5, the diaspora of Django's community, dev process, and lack of a single decision maker when consensus isn't quickly reached, makes it virtually impossible to correct past mistakes.

> Regarding #3, you can already do this with Jinja2 template functions perfectly well. You can also do it with template tags, but it isnt as nice.

This is exactly the problem tho. Every Django solution is "install this thing that replaces or adds a component that should be standard". People adopt frameworks to help them stay on track, not because they want to immediately install 5-10 packages just to correct the framework. Not to mention this just creates a big split when every project will be very different.

Active Record leads to a big ball of mud.

A lot pythonistas who only know Django have no idea that there other ways of building web apps.

Is there something like this available for Ts/js folks? This looks quite complete.
This feels right and wrong at the same time.

It’s right (as explained in the about):

- to like Django and all the 1000s of contributions

- to be frustrated by its limits & to want to do more

- to fork and rearchitect if you can’t get there by debate

- that people may like it and come along or the ride

- in many of the features and design points

- to embrace HTMX

It’s wrong:

- to try to innovate on the Python/Django ecosystem

- to miss out on functional code for HTML composition

- to continue the framework paradigm - HTMX leads to server side which leads to devs reclaiming the application loop

If, like me, you feel that plain is on the right track, but want to go faster / further, then I encourage you to take a look at https://harcstack.org. [disclaimer, I am the author]

Do you have more posts about this? My main gripe about Django is that the usual html templating options are but-uggly (as opposed to those that ship with Rails), but I haven't tried one of the new options.
I wish django's template engine was demoted to a contrib package and eventually replaced by jinja (i.e. jinja becoming a django dependency).

I understand that django templates started with the intention of eliminating programing logic in the templates (presentation). But the implementation of the concept is very puritanistic, to the point of becoming counter-productive. Jinja's approach OTOH is less opinionated: you can be a puritan and emulate django's approach if you want, but you can also be less dogmatic about the logic/presentation separation if that serves you.

As someone very aptly put it on reddit [1]:

> Jinja may let program logic layer bleed into the presentation layer, but with Django it seems there's no way to do it without presentation layer bleeding into program logic layer.

[1] https://www.reddit.com/r/django/comments/13n9pfd/is_it_me_or...

And immediate and persistent 502 is not a great endorsement.
eating own dog food and I made an error - red face
(comment deleted)
Yeah, no thanks, I'll stick with Django (my bread and butter for over 15 years now!).
I miss a thorough explanation of how Plain is fundamentally different than Django + extensions. Good luck though
Related, "Django's REST (Framework) Problem" — https://news.ycombinator.com/item?id=43510495

I'm not sure that many people who rely on Django Rest Framework are aware that last month the bug tracker was made private and the project is looking for new maintainers.

I love Django but the project needs to go through something similar to Angular's renaissance (and Angular needs to learn from Django docs.) I'd love to help but it seems that most of the efforts to address the issue have been stalled in committee.

A fork probably isn't the answer but something needs to be done. If it's a money issue, pass the plate! Whenever I talk to Django devs about contributing the feeling that I'm left with is that I could put in years of work, jump through every hoop, and at the end of it they may still say "We're not sure."

The feeling that I've gotten is that the Django dev community is very small and tight-knit. Whenever I've talked about helping out on various projects I've walked away with the feeling that their friend is handling it and they'd rather leave them to it. The community has been trained, through years of reinforcement, to wait instead of getting involved.

Jacob Kaplan-Moss gave a great talk at the last DjangoCon about money - what Django would do with an increased budget and how to get there: https://jacobian.org/2024/oct/8/dsf-one-million/

Video: https://www.youtube.com/watch?v=5nS1SSuHk9I

I saw the talk last year. Let's do it.

If I had $100,000 to spare I would give it to Django as an unrestricted donation. It would be worth every penny. But I'm a solo-dev and don't have that kind of cash on me.

Here's what I can do. I will send you $1,000 today if you can get something like a `django.contrib.rest` package (i.e. official rest api support) on the roadmap and secure matching funds. I'll make it a recurring donation if development gets going.

I don't want to support other REST libraries because there's no consensus. One app ships DRF views, another Ninja, and that one over there still has a Tastypie dep. Remember Piston? Using multiple rest packages means that figuring out how to create a consistent error format, etc is an exercise left to the reader.

Django makes great design decisions that the majority of devs can get behind. I'd love to have an officially supported REST package that feels like the rest of Django.

`django-tasks` is a good recent example. I was reading through the code a few months ago and I was impressed.

Another project I'd fund: Making Django an async-first (not async-only) framework over the next decade. It's easier to mix sync code into async than the other way around.
So glad that's not actually true so I didn't have to rewrite sqlalchemy from scratch
It's more straightforward to call a sync function from an async function than the other way around. That's a pretty uncontroversial statement. Adding async support to a library doesn't mean starting starting over.

I'm not fully understanding your thought. Can you say more?

If one can make it without breaking the API too much, why not.

The #1 reason I use Django is stability. I have projects that span 4 major Django version without any significant break. That's quite a feature.

I just setup a $83/month ~$1,000/year recurring donation.

https://www.djangoproject.com/fundraising/ if anyone else depends on Django.

thanks for sharing this, just donated too.

I read thru Plain's doc, it is not bad at all, but I really hope Django can be much better than it is now.

Yep – I've been using Django since 2007. The big win used to be the admin, ORM, database migrations... but now oddly enough a lot of that has become a pain. I'm someone who knocks small solutions together for fun or to scratch and itch, so I'm looking for low maintenance. The problem I need solved has shifted and now Django is too much boilerplate (APIs and models are perhaps too distant as concepts), and too much maintenance work. Auth is perhaps underemphasised as an area for improvement. The built in auth isn't really fit for purpose anymore, and the various extensions for federation / passkeys take work to integrate and change a lot.

None of this is to write off Django or the people who've worked on it: I'm genuinely grateful for the framework. It's let me build open source things that help people out. The typical problems most of us standing up small-to-medium solutions need solved by a backend have just shifted underneath the framework, and it hasn't had the resourcing to keep up.

I've been looking at Pocketbase as a replacement. I think I'd prefer something that uses Postgres rather than sqlite, but it's pretty awesome as a solution for those two or three day projects, and the maintenance burden looks like it's pretty low on an ongoing basis.

Django dying the Drpal death of becoming a generalised case of nothing but itself?

Try Flask.

What's become a pain about DB migrations? They've barely changed and they are still so amazingly useful that you forget it's something you have to think about until you move to another framework that doesn't have them.
For a web framework for building in Python, use webpy:

“Django lets you write web apps in Django. TurboGears lets you write web apps in TurboGears. Web.py lets you write web apps in Python.”

https://webpy.org/

Sorry, can't work without typesafety.
if type(var) != type(var2): # here's your type safety
Challenging hard work. Hope to go well.
By what metric is Python the most popular language on earth? I'm actually curious, genuinely asking. I thought JavaScript (Node) was king of newly written code, but perhaps that is outdated information.
https://github.blog/news-insights/octoverse/octoverse-2024/ - "In 2024, Python overtook JavaScript as the most popular language on GitHub, while Jupyter Notebooks skyrocketed—both of which underscore the surge in data science and machine learning on GitHub."

What's missing here though is TypeScript: I believe if you combine JavaScript and TypeScript together they still beat Python on GitHub.

Thanks, this is interesting. I'm also a big fan of your blog posts :)