Build a Complete User CRUD REST API in Django REST Framework – Angular Ready with Image Upload

Build a Complete User CRUD REST API in Django REST Framework – Angular Ready with Image Upload

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_URL and MEDIA_ROOT in settings, and the image field stores files in a profile_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), and DELETE /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 users
  • POST /api/users/ – Create user
  • GET /api/users/<id>/ – View user
  • PUT/PATCH /api/users/<id>/ – Update user
  • DELETE /api/users/<id>/ – Delete user

Leave a Reply

Your email address will not be published. Required fields are marked *