Skip to content

Modernice support for SPA apps / REST services #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
1 task done
alexandernst opened this issue Apr 27, 2025 · 9 comments
Open
1 task done

Modernice support for SPA apps / REST services #11

alexandernst opened this issue Apr 27, 2025 · 9 comments

Comments

@alexandernst
Copy link

alexandernst commented Apr 27, 2025

Code of Conduct

  • I agree to follow Django's Code of Conduct

Feature Description

(This is a split from #10)

Problem

Previos version of this submission Web landscape has completely changed and what could have been considered a novelty 10 or 15 years ago, nowadays is the norm. For example, SPA on the front and REST (or GraphQL) on the backend. Django completely lacks any support for either of these. Trying to use (only) the framework as a purely REST service feels wrong and deficient.

And while the situation on the backend is totally under control with DRF (and other 3rd party packages), the situation on the frontend is in a completely sorry state. It boggles me how it is completely impossible to do even the simplest thing, such as using static images in CSS files (e.g. {% static 'path/to/image.png' %}, but in a CSS file). I'm aware of django-compressor, django-webpack-loader and other 3rd party packages, but all of them feel broken, inefficient, storage-dependant and just overcomplicated for a feature that I'd expect to find in the core of the framework. There is also 0 support for anything JS-related.

Django has completely disregarded how websites are built. I beg you take a look at what other frameworks are doing to mitigate this situation.

For the backend part, I'd suggest a strong collaboration with DRF (maybe merging some of the features into core?). For the frontend part, I'd suggest creating a call for feedback from the community. Ask people which way Django should go (integrate a bundler such as vite? do something like hotwired?).


Second take at better describing what this ticket is about

Modern web application can be split into 2 general categories: CSR and SSR. In order for me to be able to explain and showcase the major pain points in Django, I'll compare it to Laravel and Ruby on Rails.

SSR

Server Side Rendered web applications. This is your "fullstack" web site. The backend is responsible for rendering HTML blobs (either total or partial) that can be fed directly to a browser (or an indexing bot). This means that the backend is concerned with how to app looks like (html, css) or works (js).

In this configuration the backend and the frontend coexist in the same codebase. Backend performs some sort of interpolation in order to render templates. Other static assets might get included in the reply or be used during the processing of the reply. Additional packages might be required for the later. In Django specifically:

  • django-compressor (or equivalent)
  • jinja2 (for advanced use cases in templates)

The frontend is composed by views which might inherit from other views and can use css, js or other static files. During a response, the framework can interpolate data into the view. During deployment, static files might get collected or bundled in a specific way (eg. name versioning in order to bust CDN cache).

How other frameworks do it

Both Laravel and Ruby on Rails have built in support 1 2 for interpolation in CSS and/or JS files. Specifically, they allow the following JS code to work out of the box:

Laravel

import log from "./images/logo.png";
.logo {
  background: url('./images/logo.png');
}

Ruby on Rails

.logo {
  background: url(<%= asset_path './images/logo.png' %>);
}

For JS assets, there is RAILS_ASSET_URL, which might be good enough depending on the use case. Advanced use cases require using external bundlers (vite integration in RoR).

How Django does it

Django doesn't offer any support for assets management other than referencing static files from the views. CSS and/or JS interpolation of file paths requires 3rd party packages such as django-compressor. This creates unnecesary friction and it can be avoided by integrating vite in the same way Laravel and RoR do it.


CSR

Client Side Rendered web applications. This is your SPA + API webapp. The backend is responsible for delivering raw data in any format (yaml, json, xml, etc...) to the frontend. The backend has no concerns or notion about how the app looks like (html, css) or works (js). It might or it might not care about the state in which the user's session is (stateless vs stateful).

In this configuration the backend and the frontend codebases are split. The backend is composed mainly by features that would allow the developer to expose an API. In Django specifically:

  • djangorestframework
  • djangorestframework-simplejwt (or equivalent)
  • django-filter
  • django-cors-headers
  • channels

The frontend is composed by a JS framework / DOM manipulation library + state manager of some sort, a bundler, maybe a SCSS framework, etc... It could be React + Redux, or Angular or Vue combined with Tailwind or Bootstrap or (...).

In this scenario, the backend framework (Django in our case) can completely ignore any frontend-related tasks (parsing scss/js files, name versioning, bundling, ...) and focus exclusively on the API stuff.

How other frameworks do it

Frontend side

In this configuration the framework is not expected to care about the frontend. Developer is free (and encouraged) to seek whatever solution fits best.

Backend side

Laravel and RoR support model serialization out of the box 3 4. This would be the equivalent of DRF's serializers. All of them support any features that could be expected from a serializer: adding and/or removing fields during the serialization process and functions as field getters.

They also support serialization of input data (request validators) 5 6 with both basic validation (required fields, nullable fields, unique fields, min/max length, data type, etc...) and advanced validation (functions).

Filtering (as in URL query params; django-filter) is not supported by default in any of these frameworks. Functionality achievable by writing custom code.

How Django does it

Frontend side

Same as the other frameworks.

Backend side

Django doesn't support serializers as such. There is JsonResponse which could be threated as a very basic serializer, sort of, but it would consist of manually writing down each field into a dict, no support for getters and the resulting data is an actual response object, which makes any further operations on that data unnecessarily difficult.

Django also doesn't support any form of serialization of input data (no such thing in the framework). The closest one can get is using ModelForm (or the subset of *Form* classes) combined with MyForm(json.loads()), form.is_valid(), form.save() and so on...

The DX with the other two frameworks feels polished and well integrated, definitely suited for a REST framework. Django doesn't offer any support for this use case and there is no way around having to include DRF (unless one is willing to accept a lof of manual code).

Request or proposal

request

Additional Details

No response

Implementation Suggestions

As explained in my first attempt, Django is lacking in features in both options.

The SSR option can greatly benefit from even something as simple as interpolating file paths in CSS files. Of course, making vite (or another bundler) a first class citizen (as in other frameworks) would be amazing.

The CSR option can greatly benefit from some of the features provided by DRF. Of course, I'm not asking to integrate DRF itself, but only a small subset of features. Features from other packages are also more than welcome.

Final words: Django is marketing itself as a "batteries included" framework, but further analysis in this context reveals that this might not be the case as it's currently offering no built in features that can be used to cover basic use cases for modern web developers.

Copy link

Thank you alexandernst for sharing your idea! We have a lot of them so please be patient. You can see the current queue here. If you'd like to learn about other ways to get this idea more attention, please see this page.

Community instructions

For commenters, please use the emoji reactions on the issue to express support, and/or concern easily. Please use the comments to ask questions or contribute knowledge about the idea. It is unhelpful to post comments of "I'd love this" or "What's the state of this?"

Reaction Guide

  • 👍 This is something I would use
  • 👎 This is something that would cause problems for me or Django
  • 😕 I’m indifferent to this
  • 🎉 This is an easy win

@gav-fyi
Copy link

gav-fyi commented Apr 28, 2025

I wonder if this should be 2 separate issues? Whilst I'm 👍🏻 for trying to find a nice route through having better JS/bundling support in core, I'm 👎🏻 on adding or relying on DRF (or a subset of its features) into core.

@alexandernst
Copy link
Author

My reasoning for writing these 2 things together is that they go hand by hand in the current landscape of frameworks (and use cases). Some of the frameworks / solutions that I mentioned rely on that fact in order to provide a more coupled solution / experience.
The baseline can be "REST on the back and SPA on the front", but we could also learn some stuff from hotwire/turbo (linked in my first comment) and improve DX. Let's not just add things to core for the sake of adding stuff. Instead, let's figure out how to improve the overall experience while using Django for building fullstack applications.

I suggest we try to understand what are the current pain points when building a full application using Django and trying to provide functionalities that will solve these problems and attract new users.

@tim-schilling
Copy link
Member

I think this would benefit from a clearer statement of what is being requested.

@alexandernst
Copy link
Author

All right, let me try to reword it.

@carltongibson
Copy link
Member

I've been using Django-compressor for more than a decade. I started with jQuery. Went through Backbone, sass and less, bootstrap, Ember, Elm, React with webpack, and esbuild and vite. I'm now using it with Tailwind and Alpine. It's far from broken, though there are always the latest bleeding edge things to add, that being front end.

The proposal to add a build pipeline type thing to Django has been a constant over all that time. The longer that's not happened, the more it's become clear that was the right decision.

There are currently proposals to improve Form.Media adding JS Assets with support for import maps and other niceties. I'm
not sure what other parts might be suitable for core itself. I'd suggest not many.

Likely some of the ecosystem HowTos on setting up staticfiles for different scenarios could be highlighted or added to the docs.

@frankwiles
Copy link
Member

I agree with @carltongibson on adding something like compressor to core, despite having myself fought ALL of the bundlers over the years (django-compressor, django-pipeline, django-webpack-loader, django-vite, and crap I wrote myself).

That being said, I DO BELIEVE we can improve static file handling and specifically debugging why what you feel should be happening isn't.

@nanuxbe
Copy link
Contributor

nanuxbe commented May 1, 2025

While I don't see us introducing any preferred way of doing things, I believe there are some changes in Django core that could go a long way. The Form media proposal is part of those "small things".

I think it would be a good idea to look at what can be done without too much pain on the Django side

@alexandernst
Copy link
Author

I updated the initial comment with more details about the suggestion. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Idea
Development

No branches or pull requests

6 participants