6 ms·
I like class based views. But either way if your views are getting complicated you're doing it wrong. Views should just be plumbing to glue together the data y
by dec0dedab0de 3y ago
I like class based views.
But either way if your views are getting complicated you're doing it wrong. Views should just be plumbing to glue together the data you want for the template. All your business logic should be methods on your models, and if those are getting too complex they should be importing separate modules. The views should mostly be boilerplate.
The reason everything should be on the model (or atleast a separate module if you're a functional zealot) is so you can have your same logic available in your async queue, the api, cron jobs, and the shell for troubleshooting. If you have any logic tied up in the view it's a huge pain to access from anywhere else. And I don't know about you, but I always end up needing the logic somewhere else.
- kamikaz1k 3y agoThere should be an intermediate layer between views and models, especially if they're getting complicated. Complications probably come from coordinating more models. So you introduce a Service layer. So Models house logic specific to handling the data within that Model. And Services can orchestrate across multiple Models, or Multiple Services. But you try to keep it as a DAG. There's always room for pragmatic compromise though...
- dec0dedab0de 3y agoI tend to handle that with an extra model that just has relationships to the other models and some methods to make it work
- gmt2027 3y agoThere's an argument against service layers in Django. The recommendation is to use instance and manager methods. https://www.b-list.org/weblog/2020/mar/16/no-service/ https://www.b-list.org/weblog/2020/mar/16/no-service/
- btown 3y agoOver time, though, this approach leads to massive model/manager files with dozens of groupable methods. Sometimes a service is a useful abstraction as a way to encourage placing related functionality in a dedicated file. The one-minute learning curve for telling new team members what that services directory does, may save hours that would have otherwise been necessary to grok a thousand-line model file.
- rpep 3y agoI disagree with the idea of not having a service layer at all, because in practice, changing your data model in some way is actually pretty common, even if the API remains the same so the data coming in/out isn't changing. I've had to split models into multiple parts to add audit history on certain fields, create notifications on object creation or modification (possible but hard to follow and a visibility problem when using signals), change the normalisation on fields, etc. etc. and at this point, turning to a service layer is much more appropriate than putting methods on the model since often the data is split across multiple database tables. I also would advocate this in projects where it's Django + DRF since you generally want exactly same logic to be run through whether submitting via a form or submitting via an API. I've also found that it's good practice to impose boundaries between apps so that they are not strongly coupled together but communicate through an interface. That way, if you need to split an app out into its own project at some point, the migration is significantly easier from a code perspective, since the implementation of the interface function is all that needs changing on the consumer side.
- hitchstory 3y agoIt sounds to me like you could use model managers and just call it a service layer. >in practice, changing your data model in some way is actually pretty common I find this to be very true on some projects and very not true on others. Where it is true the abstraction would be beneficial but if you assume all projects have this problem and therefore jam the abstraction into a project that doesn't have it you're just creating overhead.
- rpep 3y agoModelManagers are directly coupled to one model though. You mix concerns if you need to reference other models in them. For e.g. say you have a User model and a corresponding “Profile” model. If you need to create the profile object when the user is created, it doesn’t really feel appropriate to put that in a UserModelManager directly coupled to the User object. This is the example given from the Hacksoft Django style guide to advocate creating a service layer. In terms of the abstraction, I totally agree and tend to be pretty pragmatic about this sort of thing.
- Izkata 3y agoWe could never figure out what to call these and just ended up with "utils.py" They're definitely necessary though, most of what we were doing didn't map cleanly to a single model/manager so it would have been a confusing mess to shoehorn it into there.
- hitchstory 3y agoI've never seen complex CBVs that werent a mess. FBVs yes, CBVs no. CBVs are ok for simple use cases, but the fact that FBVs work fine for both suggests to me that CBVs are probably better not used at all. >you're doing it wrong Over the years I've come to view the frequent appearance of this phrase when discussing the merits of any kind of tech, process or abstraction as a red flag that something nonobvious is badly wrong with it. With CBVs I think there is a slight impedance mismatch between classes and views - not quite enough to cause trouble with simple use cases but enough to create an ugly mess when view complexity ramps up.
- dec0dedab0de 3y agoI think that comes down to how comfortable you are with classes and multiple inheritance and whatnot. Django is a shining example of how to do these things right, but yes it can be a bit daunting if you're not used to them. But in my experience, FBVs become a mess even if they're relatively simple, because of the temptation to keep it all within a single function. If you take the time to break things down into separate functions and try to keep it dry, while passing around the related objects then FBVs are ok, but then you're basically recreating classes. In any case, my point is that function or class views should never be complicated, they should just be taking a request, and returning an appropriate object. If the process for creating the appropriate object is complex, that should be handled outside the view. Oh and my use of the phrase "you're doing it wrong" is kind of tongue in cheek, and comes from my time doing tech support in my early 20s, where we all thought it was hilariously unhelpful. I agree it's a bit obnoxious, I almost edited it out last night. But I made myself giggle enough that I left it in.
- hitchstory 3y ago>I think that comes down to how comfortable you are with classes and multiple inheritance and what No, not really. Multiple layers of inheritance naturally causes code to lose cohesion no matter how familiar you are with it. It's one of the reasons for the maxim "prefer composition over inheritance". >But in my experience, FBVs become a mess even if they're relatively simple, because of the temptation to keep it all within a single function. If calling functions or classes from within functions is a struggle I dare say you might have bigger problems than whether to use FBVs or CBVs.