Would be an interesting study, yes. But personally, I wouldn’t go so far as to say it’s “required”. I’m enough of a pragmatist to acknowledge that “it is what it is” - I can use it (or not) regardless of how we got here.
The investment in any sizable web framework is huge. Any company choosing to build core logic around .Net, Spring, Django, Symfony - or their corresponding “products” such as Liferay, Wagtail, Drupal, Wordpress, etc has typically made a decision that they need to feel good about for 10 years. Replacing any such product is never trivial. The frameworks, in providing the shell in which the business logic resides, does drive the architecture.
I’ve only been using Django consistently for 7 years now. I know, empirically, I can deliver solutions faster, easier to extend, and with fewer problems across the board than I can with .Net (4 years), Java/Spring (8 years total), or Drupal (5 years). (There is some overlap there, those Java projects were concurrent with both some of the .Net and Django work. Only about 3 years of that was exclusive to Java.)
I’ve worked with 3 large Java projects - two of the three exhibited a bad case of “over-engineered layers”. (The third had no discernable architecture at all - it was a complete mess.)
One had all the code nicely laid out between servlets, data access layer, business logic layers, and JSPs. And it was probably the worst system I ever had to deal with. I wish I had permission to keep a copy of it. It adhered to every generalized “best practices” pattern of Java engineering you could name. Yet it was also the most difficult code I ever had to dive in to to try and diagnose problems, or to extend functionality. I’ll take the most disorganized Django-based project over that one any day of the week.
My opinion is that it’s not needed independent of the models and managers. Such a layer, as a separate entity, provides no value in Django.
For a real-life example:
I have a system I’m working on now - part of that system is a Timesheet reporting system. People enter their time every week, reporting hours by day by project and task.
A “business entity”, the Timesheet, actually consists of data from six (seven? I might be missing one) different tables. Each of those tables are separate models. However, most of them have no intrinsic existence outside the context of that Timesheet.
The base Timesheet object itself is rather small. It consists of an id field (primary key), a foreign key to User, creation date, last modified data, week-ending date, and a status. Each row of the timesheet (a separate “Timesheet Row” is the hours for a specific task) is related to it, and each day (a separate “Timesheet Hour” table) is related to the Timesheet Row.
In this particular case, the “public API” is the retrieval of an individual timesheet. That functionality - retrieval and organization of all the data associated with the timesheet, exists within the Timesheet Manager and the Timesheet Model.
Why? Because in this case, the “Logical timesheet” - the “business entity” is fundamentally driven by the Timesheet table. There is no reason to put that logic anywhere else. Creating a separate layer, just to retrieve that object and its related data, is adding complexity without adding value.
With that pattern in mind, our database in this system consists of 6 base entities - business objects such as Users, Work, Invoices, Timesheets, Reports, and Firms. Each one of those is a table in the database, but has multiple tables (and relationship tables) supporting them. (The current database is about 125 tables total.) Those business entities serve as what might be construed as the “business layer” in a different framework - they certainly provide the same functionality, but without the artificial segregation of code.
If I’m having an issue with a User’s permissions, I know that all the logic associated with the permission system is in the User module.
So the point here isn’t that there’s no “business perspective” on the data - there clearly is. The point is that there’s no value in creating a separate architectural layer for it. The managers and model methods reflect both the logical views of the models themselves and the business views “anchored” by that model. And that is my understanding of what is meant by the “Fat Model”.
As a side note, to try and provide some balance here, I searched for some of the blog posts I’ve seen in the past that argue against the “Fat Model” idea. However, the first 4 that I found actually agree with me, in that they take the position that the logic belongs in the managers not in the models themselves. I’ll accept the argument that I’m inaccurate by including the managers and querysets as being logical components of the models. Personally, I include them there since you access those managers through the model’s class name, and when I refer to the concept of a “Fat Model”, that includes those related managers and querysets.