Hacker News new | ask | show | jobs
by mg 725 days ago
What I love about Django is that you can create a Django project with just one file.

You can turn a fresh Debian machine into a running Django web app by just doing:

    apt install -y python3-django apache2 libapache2-mod-wsgi-py3
And then creating the one file Django needs:

/var/www/mysite/mysite/wsgi.py:

    import os
    import django
    from django.core.wsgi import get_wsgi_application
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.wsgi')
    application = get_wsgi_application()

    ROOT_URLCONF = 'mysite.wsgi'
    SECRET_KEY = 'hello'

    def index(request):
        return django.http.HttpResponse('This is the homepage')

    def cats(request):
        return django.http.HttpResponse('This is the cats page')

    urlpatterns = [
        django.urls.path('', index),
        django.urls.path('cats', cats),
    ]
And then telling Apache where to look for it:

/etc/apache2/sites-enabled/000-default.conf:

    ServerName 127.0.0.1
    WSGIPythonPath /var/www/mysite
    <VirtualHost *:80>
        WSGIScriptAlias / /var/www/mysite/mysite/wsgi.py
        <Directory /var/www/mysite/mysite>
            <Files wsgi.py>
                Require all granted
            </Files>
        </Directory>
    </VirtualHost>
And voilá, you have a running Django application, which you can expand upon to any size and complexity.

If you want to try it in a docker container, you can run

    docker run -it --rm -p80:80 debian:12
perform the steps above and then access the Django application at 127.0.0.1
5 comments

Blown away this is possible. When I was starting to learn to code and was overwhelmed when learning all the bits and pieces of rails, I wondered if everything necessary to run a very small app could be placed in a single file. I guess this is the answer, but in python/django instead of ruby/rails. It would be a fun exercise in ruby/rails too (not totally sure if it's possible, but suspect it may be, albeit probably resulting in a larger file than the one you give above!)
Not that I think this is pratical or even looks good, but its also doable with rails

  require 'bundler/inline'

  gemfile(true) do
    source 'https://rubygems.org'

    gem 'rails', '~> 7.1'
    gem "sqlite3", "~> 1.4"
  end

  require 'rails'
  require 'active_record/railtie'
  database = 'app_development.sqlite3'

  ENV['DATABASE_URL'] = "sqlite3:#{database}"
  ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: database)
  ActiveRecord::Schema.define do
    create_table :my_table, force: true do |t|
      t.integer :my_table_id
    end
  end

  class App < Rails::Application
    routes.append do
      root to: 'home#index'
    end
  end

  class HomeController < ActionController::Base
    def index
      render inline: 'HOME'
    end
  end

  App.initialize!

  run App
For very small apps on ruby land sinatra and roda are the right choices. On python the choice would be flask instead of the single file django.
Is the db mandatory in Rails or could the db specific lines be removed from the code if no db is needed?
Not mandatory, you could remove that
Cool. What would be the steps from a fresh Debian to get it running and see it in action?
Not sure debian has (a modern) ruby installed by default, but I think you only need to have a working ruby installation and running the script. On a sidenote, this came out recently and could interest you https://dashbit.co/blog/announcing-phoenix-playground
This is also easily done by design with flask or quart, and probably several other frameworks.
There is like 10 python frameworks which achieve that with much fewer steps.
Yes but how do you go about defining an ORM model without an app init class?
I hanen't touched Django in some time, but something like this should work:

    from django.db import models
    from django.db import connection

    class MyModel(models.Model):
        name = models.CharField(max_length=255)

        class Meta:
            app_label = 'myapp'


    with connection.schema_editor() as schema_editor:
        schema_editor.create_model(MyModel)

    # from django.core.management import call_command
    # call_command('makemigrations', 'myapp')
    # call_command('migrate', 'myapp')
A lot could be said about it, but the first thing that comes to mind is that not every application uses a db.

And not every application that uses a db needs an ORM.

You probably can build an ORM into the single file. But I'm not saying every application should be developed as a single file forever. I just like that you can start with one and expand later.

Then you don't need django, flask and fast API already does all that withing a single file.

What makes django useful is the admin, auth, session and so on that are all built around the ORM.

You never know into what a project will develop. So it is nice to know you can expand it into anything, even when you start simple.
I don't catch if you are sarcastic or not

do you really consider this a lean process in 2024?

You get downvoted but my first thought was similar, I wasn't sure the author was being sarcastic or not, although for a slightly different reason: the whole process, if done more properly, has a few more steps (and of course even more for production) - but on the other hand it might be interesting for someone to know you can skip some and start a smallish app a bit quicker although I'm not a fan of such hacks.
This is one of the core criticisms of Django and python web backends.

WSGI is old tech that in your example requires extra packages and code in project to work. By now Python should stand on its own and handle this independently, being proxied to by better http servers like nginx or caddy.

You have to install software for software to run on your computer?!?
You have to install extra software that should’ve been part of std, big difference.
Are you still talking about Apache here?
> This is one of the core criticisms of Django and python web backends.

No it's not. Please cite reputable sources.

One does not need to cite a source of criticism, it is in itself the criticism.
One needs to cite a source for a claim that a particular criticism is widespread.
The burden of proof is on the person making the empirically unfalsifiable claims.
You're playing with words to deflect from the argument. No one has to have proof that they have a criticism. They have to have proof that the criticism is as stated. The evidence is self evident given the OP post.

Many share my opinion, and I don't have to prove that. Nor should I, and neither do you for any position you have. Address the argument.

You have to have proof that a claim is "widespread" if you are asserting it as such without any sources, as you have.
Not only extra packages. They are currently shoehorning extended multiple interpreter support into CPython, which only Django uses. Similarly, the thread support appears to be mainly for the benefit of that famous photo sharing website that uses Django.

CPython is fully commercialized.

As someone that doesn't work for the photo-sharing website, I love the new multiple interpreter stuff (it does feel a bit redundant now that the gilemtomy is going forward though, but who knows, maybe more cool uses will become apparent with time (and even so, it is making cpython-the-implementation clean up some of its ugly c-isms that it never bothered fixing, so it's a net win imo even if the feature itself ends up being not-useful)) and the gil-removal. As soon as the gil is gone I'm going to be experimenting with some new optimization projects at work, whole new flows that just weren't viable before under multiprocessing now suddenly are. (whether it all works out for us at that point is anyone's guess, but it's now our problem and not the languages', so yay!)

And I'm certainly not unique amongst other pythonistas, this has been a goal for literal decades.