I finally set aside some time to read Django Views — The Right Way.
Luke Plant makes a very persuasive argument for view functions (FBV) - especially about their being
more explicit especially when it comes to the transparency of passing request into each view
function. He is quite negative about class-based views (CBV). I kind of agree about CBVs hiding
details and making it harder to know what to change. I would be lost without the Classy Class-Based
Views site but Luke’s critiques are more about CBVs creating layers of
indirection and actually introducing extra boilerplate as compared to FBVs.
Most of his examples are simple enough that either approach is fine. But his example of the detail view plus list of releated items is rather persuasive - largely because the CBV version feels a little weird. And the story about converting to CBVs introducing a security issue is sobering. But the really scary section is “Mixins do not Compose”, though I am not sure how much of that is the fundamentals of Mixins vs the details of UserPassesTestMixin. Perhaps it is fundamental. In the section Helpers vs mixins he enumerates issues with mixins, including:
-
Mixins hide the source of the changes; you have to look at all of them to get the full picture.
-
Mixins do not have a well defined interface. Because mixins are inheritance, each mixin affects the definition of the class but spread out the class definition into multiple places. In the FBV versions, each function has a specific signature - we know all the parameters that go in and we can see what it returns. If you add type hinting, your IDE can help you check for plausibility. The next thing I need to read is this essay on Composition over Inheritance.
The last really interesting part of this essay is the Thin Views section. This is the Django version of Rails’ “fat models; skinny controllers”. He argues that the view should really only be the request/response cycle parts and the business logic should be in separate methods - with a preference for making them part of the model layer rather than creating a Services layer. The business logic doesn’t neccessarily have to be part of the ORM model class. But it should be in a class or function that is independently testable. The most interesting example was a demo of how to implement Rails’ models scopes by creating custom QuerySet classes. This is how Wagtail adds its page tree methods into the Page model.