Building a full Django project, starting with a single file

(mostlypython.com)

121 points | by kqnrnq17r 11 days ago

11 comments

  • simonw 11 days ago
    I'm a big fan of the single-file Django ambition - it's the feature I most envy from frameworks like Flask and Starlette.

    I actually had a go at this myself 15 years ago, with a project I called Djng: https://github.com/simonw/djng - more details on that here: https://simonwillison.net/2009/May/19/djng/

    • radiac 11 days ago
      Me too, I'm convinced it has a place - the number of single file projects over the past few years can't be a coincidence.

      For me the two missing pieces were models and a path to migrate to a full project once it outgrew a single file, so I wrote nanodjango (https://github.com/radiac/nanodjango/, formerly django-flasky) - you can use the ORM and admin site, and I recently added a "convert" command to automatically break up a single page app into a full Django project structure.

      I've been using it for a couple of years for prototyping/experimenting and putting together small apps, and with the new features this year feels like it's a really practical alternative to flask.

      • creshal 11 days ago
        > I'm convinced it has a place - the number of single file projects over the past few years can't be a coincidence.

        The human soul yearns for the simplicity of php or cgi-bin hosting, without the horrors of PHP or C

        • radiac 11 days ago
          Mine certainly does - we lost so much when we killed off our cgi-bin/guestbook.pl
      • selcuka 11 days ago
        This looks really cool, congratulations.

        Are you planning to add some kind of API serving functionality (either by integrating something like Django Ninja or even raw Pydantic)? I think such single file frameworks are great candidates to implement microservices.

        • radiac 11 days ago
          Thanks! Yes definitely, I think it's a great fit for anything self-contained and limited scope that doesn't need a lot of code. I've certainly found having an easy way to run a single file using Django's ORM is pretty handy.

          Regarding API serving, I'm planning on making it easier to use third party apps; the main obstacle is registering `includes` urls, which is doable at the moment but involves manually appending a path to `nanodjango.urls.urlpatterns`. I want to expand route registration to give a nicer internal api, then once that's in place Django Ninja should work pretty much out of the box - the only different should be how you register the url.

      • pjerem 11 days ago
        This looks amazing ! Bravo
        • radiac 11 days ago
          Thank you, it's great to have positive feedback!
    • BeefySwain 11 days ago
      I would be interested to hear your thoughts on why this never ended up going anywhere? (Or did it go somewhere ?)

      As a Django user that shares your frustrations with settings.py, I wish this had panned out.

      • simonw 11 days ago
        I got very busy at work, then quit to go on honeymoon, then accidentally started a startup!

        I wasn't particularly good at sticking with open source projects like this and pushing them forwards back in 2009. I've since learned how to do that but it took me another decade to get there.

        • BeefySwain 11 days ago
          Is this something you think you would ever come back to?
          • simonw 11 days ago
            Honestly no - not at this point. I have too many other projects on the go. I'd love to see the Django community take this on generally - there are a bunch of people interested in it, hopefully that result in a long-term stable project around the idea.
  • sireat 11 days ago
    Fantastic idea to start Django with a single file!

    Some years back when I had to do some quick and dirty projects, I chose to go with Flask because of how dirt simple it was to start.

    All the Django books and tutorials had this hidden magic abstraction feel to them after:

      $ django-admin startproject <project-name> .
      $ python manage.py startapp <app-name>
    
    
    Once you've reinvented half the Django functionality in Flask (using SQLAlchemy etc) you realize the need for the most of these abstractions.
  • Onavo 11 days ago
    The most powerful part of Django is its ORM, nothing else comes close in the ecosystem. The automatic migration generation tools for SQLAlchemy like alembic are much harder to use than django's built-ins.

    Django just needs to add Pydantic integration.

    • fleetfox 11 days ago
      In what way "most powerful"? If you do anything more involved than CRUD it falls apart pretty fast. You can't express most of the things you can do with raw SQL since there is not intermediate DSL like you do with SQLA. You can't hydrate arbitrary object graphs. It's slow, for deep queries building back objects is slower than actual SQL round trip.

      It's very easy to use but it's also very limited and i often find myself dropping down to RawSQL or even having SQLA connection in my Django projects.

      • SheepSlapper 11 days ago
        Then you might not be in the target audience of Django. For the rest of us, the ORM is dope as hell and nobody cares that you aren't writing the most performant SQL the world has ever seen...
        • rossant 11 days ago
          The ORM is fantastic and I never use raw SQL, but I can see how it may be simpler to just go straight to raw SQL with complicated database structures and queries.
          • Maxion 11 days ago
            The best part about it though is that you can use raw SQL and the ORM at the same time. In larger projects that's how I've always used it. ORM for the majority of use cases, and the raw SQL where performance really matters.
      • selcuka 11 days ago
        Which other Python based ORM addresses those issues?
        • fleetfox 11 days ago
          SQLAlchemy does. I get that DjangoORM is more convenient and might be good enough. But powerful seems like wrong adjective.
          • winrid 11 days ago
            Powerful in terms of productivity. The occasional N+1 query problem here and there isn't a big issue for many projects and means you can launch 10x faster than someone using some other technologies. If you're successful, you can easily write raw SQL and optimize as needed.
          • pjerem 11 days ago
            DjangoORM isn’t perfect but its power comes from the fact it is heavily integrated with Django (the framework).
          • selcuka 11 days ago
            Ah, sorry. It wasn't clear that SQLA meant SQLAlchemy in your first comment.
    • dhruvkb 11 days ago
      I have a few projects where I use Django just for the ORM. The rest of the project is is CLI commands that are being run as Django's management commands to be able to access the ORM models. SQLAlchemy and alembic are quite far behind compared to Django.
    • axit 11 days ago
      There are couple of projects aiming to integrate django & pydantic: https://django-ninja.dev for APIs & https://github.com/jordaneremieff/djantic for model data
    • jamestimmins 11 days ago
      Few things I want more than for someone to extract the Django ORM from Django so we can use it standalone instead of SQLAlchemy
    • wilsonfiifi 11 days ago
      Have you taken a look at Masonite Framework's ORM [0]? It's an implementation of ActiveRecord. I'm not sure why the framework [1] doesn't get enough attention though. I think it's a nice option for projects that have outgrown Flask but aren't keen on Django.

      [0] https://orm.masoniteproject.com/

      [1] https://docs.masoniteproject.com/

    • konschubert 11 days ago
      I was thinking the same the past few days.

      Going with fastapi and sqlalchemy, there is no django admin and no user management out of the box.

      But writing serialisers for DRF feels dated.

      • SCUSKU 11 days ago
        Would highly recommend you check out Django Ninja as well as Django Ninja Extras. Having done Flask + FastAPI dev then Django, Django Ninja brings the modern feel of FastAPI to the battle tested reliability of Django.
      • alumic 11 days ago
        I’ve been very happy with Django ninja. It brings in pydantic as well so you get the benefit of type safety in addition to a much faster request response cycle as compared to DRF
      • Maxion 11 days ago
        You can quite easily generate typescript models from DRF serializers, that helps a lot when setting up a frontend project against a DRF api.
    • hsbauauvhabzb 11 days ago
      Agree, I never felt comfortable with sqlalchemy, but I don’t need most other django features and find mTLS elf wrestling against them
    • ipaddr 11 days ago
      I'm using Orator as a replacement and enjoying the experience.
  • whatever1 11 days ago
    I really love Django. I knew nothing about web development, it took me by the hand and from a tutorial I went to a full fledged application.

    I cannot fathom what is the GDP impact that these folks enabled.

    • rossant 11 days ago
      After more than a decade building custom admin-like interfaces from scratch in PHP, the auto-generated admin interface in Django felt like magic.
      • SCUSKU 11 days ago
        Django admin + the Django ORM are the biggest reasons I haven’t moved to JavaScript Metaframework land. Next.js is great in its support of react and server rendered react for SEO. But where Django wins is that logic will always have to be on the trusted compute environment, the server. JS Metaframeworks approached the full stack problem from the front end and Django from the backend.
  • jarpineh 11 days ago
    I'd love to use Django as a fast and easy single file app. There's some great looking solutions here. Have to take a look.

    I tried myself about five years ago. My idea was to make a tool that could make a HTTP service from any Python file with very simple setup. With all the features of Django at the ready. Unfortunately neither Django's configuration system nor Python import methods made it reliable enough. Or I just couldn't hack it. This was the smallest I managed:

      from django.urls import path
      from django.http import HttpResponse
    
      CONF = {
        "INSTALLED_APPS": ["serverless"],
        "ROOT_URLCONF": (path("", lambda x: HttpResponse("look ma, no server")),),
        "DEBUG": True,
        "SECRET_KEY": "randobrando"
      }
    
    Other thing I tried to do with this was attach a Jupyter kernel. This way I could change the code as I went, but wouldn't have to use entire Jupyter client stuff. Unfortunately there I ran into problems with event loops. I could not find a way to manage different servers in the same runtime instance. Perhaps it's time to try again wiser and helped by LLMs...
    • japhyr 11 days ago
      The app-based model is really baked into Django. As we've seen from a bunch of examples, especially recently, it's not too hard to build out a single-file project that serves a simple home page with a brief message. As soon as you want to support a full actual page, and a set of pages, you really have to figure out a well-thought-out plan for how people will expand the project.

      If you're still interested in this work, I suggest checking out nanodjango, which was mentioned earlier in this thread. That project is new, but there's a plan from the outset for how people can transition from the single-file based version to a standard Django project. You might also want to check out Andrew Godwin's django-singlefile project. It's meant to support small flask-like projects, where you don't have any intention of expanding out into a standard Django project.

      Both of these projects have their own code that takes what's included in the small file and tells Django how to make sense of it. That's much different than the projects that are only trying to make use of what's included in Django itself.

      (I'm the author of the Django from first principles series that was submitted here, but I didn't see it on HN until this morning.)

      nanodjango: https://github.com/radiac/nanodjango

      django-singlefile: https://github.com/andrewgodwin/django-singlefile

      • jarpineh 10 days ago
        Thank you for your reply. For the first point, I agree. When I was doing my experiments with single file Django I was thinking of combining few simple, single purpose apps into one regular Django project. This project would serve as an actual site for people to use with its own templates, but hopefully not that much custom code. With ASGI coming along (this was 2019 I think) I even tried to combine these app pieces under one ASGI server. Sadly I run into some trouble with server tooling.

        In regards to nanodjango I shall take a look. Also, need to read the rest of your articles. Thank you for writing them! I’d still like to experiment with the idea of small, independent, pluggable apps. Perhaps Django can be coaxed to this now.

  • wilsonfiifi 11 days ago
    Lightweight Django (2014) [0] actually explores using the Django framework in a similar manner.

    [0] https://www.oreilly.com/library/view/lightweight-django/9781...

  • seper8 11 days ago
    Am I missing something or is there no sample code...?
  • thedeparted_one 11 days ago
    Awesome!
  • xcdzvyn 11 days ago
    I really wish there were something like this for Phoenix. I want to like it, but I feel a little inundated with all the codegen.
    • agos 11 days ago
      I second the feeling. It's really hard to tell what is (are?) the entry point and where does the flow go
      • arcanemachiner 11 days ago
        If you use all the `--no-` flags (e.g. `--no-tailwind`) when creating a Phoenix project, you will be left with a surprisingly small amount of code.

        This is not so useful in a real project, but good as a learning exercises to see what comprises the core of a Phoenix application.

        https://hexdocs.pm/phoenix/Mix.Tasks.Phx.New.html

        FWIW, everything starts in your project's `lib/project/application.ex` file. All the things in the `start` function dictate the "flow" of the application.