AI Reading
Quick summary of this article
This tutorial explains how to build a complete user management REST API using Django REST Framework (DRF), designed to work seamlessly with frontend frameworks like Angular or React. It covers all CRUD operations—creating, reading, updating, and deleting users—and includes profile image upload support. The guide walks through setting up a custom user model with email authentication, creating serializers and viewsets, configuring media file handling, and exposing standard API endpoints.
- The API uses a custom user model based on email instead of username, with fields for first name, last name, and an optional profile image.
- Password handling is secure: passwords are write-only in the serializer and stored using Django's password hashing via the
set_password()method. - Image upload is enabled by configuring
MEDIA_URLandMEDIA_ROOTin settings, and the image field stores files in aprofile_images/directory. - CORS is enabled with
CORS_ALLOW_ALL_ORIGINS = True, making the API accessible from any frontend domain during development. - Pre-built API endpoints include
GET /api/users/(list),POST /api/users/(create),GET /api/users/<id>/(detail),PUT/PATCH /api/users/<id>/(update), andDELETE /api/users/<id>/(delete).
User CRUD REST API in Django REST Framework
In this tutorial, you’ll learn how to build a full-featured REST API for managing users using Django REST Framework (DRF). The API supports create, read, update, and delete (CRUD) operations, including image upload. It is fully frontend-ready — perfect for Angular, React, or any SPA.
✅ Features Covered
- User Registration with profile image
- View all users or a single user
- Update user data including password and image
- Delete user
- Frontend integration via FormData
📁 Project Structure
usercrud/
├── manage.py
├── usercrud/
│ ├── settings.py
│ └── urls.py
├── users/
│ ├── models.py
│ ├── serializers.py
│ ├── views.py
│ ├── urls.py
1️⃣ Install and Set Up Django
pip install django djangorestframework pillow
django-admin startproject usercrud
cd usercrud
python manage.py startapp users
2️⃣ Configure settings.py
Add to INSTALLED_APPS:
'rest_framework',
'corsheaders',
'users',
Enable media file upload:
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
CORS_ALLOW_ALL_ORIGINS = True
3️⃣ Create CustomUser Model
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError("Email is required")
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
if password:
user.set_password(password)
user.save()
return user
class CustomUser(AbstractBaseUser):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField(unique=True)
image = models.ImageField(upload_to='profile_images/', blank=True, null=True)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']
4️⃣ Make Migrations
python manage.py makemigrations
python manage.py migrate
5️⃣ Create Serializer
from rest_framework import serializers
from .models import CustomUser
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, required=False)
class Meta:
model = CustomUser
fields = ['id', 'first_name', 'last_name', 'email', 'password', 'image']
def create(self, validated_data):
password = validated_data.pop('password', None)
user = CustomUser(**validated_data)
if password:
user.set_password(password)
user.save()
return user
def update(self, instance, validated_data):
password = validated_data.pop('password', None)
for attr, value in validated_data.items():
setattr(instance, attr, value)
if password:
instance.set_password(password)
instance.save()
return instance
6️⃣ Create ViewSet
from rest_framework import viewsets
from .models import CustomUser
from .serializers import UserSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = CustomUser.objects.all()
serializer_class = UserSerializer
7️⃣ Wire Up URLs
users/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import UserViewSet
router = DefaultRouter()
router.register('users', UserViewSet)
urlpatterns = [
path('', include(router.urls)),
]
usercrud/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('users.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
✅ API Endpoints
GET /api/users/– List all usersPOST /api/users/– Create userGET /api/users/<id>/– View userPUT/PATCH /api/users/<id>/– Update userDELETE /api/users/<id>/– Delete user
