Skip to content

Question

Question

What is required to implement a Backend for Frontend (BFF) architecture in Django with Django REST Framework (DRF)?

To implement a BFF architecture in Django and DRF, you generally need to focus on the following key components:

  1. Custom Serializers:

    • You will need to create different serializers for each frontend application (e.g., web and mobile) to tailor the data structure according to their specific needs.
  2. Viewsets:

    • Create separate viewsets for each frontend, using the custom serializers to handle requests and responses appropriately.
  3. URLs:

    • Set up distinct URL routes for each BFF endpoint, ensuring that each frontend can access its corresponding API.
  4. Data Models (if applicable):

    • Your data models may remain the same, but the way you serve them will differ based on the serializers and viewsets you create.
  5. Authentication and Permissions (if needed):

    • You may also want to implement different authentication or permission schemes based on the frontend requirements.

Summary

While customizing serializers is a significant part of implementing a BFF, it’s not the only step. You also need to create dedicated viewsets and URL configurations to ensure each frontend receives the data in the format it requires.


Step-by-Step Example

  1. Set Up Your Django Project

    First, create a new Django project and an app:

    django-admin startproject my_bff
    cd my_bff
    django-admin startapp user
    
  2. Install Django REST Framework

    Install DRF:

    pip install djangorestframework
    

    Add 'rest_framework' and your app ('user') to INSTALLED_APPS in settings.py:

    # my_bff/settings.py
    
    INSTALLED_APPS = [
        ...
        'rest_framework',
        'user',
    ]
    
  3. Create the User Model

    Define a simple User model in models.py:

    # user/models.py
    
    from django.db import models
    
    class User(models.Model):
        username = models.CharField(max_length=150)
        email = models.EmailField()
        phone = models.CharField(max_length=15)
        street = models.CharField(max_length=255)
        city = models.CharField(max_length=100)
        zipcode = models.CharField(max_length=10)
        newsletter = models.BooleanField(default=False)
        notifications = models.BooleanField(default=False)
    
        def __str__(self):
            return self.username
    

    Run the migrations to create the User table:

    python manage.py makemigrations
    python manage.py migrate
    
  4. Create Serializers

    Create serializers for the User model in serializers.py:

    # user/serializers.py
    
    from rest_framework import serializers
    from .models import User
    
    class UserProfileWebSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ['id', 'username', 'email', 'phone', 'street', 'city', 'zipcode', 'newsletter', 'notifications']
    
    class UserProfileMobileSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ['id', 'username', 'email']
    
  5. Create Viewsets

    Define viewsets for the different BFFs in views.py:

    # user/views.py
    
    from rest_framework import viewsets
    from .models import User
    from .serializers import UserProfileWebSerializer, UserProfileMobileSerializer
    
    class UserProfileWebViewSet(viewsets.ReadOnlyModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserProfileWebSerializer
    
    class UserProfileMobileViewSet(viewsets.ReadOnlyModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserProfileMobileSerializer
    
  6. Configure URLs

    Set up URLs for the two different BFFs in urls.py:

    # user/urls.py
    
    from django.urls import path, include
    from rest_framework.routers import DefaultRouter
    from .views import UserProfileWebViewSet, UserProfileMobileViewSet
    
    router = DefaultRouter()
    router.register(r'web/user-profile', UserProfileWebViewSet, basename='user-web')
    router.register(r'mobile/user-profile', UserProfileMobileViewSet, basename='user-mobile')
    
    urlpatterns = [
        path('', include(router.urls)),
    ]
    

    Include the user app URLs in the main project urls.py:

    # my_bff/urls.py
    
    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('api/', include('user.urls')),
    ]
    
  7. Test the BFF APIs

    Run your Django server:

    python manage.py runserver
    

Endpoint

Now, you can test the endpoints using a tool like Postman or curl.

  • URL: http://localhost:8000/api/web/user-profile/
  • Response Example:

    {
        "id": 1,
        "username": "john_doe",
        "email": "john@example.com",
        "phone": "123-456-7890",
        "street": "123 Elm St",
        "city": "Somewhere",
        "zipcode": "12345",
        "newsletter": true,
        "notifications": false
    }
    
  • URL: http://localhost:8000/api/mobile/user-profile/
  • Response Example:

    {
        "id": 1,
        "username": "john_doe",
        "email": "john@example.com"
    }
    
Benefits of Using BFF
  1. Tailored Responses:

    • The web app receives all necessary details, while the mobile app only gets the crucial information it needs.
  2. Reduced Payload:

    • The mobile app's response is smaller, improving load times and performance.
  3. Decoupled Development:

    • Frontend teams can make changes to their BFFs independently without affecting the other frontend.

Conclusion

In this example, we implemented a BFF architecture using Django and Django REST Framework. We created two separate APIs tailored for different frontends (web and mobile), showcasing how to customize serializers, viewsets, and URLs to meet the specific needs of each frontend application. This approach optimizes data delivery and enhances performance, making it a great architectural choice.