I had been writing for 1 year with FastAPI after 5-year experience with Django. And here what I have learned.

Daria Plotnikova
6 min readAug 6, 2023

--

For whom this article is written — for people who just started their way in backend development and are deciding now what a framework to choose, either FastAPI or Django. Also the post may be interesting for Djangonauts, who consider switching to FastAPI.

You will not find deep comparison of these two frameworks and benchmarks. Only my own opinion is presented here. So, let’s start!

1. FastAPI generates awesome swagger UI for your API

Yes, Django has Django Rest Framework which creates API documentation. But if you are a newbie, figuring out one more huge library with a lot of new concepts (serializer, view set, etc.) may be really stressful for you.

Also it may turned out that your company doesn’t use DRF because of some strong reasons and then developers have to write API generator by their own. It is not productive.

2. At this point amenities of FastAPI for begginer-developers run out:)

If you want create some minimal valuable project instead of the simpliest GET /ping returnung {response: pong}, you have to work with any storage. Usually it is a relational database, so you need an ORM (object-relation mapper), typically sqlalchemy. To manage a database schema you have to rely on some migration manager, for example alembic.

If you need an admin system out of the box, then FastAPI probably is not the best choice. You will spend your time looking for and comparing admin systems for FastAPI, which may be easily integrated with your database schema and which includes role-based access management.

If you are experienced developer, than this process of mixing different libraries will not take too much time, but for newbie it may waste a lot of hours of investigation.

3. Django ORM vs SQLAlchemy

  1. Concept
    There are tons of holy wars in the internet about “What is better Django ORM or SQLAlchemy”. I’d say that it was a little bit hard to change your mindset to use Unit of work (UoW) SQLAlchemy’s pattern instead of Active record (AR) Django’s pattern. This approach defines how you as a developer should use ORM’s objects to interact with models (when, which part of your code must call needed methods to interact with database and modify it’s rows).
    The main difference, as I think, is that in Django usually you don’t mind about when data from python ORM’s models will be saved or obtained from database. You may force getting data (e.g. packing to JSON for response, full list for getting objects is there), you may call Model.save() method when you want. But in general, you don’t have 100%-ability to control ORM behavior. In SQLAlchemy you, as a developer, must clearly specify when and how your data should be grabbed from a database, when ORM’s objects must affect a database.
  2. Choice fields in models
    One huge thing which I faced with is that SQLAchemy + alembic doesn’t realize, if you used Enum as choice-field in your model and changed Enum’s content.
    To specify choice-field you have special syntax in Django. When you change choices’ enums or iterable, Django ORM easily finds the difference to the previous state and generates ready-to-apply migration automatically.
    But if you use alembic migration tool with SQLAlchemy ORM, you will not have any help there. You have to write migration’s content adding Enum’s values on a database’s level manually every time you change Enum presented choice-field in model in python code.
    I’d need to clarify that I from that sort of a developers, who things that there should be as many as possible restrictions on a database level to prevent terrible bugs when your broken code ruins you data by writing to a database some invalid data. This is why I really like setting up choice-fields with Enum. Working with alembic in this case is painful.
  3. ORM documentation
    I really like Django’s documentation. It contains both — an exhaustive API explanation and also full example, which layer-by-layer immerses developer understanding why some syntax constructions are used for and how they work . When you are newbie in web development, you just have to follow step-by-step beginners guide and don’t need to think of something.
    Of course SQLAlchemy has its beginners guide too. But, as for me, it is just scattered pieces of code. For people, who are not familiar with general idea of how web apps may be designed, it is really confusing where to place these pieces.
  4. API framework documentation
    One one hand as I said in the previous paragraph, Django’s ORM docs are amazing. On another hand FastAPI’s documentation good in its own way. If you pass through it, you learn not only FastAPI’s features, but also it introduces you general web and python concepts, e.g. typing, OpenAPI, authentication mechanisms, etc.. Django’s documentation only highlight how this certain python web framework works and nothing more.

Let’s touch programming concepts, which the most developers usually apply working with Django or FastAPI.

  1. Dependency injection (DI)
    This is one of the most commonly used mechanism in FastAPI. Developer is immediately invited to use this approach writing HTTP endpoints in the tutorial.
    This mechanism leads to write code in SRP- (Single Responsibility Priciple) and DRY- (Don’t Repeat Yourself) style. You may specify dependency function, which do certain thing, e.g. returning current user from the request object, and reuse in every time you need user in your code in endpoint.
  2. Overrides for testing
    Moreover, as FastAPI provides DI mechanism out of the box, it’s possible to override your dependency function for tests. Now you don’t need to monkey patching them using ugly constructions like @patch(“app.mymodule.func_name_to_patch_in_tests”)
  3. Project’s structure
    Django provides project template, explained in docs. It generates project with hard-coded apps’ structure inside just in a second with only 2 commands — startproject and startapp. Very convenient, isn’t it? Yes, but, no.
    Business logic usually is placed inside this apps (unfortunately, I’ve never seen any project where developers have separated core logic in standalone module). When your project is small, it doesn’t disturb you. But if your projects seems to be huge application, it may be hard to separate business logic and endpoints, because there are plenty of biderectional dependencies between modules, e.g:
    Project contains 3 apps. User app contains buy_books.py module which describes logic of buying book by current user. This module depends on book/models.py and it is dependant for user/views.py. Vice versa there is upload_book.py module describing logic of uploading book to the system by author. Author should be user of this application it means, that book/upload_book.py depends on user/ module. But also it is dependant for book/views.py:
- myproject/
- user/ # app
- models.py
- buy_books.py # business logic to buy book by user
- views.py
- book/ # app
- models.py
- upload_book.py # business login to upload book by author
- views.py
- store/ # app

This is quite typical project’s structure (at least in my experience) with a lot of cyclic links between modules caused, as I think, by Django’s documentation. There is no attention to project design at all.
Opposite to Django, FastAPI presents a guide how developer should structure code in an application. It may help do less design mistakes at the beginning with new framework.

Conclusion

For the last 1.5–2 years, working on a Django project, I have been looking towards FastAPI, and it seemed attractive. But some questions remained unanswered, mainly related to testing — how to test my code? how to recreate the database and erase data between tests? etc. The lack of batteries included was also a little repulsive, as it is done in Django. I just want to sit down and start writing code, without choosing technologies, libraries and approaches.

Now I am using FastAPI for 1 year

Now, after working with FastAPI for 1 year, I can say with confidence that it is a great tool if your task is to write APIs for client applications. Using it daily in my work project, I found answers to all the questions I had earlier. But FastAPI has significant limitations that can make this framework not the most effective for your tasks, for example, the lack of a good role-based admin panel. Limitations in comparison with Django ORM generation of migrations in alembic. Perhaps there are some other features that I haven’t encountered yet.

Don’t be afraid to test new technologies in your work. But in any case, before using technology, always check it with your task and choose the most suitable one.

--

--