How to Create User Model Using FastAPI and Django

Learn to create a User Model with FastAPI and Django.

Picture of Nsikak Imoh, author of Macsika Blog
How to Create User Model Using FastAPI and Django written on a blank white background
How to Create User Model Using FastAPI and Django written on a blank white background

In the previous tutorial, we learned how to combine Django with FastAPI to build a blog covering all aspects of a CRUD project.

We created the models and ORM in Django and a CRUD API Endpoint with FastAPI.

We also set up: validations using pydantic, Django ASGI and WSGI to work together with FastAPI, and a basic API versioning with FastAPI.

In this tutorial, you will learn to create a User Model with FastAPI and Django.

The codes for this tutorial build upon the previous one.

Step 1: Create a Django Accounts App

  • How to Create a Django Accounts App

    
    	python manage.py startapp accounts
    
    Create a Django Accounts App.
  • Add accounts to Installed App in Django Settings

    
      INSTALLED_APPS = [
    	...,
    	"accounts",
      ]
    
    Add accounts to Installed App.

Step 2: Create a Django User Model and Manager

  • How to Create a Django User Model with Fullname Field and Email

    The code below will create a User Model Field with a fullname and email as a username.

    
    	from django.contrib.auth.models import AbstractUser
    	from django.db import models
    	
    	from accounts.managers import UserManager
    	
    	
    	class CustomUser(AbstractUser):
    		username = None
    		first_name = None
    		last_name = None
    		password2 = None
    	
    		name = models.CharField(max_length=150)
    		email = models.EmailField(max_length=255, unique=True)
    	
    		objects = UserManager()
    	
    		USERNAME_FIELD = 'email'
    		REQUIRED_FIELDS = ['name']
    	
    		def __str__(self):
    			return self.email
    
    Create a Django User Model.
  • How to Create a Django Manager for a User Model

    Create a manager.py file in the accounts app and add the codes below.

    
    	from core.utils import get_first_name, get_last_name
    	from django.contrib.auth.models import BaseUserManager
    	from django.core.exceptions import ValidationError
    	from django.db import models
    	from django.utils.translation import gettext_lazy as _
    	
    	
    	class UserQuerySet(models.QuerySet):
    		pass
    	
    	
    	class UserManager(BaseUserManager):
    		use_in_migrations = True
    	
    		def get_queryset(self):
    			return UserQuerySet(self.model, using=self._db)
    	
    		def _create_user(self, name, email, password, **extra_fields):
    			"""
    			Create and save a user with the given name, email, and password.
    			"""
    			if not email:
    				raise ValueError(_("Users must have an email address"))
    	
    			fullname = name.split()
    			if len(fullname) <= 1:
    				raise ValidationError(
    					_('Kindly enter more than one name.'),
    					code='invalid',
    					params={'value': self},
    				)
    			for x in fullname:
    				if len(x) < 2:
    					raise ValidationError(
    						_('Kindly give us your full name.'),
    						code='invalid',
    						params={'value': self},
    					)
    			email = self.normalize_email(email)
    			name = ' '.join(map(str, fullname))
    			user = self.model(name=name, email=email, **extra_fields)
    			user.set_password(password)
    			user.save(using=self._db)
    			return user
    	
    		def create_user(self, name, email=None, password=None, **extra_fields):
    			extra_fields.setdefault('is_staff', False)
    			extra_fields.setdefault('is_superuser', False)
    			return self._create_user(name, email, password, **extra_fields)
    	
    		def create_staff(self, name, email, password, **extra_fields):
    			extra_fields.setdefault('is_staff', True)
    			extra_fields.setdefault('is_superuser', False)
    	
    			if extra_fields.get('is_staff') is not True:
    				raise ValueError('Staff must have is_staff=True.')
    	
    			return self._create_user(name, email, password, **extra_fields)
    	
    		def create_superuser(self, name, email, password, **extra_fields):
    			extra_fields.setdefault('is_staff', True)
    			extra_fields.setdefault('is_superuser', True)
    	
    			if extra_fields.get('is_staff') is not True:
    				raise ValueError('Admin must have is_staff=True.')
    			if extra_fields.get('is_superuser') is not True:
    				raise ValueError('Admin must have is_superuser=True.')
    	
    			return self._create_user(name, email, password, **extra_fields)
    	
    		def get_full_name(self):
    			return self.name
    	
    		def get_short_name(self):
    			return get_first_name(self.name)
    	
    		def get_first_name(self):
    			return get_first_name(self.name)
    	
    		def get_last_name(self):
    			return get_last_name(self.name)
    
    Create a Django Manager.
  • How to Add an Admin for a Django User Model

    
    	from django.contrib import admin
    	from django.contrib.auth import get_user_model
    	from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    	from django.utils.translation import gettext_lazy as _
    	
    	from .forms import UserAdminChangeForm, UserAdminCreationForm
    	
    	User = get_user_model()
    	
    	
    	class UserAdmin(BaseUserAdmin):
    		# The forms to add and change user instances
    		add_form = UserAdminCreationForm
    		form = UserAdminChangeForm
    		# inlines = [
    		#     ProfileInline,
    		# ]
    	
    		fieldsets = (
    			# (None, {'fields': ('password',)}), # This simply shows the hashed password field
    			(_('Personal info'), {'fields': ('name', 'email',)}),
    			(_('Permissions'), {
    				'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions',)
    			}),
    			(_('Important dates'), {'fields': ('last_login', 'date_joined',)}),
    		)
    		# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
    		# overrides get_fieldsets to use this attribute when creating a user.
    		add_fieldsets = (
    			(None, {
    				'classes': ('wide',),
    				'fields': ('name', 'email', 'password1', 'password2')}
    			 ),
    		)
    		list_display = ('id', 'email', 'name', 'is_active', 'is_staff')
    		list_display_links = ['email']
    		list_filter = ('is_superuser', 'is_staff', 'is_active', 'groups')
    		search_fields = ('email', 'name')
    		ordering = ('email',)
    		list_per_page = 10
    		filter_horizontal = ('groups', 'user_permissions',)
    	
    	
    	admin.site.register(User, UserAdmin)
    
    Add an Admin for a Django User.
  • Add the helper functions below to the utils.py file in the core module

    
    def get_first_name(self):
    	if isinstance(self, bool):
    		pass
    	else:
    		names = self.split()
    		return names[0]
    
    
    def get_last_name(self):
        if isinstance(self, bool):
            pass
        else:
            names = self.split()
            return names[-1]
    
    Add helper functions.

Step 3: Migrate the Models

Run the commands below to migrate our user model's data.


python manage.py makemigrations
python manage.py migrate
Migrate our user model.

Step 4: Create a Super User

Run the command below to create a superuser for our app.


	python manage.py createsuperuser
Create a Super User.

If you successfully created a superuser, run the django server and log in to the admin page to test our models.


	python manage.py runserver
Run the django server.

Wrap Off

In this tutorial, we focused on Django mainly to add a user model to the project.

Next, we will improve the accounts app to be production-ready. We will use Django Rest Framework and Django packages like Django AllAuth, dj-rest-auth for authentication and authorization.

Next Tutorial — 4 Ways on How to Improve Your Django ModelsGet the Complete Code of Django and FastAPI Combo Tutorials on Github.

Connect with me.

Need an engineer on your team to grease an idea, build a great product, grow a business or just sip tea and share a laugh?