Hi all,
This is a long post so I’ve copied my two questions for a TL;DR. I’ve also bolded the questions within my post so you can grasp for any context if you think that it’d help your answers.
-
is there any publicly available (paid is ok) literature or training available that covers how to best structure a large, ongoing, mature Django project?
-
Does anyone have any experience writing complex Django applications with a services layer as discussed in the linked style guide? How has it gone for you? Has it saved more time than it’s spent having to override or reimplement Django’s provided batteries?
I am the sole developer of a Django-based web application. This application was developed by a small team (including myself) in a digital consultancy, so it is quite large. I have since moved on from that role and now work with the client full-time as their sole FT developer. I contract out as need be, however, so far I have done the vast majority of the development work.
If any of you have worked for a hourly-billing consultancy, or have seen code written by one, you will understand the potential shortcomings. The codebase is pretty good and does very well, but a lot of the work was done ad-hoc and crucial things like tests have been largely ignored. The structure of the codebase may also be in need of some TLC with the hindsight of how big the project has become.
At least in the literature I read, not much is said about how to structure these larger projects. People talking about deliberately sterile ‘todo’ applications is largely unhelpful, as my application faces problems that are either deliberately sidestepped by malleable defined requirements, or not dealt with as a result of the (lack of) complexity of toy applications.
So my first question is, is there any publicly available (paid is ok) literature or training available that covers how to best structure a large, ongoing, mature Django project? This project has moved far beyond a collection of generic CRUD views and does some impressive stuff. Unfortunately, I find that I can not relate to a lot of conversations when discussing project structure. I’m unsure if this is due to the size of my project or because there are obvious things that I am missing.
Of all places, it was a sponsored post in @wsvincent and @jeff’s Django News newsletter that I saw the HackSoftware (never heard of them) Django style guide for enterprise applications. There is a fair bit of stuff in here that I think that I disagree with. However, this document touches heavily on the concept of including a services layer in a project, which would encapsulate all business logic / actions outside of a view/form coupling, with the intent being that only the services layer interacted with model / ORM code.
The benefits of this are obvious, it’d be much easier to test business logic in the (fat) services layer without concerning yourself with views, forms, or most of the ORM. This would be especially advantageous to me as it’d encourage better test hygiene in my project. It also allows for easy re-use, yada yada.
This is not really groundbreaking. It’s a common pattern and obvious if you have an intuition for separation of concerns. However in the world of Django where the usage of things like ModelForm and generic class-based views seem to be quite the norm, it is a bit of a departure. This is where the downsides come in. Things like generic class-based views (esp. database mutating views like CreateView
, UpdateView
.etc) muddy the waters and strictly speaking could not be used in their default states. Things like ListView
seem like they’d be fine. The magic of ModelForm
s — or at least the default save()
method—could not be used. These seem like they are big time-savers to me at the moment.
I recall seeing an article (or maybe it was a conference talk or email) by Tom Christie about such an architecture, where he similarly advised against using Django REST Framework ModelSerializer
s and instead suggests using regular Serializer
s for mutating data via your services layer. This similarly seems like it would introduce a lot of extra work, and the DRF documentation seems to suggest that ModelSerializer
s and generic CRUD ViewSet
s are the way forward. A services layer seems like it’d break this. Have I understood the intent? Are these shortcuts not meant for me?
Does anyone have any experience writing complex Django applications with a services layer as discussed in the linked style guide? How has it gone for you? Has it saved more time than it’s spent having to override or reimplement Django’s provided batteries?
Thanks in advance.