<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rahim Btc</title>
    <description>The latest articles on DEV Community by Rahim Btc (@rahimbtc).</description>
    <link>https://dev.to/rahimbtc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1059568%2F28e8fade-daa4-49d0-8223-68be888f6852.jpeg</url>
      <title>DEV Community: Rahim Btc</title>
      <link>https://dev.to/rahimbtc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rahimbtc"/>
    <language>en</language>
    <item>
      <title>Bulletproof Django API for a TMS project</title>
      <dc:creator>Rahim Btc</dc:creator>
      <pubDate>Sun, 19 Jan 2025 13:32:07 +0000</pubDate>
      <link>https://dev.to/rahimbtc/bulletproof-django-api-for-a-tms-project-3a61</link>
      <guid>https://dev.to/rahimbtc/bulletproof-django-api-for-a-tms-project-3a61</guid>
      <description>&lt;h2&gt;
  
  
  🛡️ Bulletproof Django API for a TMS project 🎓
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we will build a robust web application using Django and Django REST Framework (DRF), designed to serve as a solid foundation for production-ready projects. This is my first tutorial, and it will guide you through the creation of a bulletproof project skeleton with a well-organized structure that adheres to best practices.&lt;/p&gt;

&lt;p&gt;We will manage a collection of books, allowing users to perform CRUD (Create, Read, Update, Delete) operations through a REST API, but with a lot more features, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Good Project Structure: Organizing the project into Django apps, separating concerns, and following a clean directory structure.&lt;/li&gt;
&lt;li&gt;Role-Based Access Control (RBAC): Ensuring secure access by assigning different roles and permissions to users (e.g., admin, author, reader).&lt;/li&gt;
&lt;li&gt;Logging: Setting up logging for better monitoring and debugging in production environments.&lt;/li&gt;
&lt;li&gt;Email Integration: Sending emails for user registration, password reset, and notifications.&lt;/li&gt;
&lt;li&gt;File Upload: Allowing users to upload book images or other media.&lt;/li&gt;
&lt;li&gt;Input Validation: Using serializers to validate data inputs to ensure they conform to expected formats and business rules.&lt;/li&gt;
&lt;li&gt;Swagger for API Documentation: Automatically generating interactive API documentation to make testing and using the API easier.
This tutorial will help you set up a powerful, maintainable, and secure Django application suitable for real-world projects. By the end, you’ll have a well-structured Django project with industry-standard features and practices.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Python installed (version 3.8 or higher recommended).&lt;/li&gt;
&lt;li&gt;Basic understanding of Python and Django.&lt;/li&gt;
&lt;li&gt;pip (Python package installer).&lt;/li&gt;
&lt;li&gt;Virtual environment setup knowledge (e.g., venv).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Setting Up the Environment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Recommended VM Configuration for Your Host:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Memory (RAM): Allocate 8 GB to the VM to ensure smooth performance while leaving sufficient resources for the host.&lt;/li&gt;
&lt;li&gt;Processors: Assign 4 cores (8 threads) to the VM.&lt;/li&gt;
&lt;li&gt;Storage: Allocate 100 GB as planned for the VM's hard disk.&lt;/li&gt;
&lt;li&gt;Network: Use Bridged Networking if the VM needs a unique IP on the local network or NAT for internet access via the host.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setting Up a VM
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Download the Ubuntu Cloud Image: Ensure you have downloaded the &lt;strong&gt;ubuntu-22.04-server-cloudimg-amd64.ova&lt;/strong&gt; file from a trusted source (e.g., Ubuntu official site).&lt;/li&gt;
&lt;li&gt;Open VMware: Launch &lt;strong&gt;VMware Workstation&lt;/strong&gt;, VMware Fusion, or VMware ESXi, depending on your setup.&lt;/li&gt;
&lt;li&gt;Import the OVA file:

&lt;ul&gt;
&lt;li&gt;Click File &amp;gt; Open or Import an OVA.&lt;/li&gt;
&lt;li&gt;Select the ubuntu-22.04-server-cloudimg-amd64.ova file.&lt;/li&gt;
&lt;li&gt;Follow the prompts to import the image.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Name the VM: Provide a descriptive name, e.g., &lt;strong&gt;TMS_VM&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Configure the VM (Adjust Memory, Set Processors, Configure Hard Disk, Network Configuration)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Start and Configure Ubuntu 22.04 Server
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Start the VM&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Login and Update System:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ubuntu@ubuntuguest:~$ sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install Essential Tools:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ubuntu@ubuntuguest:~$ sudo apt install git python3 python3.10-venv python3-pip python3-venv git build-essential -y&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set Up a User:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ubuntu@ubuntuguest:~$ sudo groupadd bulletproof
ubuntu@ubuntuguest:~$ sudo adduser django
ubuntu@ubuntuguest:~$ sudo usermod -aG bulletproof django
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a directory for your project&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ubuntu@ubuntuguest:~$ mkdir /home/django/projects&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Change the group ownership to bulletproof:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ubuntu@ubuntuguest:~$ sudo chown :bulletproof /home/django/projects&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set permissions so that only group members can write to the directory:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ubuntu@ubuntuguest:~$ sudo chmod 775 /home/django/projects&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set the new user's default directory and permissions:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ubuntu@ubuntuguest:~$ sudo usermod -d /home/django/projects django
ubuntu@ubuntuguest:~$ sudo chown django:bulletproof /home/django/projects
ubuntu@ubuntuguest:~$ su - django
django@ubuntuguest:~$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Vscode setup
&lt;/h3&gt;

&lt;p&gt;To set up VS Code for your Django project via Remote-SSH, install the Python and Pylance extensions for Python support. Add Flake8 for linting and Black for code formatting. Install the Django extension for specific project features. Ensure that Flake8 and Black are also installed on the remote VM via pip. Configure the Python interpreter to use the virtual environment, and enable linting and formatting through VS Code settings for a seamless development experience.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create pyproject.toml: This is an optional file for managing project metadata and build configuration. Create it manually or use a template. Example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[tool.black]&lt;/span&gt;
&lt;span class="py"&gt;line-length&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install black: &lt;code&gt;(.venv) django@ubuntuguest:~/tms$ pip install black&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create &lt;code&gt;.flake8&lt;/code&gt; file: This file is used to configure Flake8 settings (linter for Python code style). Example .flake8 content:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[flake8]&lt;/span&gt;
&lt;span class="py"&gt;max-line-length&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;100&lt;/span&gt;
&lt;span class="py"&gt;extend-ignore&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;E203, W503&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install Flake8: &lt;code&gt;(.venv) django@ubuntuguest:~/tms$ pip install flake8&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure VS Code Settings for Your Django Project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a .vscode folder in the root directory of your project.&lt;/li&gt;
&lt;li&gt;Inside the .vscode folder, create a settings.json file.&lt;/li&gt;
&lt;li&gt;Add the following content to settings.json:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"flake8.args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--max-line-length=100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--ignore=E203,W503,F401,F403"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"black-formatter.args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--line-length=100"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"[html]"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Python setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a virtual environment:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="nd"&gt;@ubuntuguest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;mkdir&lt;/span&gt; &lt;span class="n"&gt;tms&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;tms&lt;/span&gt;
&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="nd"&gt;@ubuntuguest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;python3&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;venv&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;venv&lt;/span&gt;
&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="nd"&gt;@ubuntuguest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;venv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;activate&lt;/span&gt;  &lt;span class="c1"&gt;# On Windows: env\Scripts\activate
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install Django and DRF:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(.venv) django@ubuntuguest:~/tms$ pip install django djangorestframework&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Django project:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(.venv) django@ubuntuguest:~/tms$ django-admin startproject tms .&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the development server:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(.venv) django@ubuntuguest:~/tms$ python manage.py runserver 0.0.0.0:8000&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you encounter the error: &lt;code&gt;django.core.exceptions.DisallowedHost: Invalid HTTP_HOST header: 'ip_address:8000'. You may need to add 'ip_address' to ALLOWED_HOSTS.&lt;/code&gt;. Add your server’s IP address (e.g., 10.0.0.10) to the ALLOWED_HOSTS in settings.py: &lt;code&gt;ALLOWED_HOSTS = ['10.0.0.10', 'localhost', '127.0.0.1']&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Visit &lt;a href="http://ip_address:8000" rel="noopener noreferrer"&gt;http://ip_address:8000&lt;/a&gt; to see the default Django homepage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the Git Repository
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code&gt;README.md&lt;/code&gt; file: This file provides basic information about your project, such as purpose, installation instructions, and usage.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;.venv&lt;span class="o"&gt;)&lt;/span&gt; django@ubuntuguest:~/tms&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;README.md
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Add your project description to the file. Example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Training Management System (TMS)&lt;/span&gt;
This is a Django-based project for managing training courses, students, and instructors.
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create &lt;code&gt;requirements.txt&lt;/code&gt;: This file lists all the dependencies for your project. To generate requirements.txt based on the virtual environment:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;.venv&lt;span class="o"&gt;)&lt;/span&gt; django@ubuntuguest:~/tms&lt;span class="nv"&gt;$ &lt;/span&gt;pip freeze &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a &lt;code&gt;LICENSE&lt;/code&gt; file: This file specifies the terms under which your project can be used, modified, and distributed. It is essential for defining the legal rights and obligations of others who want to use your code. Choose a license that suits your project, such as MIT, Apache 2.0, or GPL, and include the corresponding text in this file..&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the &lt;code&gt;.gitignore&lt;/code&gt; file: This file specifies intentionally untracked files or directories that Git should ignore. It helps prevent sensitive information, temporary files, or unnecessary system-generated files (e.g., .env, *.pyc, &lt;strong&gt;pycache&lt;/strong&gt;/, .vscode/) from being included in your repository. Customize it based on your project's needs to keep your repository clean and secure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set Up SSH Key for GitHub:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(.venv) django@ubuntuguest:~/tms$ ls ~/.ssh
(.venv) django@ubuntuguest:~/tms$ ssh-keygen -t ed25519 -C "your_email@example.com"`
(.venv) django@ubuntuguest:~/tms$ cat ~/.ssh/id_ed25519.pub` and Copy the output.
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Add the SSH key to GitHub. Go to Settings &amp;gt; SSH and GPG keys &amp;gt; New SSH key. Paste the key and give it a title.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change Directory: &lt;code&gt;(.venv) django@ubuntuguest:~/tms$ cd /path/to/your/project&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Initialize Git Repository: &lt;code&gt;(.venv) django@ubuntuguest:~/tms$ git init&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add Remote Repository: &lt;code&gt;(.venv) django@ubuntuguest:~/tms$ git remote add origin git@github.com:username/repository.git&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stage Files: &lt;code&gt;(.venv) django@ubuntuguest:~/tms$ git add .&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create Initial Commit: &lt;code&gt;(.venv) django@ubuntuguest:~/tms$ git commit -m "Initial commit"&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Push to Remote Repository:&lt;code&gt;(.venv) django@ubuntuguest:~/tms$ git push -u origin main&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Snapshot the VM
&lt;/h3&gt;

&lt;p&gt;Once the VM is configured and the initial setup is complete, take a snapshot to preserve this state: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to VMware &amp;gt; Snapshot &amp;gt; Take Snapshot.&lt;/li&gt;
&lt;li&gt;Name it something like InitialSetup&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 2: Creating the Accounts App
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Restructure Django Apps
&lt;/h3&gt;

&lt;p&gt;Organizing your Django apps into a dedicated folder (e.g., apps or djangoapps) is a good practice. It improves project structure, enhances maintainability, and keeps your root directory clean. This approach makes it easier to locate apps, especially in large projects, and separates them logically from configuration files and other resources.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a core folder: &lt;code&gt;(.venv) django@ubuntuguest:~/tms$ mkdir djangoapps&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a new app inside it: &lt;code&gt;(.venv) django@ubuntuguest:~/tms/djangoapps$ django-admin startapp accounts&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Register the app in settings.py:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sessions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.staticfiles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# internal apps
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accounts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# external apps
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rest_framework&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When running the server &lt;code&gt;(.venv) django@ubuntuguest:~/tms$ python manage.py runserver 0.0.0.0:8000&lt;/code&gt;, you may see the following error : &lt;code&gt;ModuleNotFoundError: No module named 'accounts'&lt;/code&gt;. This error occurs because Django cannot find the accounts app in your project. You need to change the app name inside &lt;code&gt;tms/djangoapps/accounts/apps.py&lt;/code&gt; from &lt;code&gt;accounts&lt;/code&gt; to &lt;code&gt;djangoapps.accounts&lt;/code&gt; and update it inside settings &lt;code&gt;INSTALLED_APPS&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;djangoapps.accounts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create the User model in accounts/models.py:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AbstractUser&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.core.validators&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;EmailValidator&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.utils.translation&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gettext_lazy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbstractUser&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Override the email field to make it unique and mandatory
&lt;/span&gt;    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;EmailField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;validators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;EmailValidator&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;error_messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unique&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A user with this email already exists.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# extra fields
&lt;/span&gt;    &lt;span class="n"&gt;phone_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;USERNAME_FIELD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;# Change the username field to email
&lt;/span&gt;    &lt;span class="n"&gt;REQUIRED_FIELDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# make the username origianl field required
&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;verbose_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;verbose_name_plural&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;db_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;ordering&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the line &lt;code&gt;AUTH_USER_MODEL = "accounts.UserModel"&lt;/code&gt; in the settings.py file tells Django to use a custom user model (UserModel) defined in the accounts app instead of the default User model provided by Django. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Apply migrations:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;.venv&lt;span class="o"&gt;)&lt;/span&gt; django@ubuntuguest:~/tms&lt;span class="nv"&gt;$ &lt;/span&gt;python manage.py makemigrations
Migrations &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="s1"&gt;'accounts'&lt;/span&gt;:
    djangoapps/accounts/migrations/0001_initial.py
        + Create model UserModel
&lt;span class="o"&gt;(&lt;/span&gt;.venv&lt;span class="o"&gt;)&lt;/span&gt; django@ubuntuguest:~/tms&lt;span class="nv"&gt;$ &lt;/span&gt;python manage.py migrate
Operations to perform:
    Apply all migrations: accounts, admin, auth, contenttypes, sessions
Running migrations:
    Applying contenttypes.0001_initial... OK
    Applying contenttypes.0002_remove_content_type_name... OK
    Applying auth.0001_initial... OK
    Applying auth.0002_alter_permission_name_max_length... OK
    Applying auth.0003_alter_user_email_max_length... OK
    Applying auth.0004_alter_user_username_opts... OK
    Applying auth.0005_alter_user_last_login_null... OK
    Applying auth.0006_require_contenttypes_0002... OK
    Applying auth.0007_alter_validators_add_error_messages... OK
    Applying auth.0008_alter_user_username_max_length... OK
    Applying auth.0009_alter_user_last_name_max_length... OK
    Applying auth.0010_alter_group_name_max_length... OK
    Applying auth.0011_update_proxy_permissions... OK
    Applying auth.0012_alter_user_first_name_max_length... OK
    Applying accounts.0001_initial... OK
    Applying admin.0001_initial... OK
    Applying admin.0002_logentry_remove_auto_add... OK
    Applying admin.0003_logentry_add_action_flag_choices... OK
    Applying sessions.0001_initial... OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Register the model in &lt;code&gt;admin.py&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Create Custom User Forms: In the forms.py file within your accounts app, define two custom forms: one for creating a user (CustomUserCreationForm) and another for updating user data (CustomUserChangeForm).&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.forms&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserCreationForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserChangeForm&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserModel&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomUserCreationForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserCreationForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Custom form for creating new users. Includes all required fields
    and a repeated password field.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserModel&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;phone_number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Include the fields you want to expose
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomUserChangeForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserChangeForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Custom form for updating existing users.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UserModel&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;phone_number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Include fields you want to allow updates on
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Create the Custom Admin Class: In admin.py, define a custom admin class (CustomUserAdmin) that inherits from UserAdmin. This class will allow you to customize how the user model appears in the Django admin interface.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    ```python
    from django.contrib import admin
    from django.contrib.auth.admin import UserAdmin
    from django.utils.translation import gettext_lazy as _
    from django.urls import reverse
    from django.utils.html import format_html

    from .models import UserModel
    from .forms import CustomUserCreationForm, CustomUserChangeForm


    class CustomUserAdmin(UserAdmin):
        """
        Custom admin for the CustomUser model.
        """

        add_form = CustomUserCreationForm
        form = CustomUserChangeForm
        model = UserModel

        # Fields to display in the admin list view
        list_display = ("username", "email", "phone_number", "is_staff", "is_active")
        list_filter = ("is_staff", "is_active", "groups")
        readonly_fields = ("last_login", "date_joined")

        # Fields to display in the admin detail/edit view
        fieldsets = (
            (None, {"fields": ("username", "password")}),
            ("Personal Info", {"fields": ("email", "phone_number", "profile_picture")}),
            (
                "Permissions",
                {"fields": ("is_staff", "is_active", "groups", "user_permissions")},
            ),
            ("Important dates", {"fields": ("last_login", "date_joined")}),
        )

        # Fields to display in the admin add view
        add_fieldsets = (
            (
                None,
                {
                    "classes": ("wide",),
                    "fields": (
                        "username",
                        "email",
                        "phone_number",
                        "profile_picture",
                        "password1",
                        "password2",
                        "is_staff",
                        "is_active",
                    ),
                },
            ),
        )

        # Fields to search in the admin list view
        search_fields = ("username", "email", "phone_number")
        ordering = ("username",)


    # Register the CustomUser with the customized admin
    admin.site.register(UserModel, CustomUserAdmin)
    ```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create a Superuser in Django:

&lt;ul&gt;
&lt;li&gt;Run the following command to create a superuser: &lt;code&gt;(.venv) django@ubuntuguest:~/tms$ python manage.py createsuperuser&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Provide the required information for the superuser: Username, Email, Password (you'll be asked to enter it twice).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Access the Admin Interface: After registering and migrating, start the development server: &lt;code&gt;(.venv) django@ubuntuguest:~/tms$ python manage.py runserver 0.0.0.0:8000&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access the Django Admin Interface: Open a browser and go to &lt;strong&gt;&lt;a href="http://ip_address:8000/admin/" rel="noopener noreferrer"&gt;http://ip_address:8000/admin/&lt;/a&gt;&lt;/strong&gt;. Log in with the superuser credentials you just created, and you should be able to access the admin panel with your custom user model.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/media%2Fimage-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/media%2Fimage-1.png" alt="alt text" width="" height=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;User Management - List of Users.&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/media%2Fimage-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/media%2Fimage-2.png" alt="alt text" width="" height=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;User Management - Edit User.&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/media%2Fimage-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/media%2Fimage-3.png" alt="alt text" width="" height=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;User Management - Add New User.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commit and Push Changes to GitHub: &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To follow the Conventional Commits standard, here's an example commit message for adding the accounts app:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit -m "feat(accounts): add custom user model, forms, and admin configurations"
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Push the changes to your remote repository:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push origin development
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>tutorial</category>
      <category>drf</category>
    </item>
  </channel>
</rss>
