Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django: Fat models and skinny controllers?

This is a general architecture question. I read in many places that in an MVC framework, (1) models ought to be fat, and controllers ought to be skinny. But I also read that (2) the details depend on the framework you're developing in. So, what if you're developing in django?

My experience with django is that a lot of the logic ends up getting put into views and forms. Not the "business logic," but the details of handling requests, sessions, etc. In terms of lines of code, these details often outweigh the business logic of manipulating model objects. Am I doing something wrong, or is this how django works?

like image 879
Abe Avatar asked Dec 21 '11 13:12

Abe


2 Answers

MVC is not a universal solution and most of the time it's done wrong and can't keep its promises: in practice modifying a model will require modifications in the controller as well, because it's done wrong. If you really want loose coupling between Model and Controller then - and people usually ignore that - you have to use a service pattern (open as image). Which almost nobody actually does.

Instead of blindly adhering to the MVC fuss/pseudo-pattern in the PHP world, Django takes a pragmatic approach. Because in the common reality of software development, the developer programs things for the user to see. Then the user (your boss, client, customers ...) will "see" your work, and eventually give his opinion about how he wants to "see" it in the end. By using Django, the developer can take a more "view oriented" development pattern and guess what: it makes deadlines easier to respect and users more satisfied. If you think about it, it has its "nosql-ish" idea that the view (general view, not django view) should be the boss of what's going on behind the scenes.

I'd like to thank Django for not doing MVC wrong, unlike 99% of the PHP MVC implementations out there.

On the other hand, Django is the only framework that allows proper isolation between applications. Each application can have:

  • models
  • views
  • templates
  • urls
  • static files
  • tests
  • forms
  • optional addons (admins, filters for ajax-selects, permissions for django-authority, notifications for django-notifications, etc, etc)

So even if your models/views/templates will be tied, your project can be relevantly divided in small (also reads: easy to maintain) and loosely coupled applications. Only related models/views/templates/stuff are tied together. A big fat models script with a big fat views and urls script is not what you want in Django. For example, you don't want two model classes like Article and FootballMatch to live together, you want to make an "articles"/"blog" app and a "sport" app which can live independently. Of course sometimes they must be tied, in that case it's doable at the project level in 90% of the cases (you'd make another app, "blog_sport" if you happened to need to tie in models or templatetags).

For example, it's a super common practice to define a get_absolute_url() method in the Model class. Yes, your model class which in theory has to contain only business logic, is now tied with your urls definition. How bad is this in practice ?!! Well actually it's brilliant because it takes two seconds to add this method and you can then use it anywhere you use a model: be it in views or templates. Also, other applications (e.g. django.contrib.admin) will use it.

Another slightly more complicated example of Django brilliance is that queries are lazily evaluated. Which means, your view function/class will define a query like blog_list = Blog.objects.all(), but the query will actually be executed in the template if it calls like {% for blog in blog_list %}. So business logic happens in the template in that case, and if something fails before the rendering of the template: you saved a query. But that's not all, if your template just displays a count {{ blog_list.count }}, the select query will not be spawned at all and just a count query will be executed. The "general view" decides what business logic is needed. That's far from the promises of MVC but be honest: how practical is that ?

My point is that you can apply theory the wrong way, do it right (which reduces your choice to like 5 web frameworks all languages included), or just get to the point in an elegant and pragmatic way to get your job done the Zen way in no time: that's Django's choice.

like image 190
jpic Avatar answered Oct 15 '22 12:10

jpic


It depends of what your application is about, but the beauty of Django is that it does not enforce you to put your logical code in your views or in your models, this is your call.

If you think that some logic is strongly related to your model then you can make a method of it. The rule (for me) is that your model should be agnostic about the environment (web-app, Crontab running a manage command, etc).

My policy is to try to put the bare minimum in my models.

By the way, you don't plan to handle request and sessions in your models don't you ? that is a bad idea.

like image 37
Stan Avatar answered Oct 15 '22 10:10

Stan