Index / Blog / Django-swap-user

Open-sourcing django-swap-user to simplify custom user models

By default, the user model in Django framework includes an email, username, and password. But there are often situations where it is necessary to extend and replace the default user model. So our Python Teamlead wrote such a wrapper and open-sourced it.

June 2022

Everyone knows that Python has a very popular Django framework. By default, the user model there includes an email, username, and password. But there are often situations where it is necessary to extend and replace the default user model.

For example, there are situations where we do not need a username, only an email. Or we need a phone number instead of an email, and the email is not important. In these types of situations, the default model should be changed to a custom one which includes the relevant fields. So, the purpose of the django-swap-user project is to replace an existing model with a custom one.

In addition, authorization by one-time code is now beginning to gain popularity. So we accounted for this scenario in the library as well. When a new user model appears, it has only one field—email or phone number—and a one-time passcode. There is no password stored in the database, and a one-time passcode is sent using any provider that you connect. You get a one-time SMS, which you can use to log in.


Why did we write an entire library for this? When we start new projects, we often need a custom user model. Previously, we copied everything from one project to another, but then we realized—why constantly copy, when you can write a library once and that's it. We wanted to find a ready-made library, but all the ready-made ones were abandoned or out-of-date. So our Python Teamlead, Artem Innokentiev, decided to write this wrapper himself and open-source it.

So, if you are tired of copying a custom user model from one project to other ones—use this package. It will do it all for you!


pip install django-swap-user


Application swap_user is split into several apps:

  • to_email - provides user with email username field
  • to_email_otp - provides user with email username field and OTP (One Time Password) authentication
  • to_phone - provides user with phone username field
  • to_phone_otp - provides user with phone username field and OTP (One Time Password) authentication

Why such an unusual architecture?

If we leave them in one app, they will all create migrations and tables, leading to redundant tables. They will be treated as three custom models within the same app, which causes confusion.

With this approach (where there is a common app which contains internal apps), the user can choose and connect only the specific user model best suited for concrete business logic.

We modeled this approach after the Django REST Framework authtoken application, referenced here.

Utilizing a custom user model at the start of a project

When you are starting a project from scratch, this is the best time to integrate a custom user model, since you haven’t had a lot of migrations or you can easily regenerate them. Moreover, Django's official docs recommend that you use a custom user model, even if you are fully satisfied with the default one. In the future, it will be easier to extend a custom model to fit your use cases.

Incorporating a custom user model in the middle of a project

Adding a custom user model in the middle of a project is a harder way of doing things, but it is still possible.

  • Complete all the steps in the testing database and—ONLY IF all of them were successful—try to apply it in the production environment
  • Please note that these steps fit most cases, but in some circumstances, you may need to adapt to the situation
  • Create a backup of your database
  • Add stable tag into your repository or save a commit hash reference
  • Pray :D
  • Remove all of your migrations in every app of the Django project
  • Remove all records from django_migrations table, for example, with SQL TRUNCATE django_migrations
  • Now you have a "clean" state, so you can change the default model
  • Generate new migrations for all of your applications—python makemigrations
  • Now you need to fake migrate, because you already have all the tables with data
  • First, fake the auth application, because you are depending on this one: python migrate --fake auth
  • Install the library, follow the instructions, and apply migrations
  • Then, fake the rest of the migrations you have—python migrate --fake
  • Run your application!

Plans for the future

In the future, we plan to write better documentation and add implementation to the project. We will slowly add new authorization methods, for example, mixed ones. There are cases where you need to do authorization either by email or by phone, and we would like to add this.

At the moment, everyone can use this project, and we would love to attract members of the community to contribute and help with the development of the project!

And, of course, reach out to us via the form below if you need to develop an open-source solution or are looking for a team of professionals to build a project from scratch!

I planned this library as a set of ready-made custom user models, but at some point, I realized that OTP was gaining popularity. And I decided to add not only user models, but also authorization backends for OTP. Another case was the understanding that it is quite difficult to replace a user in the middle of a project, and the Internet offered disparate solutions to this problem. So I decided to provide a step-by-step guide for changing the model during the active development phase. In the future, I want to expand the functionality - we are thinking about adding authorization for existing models, increasing test coverage, adding more cases to the documentation, setting up CI / CD.
Artem Innokentiev
Python Teamlead, Evrone
Let’s talk about you
Attach file
Files must be less than 8 MB.
Allowed file types: jpg jpeg png txt rtf pdf doc docx ppt pptx.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.