Links

create-user-model.mo

Owner: Sammy Teillet

Context

  • You have a Django project installed.
  • You need to handle different types of users (for instance an Actor, a Producer, a Director) that will all inherit from the user, but will have different properties.
  • You want to handle them from the admin.

Prerequisites (~45min)

Situation

  • You have a basic user model with a name.
  • You want to create another type of user, a Mayor that has a City (the city is a foreign key to a City model).
  • You do not want to override the classic user model.
  • You want to create a Mayor from the admin
  • You want the newly created Mayor to be part of the Staff (Staff User can access the admin, but they are not SuperUser)

Steps

Add the Mayor model (5 min)

  • In the models.py file, where the User is defined, create a new class that inherits the User
# You should have the User in the same file, or from app.models import User
from django.db import models
from django.contrib.auth.models import User
class Mayor(User):
city = models.ForeignKey('locations.city')
class Meta:
verbose_name = "Mayor"
  • Create the migration file: ./manage.py makemigrations or docker-compose run django_container_name ./manage.py makemigrations
  • Run the migration: ./manage.py migrate or docker-compose run django_container_name ./manage.py migrate
Check 1: Run the show migration command to see the new one ./manage.py showmigrations

Create a Mayor from the admin (5 min)

  • In the admin.py, where the User model is added admin.register(User)
  • Add the following:
from .models import Mayor
from django.contrib.auth.admin import UserAdmin
@admin.register(Mayor)
class MyMayorAdmin(UserAdmin):
pass
Check 1: You now see the Mayor in the admin. But all the forms (form to add a Mayor, form to change/update a Mayor) are the same as for the regular User.

Override the admin form to add a Mayor (10 min)

  • In the admin.py when you declared your MyMayorAdmin class, you can choose the fields you want to display in the form by overriding the add_fieldsets property. You can readme more about add_fieldset here:
  • You need to know the fields you want to display. username, password1 and password2 are default fields of the "user admin add form"
  • In our case:
from .models import Mayor
from django.contrib.auth.admin import UserAdmin
class MyMayorAdmin(AuthUserAdmin):
add_fieldsets = (
('User Profile', {'fields': ('username', 'city', 'password1', 'password2')}),
)
Check 1: You now see the city field in the "add new mayor" form.

Give admin property to mayor user (10 min)

  • You can manually set a user to be part of the staff, you can also override the save method of the AddForm so it changes the property is_staff to True
  • First create a form that inherits the AddUserForm and override the save method (see overriding custom model method):
from django.contrib.auth.forms import UserCreationForm
class MyMayorCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = Mayor
def save(self, commit=True):
user = super().save(commit=False)
user.is_staff = True
if commit:
user.save()
return user
  • Then use this form in the MyMayorAdmin class:
@admin.register(Mayor)
class MyMayorAdmin(AuthUserAdmin):
add_form = MyMayorCreationForm
Check 1: When I create a mayor, I see that it is staff user in the detail view of the mayor.