loading...
Cover image for Don't Use Django for Big Projects

Don't Use Django for Big Projects

juanbenitopr profile image Juan Benito ・4 min read

Django and Django Rest Framework are great tools for creating REST applications. However, when your application grow up keeping the technical debt low is really challenging. I have suffered these kind of situations many times using Django.

The goal of this article is sharing with you the pains I have found getting bigger and more complex my applicaitons.

DRY (Don’t Repeat Yourself)

This principle is used many times by the Django ecosystem, avoiding duplications in your codes is great, but you need to understand the necessities you are solving. Two different features may have some common parts now, but they might change in the future, understanding when and how your code should be isolated using different components would be the perfect solution, in order to avoid future problems (SRP).

In order to boost your productivity, Django (and its ecosystem) exceed the usage of DRY principle, it save you a lot of work, but the sideways are it generate many couples between different parts of your applications which will generate you future. We will explore when this principle is overused.

Models

The Django models are one of the core features of any Django Application, they provide you access to the database, and they save you a lot of work. Here Django use the models as core entity to avoid you repeat the same them in other components. Despite the good intention, coupling your business entities with your database entities is not a good path you want to walk.

What happen when your database change? you will need to change your models and your business core.

As well there are other Django and DRF components which base part of their features on these models, such as: ModelForms, ModelSerializers, ModelViewsets…

These components have different mission, not only store information or work business data, DAMN IT we have just coupled our database to the whole application (a little messy)

Furthermore you are able to use your models from any app of your project, so when you change any model, you probably are affecting things which shouldn’t be, as well as breaking business use-cases in other places, so… hell I hope you have a high test coverage to catch it, before going to production.

https://cdn-images-1.medium.com/max/1600/1*G6JEDsgJJbBXVupXo8Qoxg.jpeg

Django Model dependency diagram with two applications

Recap, using Django models you are coupling many components of your project, and likely you will lose track which are using them, business, representation, data… If you have many features to maintain good luck!

Serializers

Django Serializers are one of the most useful parts of the DRF library, they allow you serialize different kind of information without sweat, but we must use them carefully, if you mix different kind of entities and start nesting serializers, it will become messy.

The DRY principle invite use to reuse serializers in many use-cases, hoping the business use case is not going to change never…. After a few weeks we have started using those serializers with many other endpoints, and insider another serializers. Refactor the serializer is now an epic tasks. Don’t hear DRY here.

If the previous situation is tedious to resolve, when you add the complexity of the ModelSerializer it becomes almost impossible to solve. The ModelSerializer couple the representation logic to the database. Then, when your representation, or you database change you are in problems.

This might become the ModelSerializer the most terrible thing in the Django ecosystem.

Trust me, NESTING MODEL SERIALIZERS IS NOT A GOOD IDEA, querys to your database will get out under control quickly.

Views

DRF Views are quiet good tools to handle the income requests of your application.

The first problem appearear with GenericViews. Those views try to save you tons of work using a few attributes.

The queryset attribute is the most harmful one, tie your view to the database, and that’s not good. As well as It encourages you to custom the queryset for each use-case using get_queryset method. I discourage the use of this method, when you handle many use cases in the same view is complicated understand which data you want to retrieve each time.

The serializer_class attribute is useful at the beginning when you need a new serializer for each use case this will end up being a torture (same serializer with dynamics fields is worse).

One of the coolest features of DRF, at the beginning, are the filters, they allow you filter easily your set of data, and they are able to handle the most use cases. However when the fields are custom created as annotations, or nested filtering is necessary it will be much difficult to handle.

Django Views try to centralize all the possible logic inside the views, and it end getting too much logic you need to handle in the same place, with many conditions and no much code, but too much possible pitfalls. The nice views quickly become spaghetti code area.

GenericViews and family (Mixins, Viewsets, ModelViewsets…) are pretty nice when you don’t need custom features and many use-cases to handle, doing simple CRUDs is super easy, but when the features are hard you should look for another strategy.

Conclusions

Django and Django Rest Framework are amazing tools to create REST Applications super fast, in order to accomplish your impossible deadline. These advantages don’t come without Although sideways, to Django and DRF help you by coupling many parts of your application and generating many cool features on their own.

Structuring your application from the beginning of the project is an important part for creating a maintainable future. You can use different coding architectures and Design patterns to keep a robust and mantainable project.

Posted on May 16 by:

juanbenitopr profile

Juan Benito

@juanbenitopr

Backend developers working at citibox. Entusiast programmer who like reading, writting and coding!

Discussion

markdown guide
 

Trying not being the devil's advocate here, I have to disagree with some of your considerations. Yes Django + DRF are a great set of tools to help you deliver fast and on deadline.

But, as in any other language/framework some tradeoffs have to be taken into account when your application starts to grow.

As I mentioned Django and DRF are tools. And as such, they have to be chosen carefuly when doing specific tasks. E.g. You mentioned ModelSerializer being evil. It's just a "shortcut" for a specific situation (serialize a model). Even the docs says: "Often you'll want serializer classes that map closely to Django model definitions". If you don't need it to closely map, you shouldn't use it. The same with nested model serializers (you can always fall back to the to_representation).

Some things you mentioned are quite the same for every language/framework. If there's a change on your database, you will have impact on you business logic if the change is not backward compatible (e.g. removing a table field). And that's why we should have tests. Imagine a handwritten query hitting a database with a field that has been removed. That's what will happen in a JDBC PreparedStatement in Java or a non-ORM PHP application.

Don't get me wrong. Django and DRF do have problems. I faced a bunch of them. As I did using Java + Spring Boot and other combinations in other languages.

All that being said, I guess you have a very good point on your conclusion: know your tools and know how you want to build your application, most importantly.

 

Hi Alexandre,

Thanks for your comment, I think you have missed the goal of the article.

Hoewer I said I wanted to share my frustation using Django, actually the goal is helping other people who choose django to be careful with the features they use, that features might be harmful in the long term.

I didn't say the rest of the frameworks are pefect, not even close. Everyone has their own issues. Hoewer every framework have issues, many of them try to separate the different layers of your applications consistently. When you isolate the main layers (Representation - Business - Database), your database changes don't need to affect your business logic, even you can change the representation of you data without affecting your business or the Database. For example, you can calculate the field you have just removed, and it won't affect your business logic.

Decoupling the main parts of your application will help you a lot. If you decouple them in a good way, you can modify each layer without affecting your whole application, and when you refactor some parts, you will be so greatful for that :).

A highly test coverage is not necessary good, the tests has to be mantained, when I commeted that part in the article, it is was not something good you need the tests, the tests help your project to be reliable, but the architecture should be the first line of trust.

As you said every tool have their own flaws, I only wanted to show the django issues for the people who is doing any project.

I recommend Clean Architecture (from Robert C Martin), if you have not read it yet. The book shows why it is important keeping the differnt application layers isolated.

We agree about knowing the tools is one of the main points, this article try to help other people to understand better these tools.

Thank again for your comment!

 

Hi, there.
Thank you for sharing your experience and insight.
Since the title is "Don't Use Django for Big Projects"
So what framework do you end up using?

 

Actually, I use django pretty much, the title is pretty unfair. You can use django following some recommendations to keep a low coupling:

  • Don't let the framework decide the architecture for you. The frameworks are toolbox, but they shouldn't decide how your project work (Clean Architecture from Robert C Martin)

  • Keep the different parts of your applications decoupled and isolated

  • Create a consistent hierachy of components

Following these recommendations you can use any framework without problem. Besides the recommendations, these frameworks are interesting for me:

I want to dive depper in my next article about the above recommendations, giving a few examples about how to implement them.