7 ms·
I think there are too many concepts in this, but rather than being negative, here are some tips: Always keep your models slim. Don't stuff template related stu
by olau 4y ago
I think there are too many concepts in this, but rather than being negative, here are some tips:
Always keep your models slim. Don't stuff template related stuff in there. You need to look at those models often, so compact is a win. course_has_finished(course) is not much longer than course.has_finished(), and will allow you to expand the functionality as time goes on. Do precomputation if you need the information in a template - that keeps your templates simpler and allows you to easily expand the complexity of the precomputation.
Don't use class-based views, at least not outside very specific niches like the Django admin. Class-based views will transform a simple, composeable call stack into a ball of inheritance mud. Inheritance is not a good code reuse tool.
Don't make separate apps in the same project, unless the project actually consists of several different, completely independent projects. You can make subdirectories without making apps, and thus avoid dependency hell.
Also be wary of the formerly South, now built-in migrations stuff. It's built around a fragile model (perfect history representation), so has lots of foot guns.
And be wary of 3rd party libraries with their own models. You can spend a lot of time trying to built bridges to those models compared to just doing what makes sense for your particular project. I think 3rd party libraries are perhaps best implemented without concrete models - duck-typing in Python let us do this. This includes Django itself, by the way. User profiles didn't become good until Django allowed you to define the user model yourself.
- drcongo 4y agoAgree with all of this, although I do like class based views.
- nicolaslem 4y agoMe too, I think it's important to acknowledge that no approach is perfect. Pick your poison.
- VWWHFSfQ 4y agoAgree with migrations. I've spent a lot of time doing migration surgery to get things back into a consistent state. But mostly I've found that if you just let Django manage the database how it wants to then things will be fine. But get very familiar with merge migrations and fake migrations if things start to go awry. I disagree with the perspective on CBVs though. I've been programming Django since 0.96 and CBVs have made nearly everything easier and better for me.
- rlawson 4y agoGood points. Agree with slim models and I personally like a service layer. FBVs are great, CBVs are ok, GCBVs are of the devil
- roland35 4y agoIs there a better alternative to South (built-in now) for migrations? I always had issues but figured it was the de facto for a reason.
- Daishiman 4y ago> Don't use class-based views, at least not outside very specific niches like the Django admin. Class-based views will transform a simple, composeable call stack into a ball of inheritance mud. Inheritance is not a good code reuse tool. People always say this but well-structured CBVs keep a generic interface that you'll be really glad that exists when you have 80 views spread across 10 apps. Composing function-based views is a PITA and when you're building an API with a bunch of auth/serialization/cache extras being bolted on it's way easier to keep disciplined and ordered. It is _trivial_ to mess up the order of callers for these things inside function-based views.
- rajasimon 4y ago> Don't make separate apps in the same project, unless the project actually consists of several different, completely independent projects. You can make subdirectories without making apps, and thus avoid dependency hell. I wrote an article on this. My goto strategy is to create a project/core/views.py,models.py,apps.py,tests.py
- cjohnson318 4y ago> I wrote an article on this. Link or it didn't happen :)
- rajasimon 4y agolol forgot to include
- cjohnson318 4y agoAre you talking about this: https://rajasimon.io/blog/django-project-structure/ https://rajasimon.io/blog/django-project-structure/
- rajasimon 4y agoyup that's that. Thanks for finding it for me :)
- randlet 4y ago"Also be wary of the formerly South, now built-in migrations stuff. It's built around a fragile model (perfect history representation), so has lots of foot guns." My experience has been opposite so I'd be interested in hearing your experiences if you are willing. I have been using the built in migrations since day 1 on a medium sized Django project with 350+ migrations and migration issues for our project have been exceedingly rare. edit: We have a small team of developers, so merge migrations are very rare for us, which might be a contributing factor.
- rowanseymour 4y agoSame here. If I was starting a non-Python project tomorrow I'd consider using Django to manage the database schema - especially now that we can describe custom indexes and constraints in migrations. Our project has gone thru over 1000 migrations so far tho we squash them down to 50 or so about once a year.
- jbellew 4y agoThats interesting, if I was using TypeScript to access the data, how would I keep the schemas in sync between TS and python?
- rowanseymour 4y agoI've never used TypeScript to talk to a database but there might be tooling to generate classes from tables. Even if there isn't, manually keeping some TypeScript classes in sync might still be worth the effort, for being able to manage schema migrations easily elsewhere.
- dnadler 4y agoWe do this manually along with a pydantic as a middleman between Django and TS. Works pretty well and is not a major inconvenience to keep things aligned.
- anileated 4y agoCan introspect and export Django models to JSON schema or similar, then in TS read it and use compiler low-level API to generate types. There may be libraries for either stage…
- switch007 4y agoApps should be buried deep in the documentation in some “super advanced” section and not advocated much at all
- rowanseymour 4y ago> You can make subdirectories without making apps, and thus avoid dependency hell. It's hard to get 100% right and thus our projects always have a few lazy foreign key relationships and inline imports to avoid cyclical imports... but I think our code is easier to manage because we try to model the dependency relationships by having things in separate apps. > Also be wary of the formerly South, now built-in migrations stuff Our experience from South to 4.x has been that the models/migrations system has matured significantly and is probably now the main selling point for Django for us.
- cjohnson318 4y agoI'm currently in circular import hell. My business logic has Jobs and Loads, and they both need to update each other under certain circumstances. Should these two things/monstrosities be lumped into the same app?
- hbrn 4y agoThe short answer is yes. The long answer is if two entities are updating each other you might benefit from shifting all update responsibilities to one of them. Or even to a third entity that knows about both and keeps those two isolated from each other.
- cjohnson318 4y agoWoof. Thank you so much. I like the idea of a third party, like a mediator. Would that mediator be another app? Or should it be some module sitting in the project directory? (I'm not even sure Django would import something like that.)
- hbrn 4y ago> Would that mediator be another app? Yes! It is an app that might not even have any model classes. But it will contain business logic. And it will probably speak domain language, which is great. If you're lucky, those two other apps will become pluggable. You will probably never replace them, but separation of concerns is always nice. The downside of course is that you will have 3 apps instead of 1. That's the balance you have to maintain.
- rglullis 4y ago> Always keep your models slim. As simple as possible, but no simpler. Django models are meant to deal not just with the data, but also with business logic. If `course.has_finished` is a property of the course, why would you want to have a separate function outside of the class? > Do precomputation if you need the information in a template If the precomputation is only needed in a template, you can (should, IMO) use template tags. > Don't make separate apps in the same project (...) avoid dependency hell. My current pattern here has been to create one "core" project where I represent all the internal models of the domain of the application, and "adapter" apps if I want to interface/integrate with anything from the external world. This makes it easier to extend or replace third-party tools. > (Migrations) It's built around a fragile model. I wouldn't call it fragile, quite the opposite. There are some annoying limitations for sure (I didn't find a reliable way to change the primary key of a model, except for creating a whole new model and migrating the data to it), but I think they are due to a matter of strong safety that the migration can only be done if it consistent.
- well1912 4y agoAt my current company, we've had many teams over the years fail to make business logic in model methods work, and I think many other people have had similar results. The issues usually boil down to some combination of "business logic is too coupled to the data model" and "this method lives at an intersection of these two models and creates weird dependency problems". I now feel that Django puts you down a path for failure by naming the DB layer "models" and not giving users a decent place to put cross-model domain logic. My current preference is a functional core-imperative shell-style architecture where as much code lives in the functional core as possible. It's not very elegant with Django but it works fine. Cosmic Python (really accessible and fairly quick read if you have the time: https://www.cosmicpython.com/book/preface.html https://www.cosmicpython.com/book/preface.html) has examples that are similar.
- rglullis 4y ago> The issues usually boil down to some combination of "business logic is too coupled to the data model" and "this method lives at an intersection of these two models and creates weird dependency problems". Refactor is not a dirty word. The problems you are describing seem to be more of the nature of having too many things concentrated at specific model classes, and that this model should be decomposed, broken down. This is not a Django-specific issue.
- yiiii 4y ago> Always keep your models slim. At least never put your business logic in your views, forms or even templates.
- collyw 4y agoI am in more or less in agreement, except for forms. Surely some validation could be considered business logic.
- dec0dedab0de 4y agoAlways keep your models slim. Don't stuff template ...course_has_finished(course) is not much longer than course.has_finished() I disagree with this. When trouble shooting or expanding code it is super convenient to import a model and have all of your methods on auto complete. Especially when you need the same functionality in a view, a cron job, a celery task, and an DRF end point. If you want to keep it clean you can put all your methods in a mixin class and import it from another file. Also be wary of the formerly South, now built-in migrations stuff. Things are much better than they were in South. But yes be careful, rule of thumb is always move forward. Don't use class-based views Please. For the love of God, always use class based views for almost everything. Almost everything you need is a variant of one of the built in class based views, don't make me read your copy/pasted reimplementation of it.
- cjohnson318 4y ago> Please. For the love of God, always use class based views for almost everything. This. 100%. Leverage as much pre-built stuff you can, especially with something as important as your HTTP layer. Whenever I run out of CRUD verbs for a model and I need to add a custom endpoint, I'll implement it in a separate APIView sublcass. Convention over configuration; write boring code.
- asalahli 4y agoIn my view (hehe), Django's class based views is a good idea implemented poorly. In theory you should be able to use any of the built-in class based generic views with minimal customizations to suit your needs, except when you want to do such customizations you're left dealing with a huge inheritance tree of mixins. It's all magic unless you know or wanna read the documentation on what each mixin brings to the view, that is _if_ you know what mixins are involved exactly, of course.
- collyw 4y agoAre you aware of https://ccbv.co.uk/ https://ccbv.co.uk/? After I discovered that, class based views became easy.
- collyw 4y agoI disagree with almost everything you have said. Fat models think controllers is the suggested strategy. It works well in my opinion / experience, though I guess it could get out of hand on very large projects. There is something that feels very unnatural and unintuitive about your course_has_finished(course) versus course.has_finished() example. This was one of the principles behind OOP, keeping your data and functions / methods together, though I know OOP isn't trendy these days. It's far more natural to have it as a method of course than some random function, stored who knows where. I worked on a system with this type of design, it was pretty bad. One thing I would like to see for larger projects is the ability to easily split models into separate files - a bit more like Java does with one class per file. Maybe you can do this already. Class based views mean that a lot of code is written and tested for you. I'll agree that your view does need to be somewhat "standard" in what it's doing (anything you would see in the admin, list, create, edit, detail, login, etc), so if you have something more complex multiple forms in one view, then thy don't give a great deal of advantage. In that situation I would still likely choose a basic View class over functional views, but more for consistency. I am probably in agreement on separate apps. Migrations are one of the best features of Django. I have just spent 4 years working on a a system without them and it was a shambles as you would expect. Everyone is scared to make database changes, so you get a ton of shitty application code to compensate for shitty database modelling. Tech debt in other words. I can't think of any 3rd party apps where I have used the models directly, or if I did it was frictionless enough for me not to remember. So no real opinion on that one. 3rd party apps can be pretty hit and miss, especially if they get abandoned as you upgrade Django, so I would say use with caution, particularly for more obscure ones (just been revisiting django-celery-beat, that's been around for years so I doubt it's going away).
- __pache__ 4y agohow is this possibly the highest upvoted thing here on django. it's like the opposite of good opinions.. they're bad opinions! _(99% kidding, but i disagree with most of this lol)_