Introduction
I have been working with the Django framework since 2012, and see some trends that have a foundation more in dogma than utility. One such trend is subclassing the AbstractBaseUser model and getting Django to recognise it thru the AUTH_USER_MODEL setting. The reason for doing this is to change the field called username into a field called email or phone or something else that is unique to your users, and having some user_type field to determine the user as staff or visitor to the site, and using permissions and other processing to make sure that the user experience is appropriate, and the authorization is appropriate. I put forward the argument that there is a better way.
The Widely Accepted Implementation of User
This code is a snippet of a web application to provide curriculum material to students. Four types of user visit the site.
- Staff who update the content by logging into the Content Management System (CMS)
- Teachers who can see the teacher notes and may also update content via the CMS
- Students who can see the student excersizes

Each user type is assigned a role. In this particular application, it was required that the teachers and students not use passwords to log in to the site, but the staff needed to authenticate, as they had access to the content management system, so a default password was set for all new users, then any users that had to be staff would have their role changed, and the password set.
The first problem was the backend CMS was Django CMS, and it had no mechanism to differentiate users according to role. Any authenticated user was expected to be someone with some access to the CMS, so the tool bar that was associated with every page appeared at the top when teachers and students were logged in, as well as staff.
The second problem was when it came time to update Django and Django CMS. The User model is fundamental to Django and Django CMS. Both modules are separate but intrinsically entwined within both is the User model. When you come to update Django or Django CMS in this scenario, it wont work. Something will break. You fix it, then something fundamental breaks. You try to fix it and fail. You set exception checking to bypass errors. You try to turn authentication off entirely so the thing can be used, and then you realise that the thing can't be updated, and try your best to keep things running for as long as you can on an operating system and applications that are 15 years old, until TLS 1.0 is depreciated and the latest webserver running on the antiquated operating system can't run TLS 2.0 which is now required by all modern browsers.
The first problem was the backend CMS was Django CMS, and it had no mechanism to differentiate users according to role. Any authenticated user was expected to be someone with some access to the CMS, so the tool bar that was associated with every page appeared at the top when teachers and students were logged in, as well as staff.
The second problem was when it came time to update Django and Django CMS. The User model is fundamental to Django and Django CMS. Both modules are separate but intrinsically entwined within both is the User model. When you come to update Django or Django CMS in this scenario, it wont work. Something will break. You fix it, then something fundamental breaks. You try to fix it and fail. You set exception checking to bypass errors. You try to turn authentication off entirely so the thing can be used, and then you realise that the thing can't be updated, and try your best to keep things running for as long as you can on an operating system and applications that are 15 years old, until TLS 1.0 is depreciated and the latest webserver running on the antiquated operating system can't run TLS 2.0 which is now required by all modern browsers.
A Better Way

The User model for staff is just the standard Django model. What we need for Students and Teachers is a model that takes a name and email address, links them to their school, and links them to the excersizes that they have done.