Essential Django Interview Questions

author image Hirely
at 10 Jan, 2025

Question: What is Django REST Framework (DRF) and how is it used?

Answer:

Django REST Framework (DRF) is a powerful and flexible toolkit for building Web APIs in Django. It simplifies the process of creating RESTful APIs by providing tools and abstractions to handle common tasks like serialization, authentication, authorization, and URL routing. DRF leverages Django’s existing components and adds functionality specifically designed for building APIs.

Key Concepts in Django REST Framework:

  1. RESTful APIs:

    • REST (Representational State Transfer) is an architectural style for designing networked applications. It uses HTTP requests to perform CRUD (Create, Read, Update, Delete) operations on resources, where resources are typically represented in JSON or XML.
    • DRF helps create APIs that expose your Django application’s data to be consumed by other systems (e.g., front-end apps, mobile apps, third-party services).
  2. Serialization:

    • DRF provides serializers to convert complex data types (like Django models or querysets) into Python data types that can be easily rendered into JSON or XML for API responses.
    • It also handles deserialization, converting incoming JSON/XML data into Python data types that can be processed or saved in the database.

    Example of a simple serializer:

    from rest_framework import serializers
    from .models import Product
    
    class ProductSerializer(serializers.ModelSerializer):
        class Meta:
            model = Product
            fields = ['id', 'name', 'description', 'price']
  3. Views:

    • DRF offers several ways to define API views:
      • Function-based views (FBVs): Traditional Django views for handling HTTP requests.
      • Class-based views (CBVs): DRF provides generic class-based views to handle common API patterns (e.g., ListAPIView, CreateAPIView, RetrieveAPIView).
      • ViewSets: A higher-level abstraction that combines multiple views into one by automatically generating views for standard actions like list, create, retrieve, update, and delete.

    Example of a basic view using APIView:

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import status
    
    class ProductList(APIView):
        def get(self, request):
            products = Product.objects.all()
            serializer = ProductSerializer(products, many=True)
            return Response(serializer.data)
  4. URL Routing:

    • DRF uses routers to automatically generate URL routes for viewsets. This makes it easy to connect views to URLs without manually specifying the URL patterns.

    Example using a router with viewsets:

    from rest_framework.routers import DefaultRouter
    from .views import ProductViewSet
    
    router = DefaultRouter()
    router.register(r'products', ProductViewSet)
    
    urlpatterns = router.urls
  5. Authentication & Authorization:

    • DRF supports multiple authentication mechanisms, such as Session authentication, Token authentication, OAuth, and JWT (JSON Web Tokens).
    • It also provides built-in permission classes (e.g., IsAuthenticated, IsAdminUser) to control access to your API based on user roles or other criteria.

    Example of using token authentication:

    from rest_framework.authentication import TokenAuthentication
    from rest_framework.permissions import IsAuthenticated
    
    class ProductList(APIView):
        authentication_classes = [TokenAuthentication]
        permission_classes = [IsAuthenticated]
    
        def get(self, request):
            products = Product.objects.all()
            serializer = ProductSerializer(products, many=True)
            return Response(serializer.data)
  6. Pagination:

    • DRF provides built-in pagination for API responses to limit the number of records returned in one response. You can configure pagination globally or for individual views.

    Example of pagination:

    from rest_framework.pagination import PageNumberPagination
    from rest_framework.response import Response
    from rest_framework.views import APIView
    
    class ProductPagination(PageNumberPagination):
        page_size = 10
    
    class ProductList(APIView):
        pagination_class = ProductPagination
    
        def get(self, request):
            products = Product.objects.all()
            paginator = ProductPagination()
            result_page = paginator.paginate_queryset(products, request)
            serializer = ProductSerializer(result_page, many=True)
            return paginator.get_paginated_response(serializer.data)
  7. Throttling:

    • DRF also provides throttling to control the rate at which clients can make requests to the API. This helps protect the API from abuse and overuse.
  8. Testing:

    • DRF includes tools for testing APIs. You can use Django’s test framework along with DRF’s APIClient to simulate API requests and check the responses.

How to Use Django REST Framework:

Step-by-Step Guide to Building a Simple API:

  1. Install Django REST Framework: First, install DRF by running the following command:

    pip install djangorestframework
  2. Add DRF to INSTALLED_APPS: In your settings.py, add 'rest_framework' to the INSTALLED_APPS list:

    INSTALLED_APPS = [
        # other apps
        'rest_framework',
    ]
  3. Define Models: In your models.py, define the data you want to expose through your API. For example, a simple Product model:

    from django.db import models
    
    class Product(models.Model):
        name = models.CharField(max_length=100)
        description = models.TextField()
        price = models.DecimalField(max_digits=10, decimal_places=2)
    
        def __str__(self):
            return self.name
  4. Create Serializers: In your serializers.py, create a serializer for your model to define how data should be serialized:

    from rest_framework import serializers
    from .models import Product
    
    class ProductSerializer(serializers.ModelSerializer):
        class Meta:
            model = Product
            fields = ['id', 'name', 'description', 'price']
  5. Create Views: In your views.py, create a view to handle HTTP requests. You can use a ViewSet for automatic routing.

    from rest_framework import viewsets
    from .models import Product
    from .serializers import ProductSerializer
    
    class ProductViewSet(viewsets.ModelViewSet):
        queryset = Product.objects.all()
        serializer_class = ProductSerializer
  6. Define URL Routing: In your urls.py, use a router to automatically generate URL routes for your viewset.

    from django.urls import path, include
    from rest_framework.routers import DefaultRouter
    from .views import ProductViewSet
    
    router = DefaultRouter()
    router.register(r'products', ProductViewSet)
    
    urlpatterns = [
        path('api/', include(router.urls)),
    ]
  7. Run Migrations: Apply migrations to create the database tables for your model:

    python manage.py makemigrations
    python manage.py migrate
  8. Test the API: Run the development server:

    python manage.py runserver

    Now, you can access your API at http://127.0.0.1:8000/api/products/.


Summary of Django REST Framework (DRF):

  • Django REST Framework (DRF) is a toolkit for building web APIs using Django. It provides components like serializers, views, routers, and authentication mechanisms to simplify the process of creating RESTful APIs.
  • Serialization handles converting data between complex Django objects and JSON/XML.
  • Views in DRF can be function-based, class-based, or viewsets, with viewsets being an abstraction that automatically handles common operations like creating, updating, and deleting resources.
  • DRF offers features such as pagination, authentication, authorization, and testing tools to handle real-world API requirements.
  • DRF integrates smoothly with Django’s existing features, making it easier to build and maintain APIs.

By using DRF, you can quickly and easily build powerful, flexible APIs that can be consumed by mobile applications, web applications, or third-party services.

Question: How do you perform form handling in Django?

Answer:

Form handling in Django is a crucial aspect of web development, as it allows you to process user input in a secure and efficient manner. Django provides a comprehensive framework for working with forms, offering built-in support for rendering forms, validating data, and saving it to the database.

Here’s a step-by-step explanation of how form handling works in Django:


1. Creating a Django Form

Django provides two ways to handle forms:

  • Django Forms: A form class that inherits from django.forms.Form is used for basic form handling.
  • Model Forms: A form class that inherits from django.forms.ModelForm, which is specifically designed for working with Django models.

a. Using forms.Form for Basic Forms

  1. Create a Form Class: A simple form can be created by subclassing django.forms.Form and defining form fields as class attributes.

    Example:

    from django import forms
    
    class ContactForm(forms.Form):
        name = forms.CharField(max_length=100)
        email = forms.EmailField()
        message = forms.CharField(widget=forms.Textarea)
    • forms.CharField: Defines a text input field.
    • forms.EmailField: Defines an email input field.
    • forms.Textarea: Defines a large text area for longer input.

b. Using forms.ModelForm for Forms Linked to Models

  1. Create a Model: First, define a Django model that you will associate with the form.

    Example:

    from django.db import models
    
    class Feedback(models.Model):
        name = models.CharField(max_length=100)
        email = models.EmailField()
        message = models.TextField()
        date_created = models.DateTimeField(auto_now_add=True)
  2. Create a Model Form: Define a model form by subclassing django.forms.ModelForm and linking it to a model.

    Example:

    from django import forms
    from .models import Feedback
    
    class FeedbackForm(forms.ModelForm):
        class Meta:
            model = Feedback
            fields = ['name', 'email', 'message']

    This automatically creates a form with fields corresponding to the model’s fields.


2. Rendering Forms in Templates

To render forms in templates, you can use Django’s built-in template tags or render the form fields manually.

a. Using {{ form }} to Render the Entire Form

You can pass a form instance to a template and render it using the {{ form }} template tag.

Example in the template (contact.html):

<form method="POST">
    {% csrf_token %}
    {{ form.as_p }}  <!-- Renders form fields as <p> elements -->
    <button type="submit">Submit</button>
</form>
  • {% csrf_token %}: Includes a CSRF token to protect against Cross-Site Request Forgery attacks.
  • {{ form.as_p }}: Renders each form field as a paragraph (<p>). You can also use {{ form.as_table }} or render the fields manually using {{ form.field_name }}.

b. Rendering Fields Individually

You can render each form field manually for more control over the layout:

Example:

<form method="POST">
    {% csrf_token %}
    <div>
        <label for="{{ form.name.id_for_label }}">Name</label>
        {{ form.name }}
        {% if form.name.errors %}
            <div class="errors">{{ form.name.errors }}</div>
        {% endif %}
    </div>
    <div>
        <label for="{{ form.email.id_for_label }}">Email</label>
        {{ form.email }}
        {% if form.email.errors %}
            <div class="errors">{{ form.email.errors }}</div>
        {% endif %}
    </div>
    <button type="submit">Submit</button>
</form>

3. Processing Form Data in Views

Once the form is submitted, you need to process the data in your view. This includes validating the form, checking if it’s valid, and performing actions such as saving data to the database or sending an email.

a. Handling Form Submission (POST)

In your view, you need to handle both GET (to display the form) and POST (to process the form) requests.

Example view using a regular form:

from django.shortcuts import render
from .forms import ContactForm

def contact_view(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            # Process form data
            name = form.cleaned_data['name']
            email = form.cleaned_data['email']
            message = form.cleaned_data['message']
            # Do something with the data (e.g., send an email, save to the database)
            return render(request, 'contact/thank_you.html', {'name': name})
    else:
        form = ContactForm()

    return render(request, 'contact/contact_form.html', {'form': form})
  • request.method == 'POST': Checks if the form was submitted via POST.
  • form.is_valid(): Validates the form data. It checks whether all fields pass the validation rules defined in the form class.
  • form.cleaned_data: Contains the cleaned and validated data from the form fields. You can use this data to perform further actions (like saving to the database).
  • If the form is not valid, you can display error messages or re-render the form.

b. Handling Form Submission with Model Form

If you’re using a ModelForm, the process is very similar but with the added benefit of automatically handling database interactions.

Example view for ModelForm:

from django.shortcuts import render
from .forms import FeedbackForm

def feedback_view(request):
    if request.method == 'POST':
        form = FeedbackForm(request.POST)
        if form.is_valid():
            form.save()  # Saves the data to the database automatically
            return render(request, 'feedback/thank_you.html')
    else:
        form = FeedbackForm()

    return render(request, 'feedback/feedback_form.html', {'form': form})
  • form.save(): This saves the form data to the database. The ModelForm handles the creation of a model instance and saves it to the database in one step.

4. Form Validation

Django forms come with built-in validation features, but you can also add custom validation logic to suit your needs.

a. Built-in Validation

  • Required Fields: Fields are required by default unless you specify required=False.
  • Email Field: forms.EmailField automatically validates the input as a proper email address.
  • Max Length: forms.CharField(max_length=100) validates the maximum length of input.

b. Custom Validation

You can create custom validation for individual fields or the entire form.

Example of a custom field validator:

from django.core.exceptions import ValidationError

def validate_even(value):
    if value % 2 != 0:
        raise ValidationError(f'{value} is not an even number.')

class NumberForm(forms.Form):
    number = forms.IntegerField(validators=[validate_even])

c. Custom Form Validation Method

You can define a method within the form to validate the entire form.

Example:

class ContactForm(forms.Form):
    name = forms.CharField(max_length=100)
    email = forms.EmailField()

    def clean_email(self):
        email = self.cleaned_data.get('email')
        if "example.com" in email:
            raise forms.ValidationError("We do not accept email addresses from example.com")
        return email

5. Displaying Form Errors

If a form is invalid, Django automatically populates form.errors with the error messages. You can display them in the template.

Example:

{% if form.errors %}
    <div class="errors">
        {% for field in form %}
            {% for error in field.errors %}
                <p>{{ error }}</p>
            {% endfor %}
        {% endfor %}
    </div>
{% endif %}

6. Redirecting After Form Submission

To avoid resubmission of a form if the user refreshes the page, it’s a good practice to redirect the user after a successful form submission (Post/Redirect/Get pattern).

Example:

from django.shortcuts import redirect

def feedback_view(request):
    if request.method == 'POST':
        form = FeedbackForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('thank_you')  # Redirect to a new URL after successful form submission
    else:
        form = FeedbackForm()

    return render(request, 'feedback/feedback_form.html', {'form': form})

Summary of Form Handling in Django:

  • Django forms provide a simple and powerful way to handle user input. They support both basic forms (forms.Form) and model-based forms (forms.ModelForm).
  • Forms are rendered in templates using {{ form }}, and data is processed in views using form.is_valid() and form.cleaned_data.
  • Validation can be done both at the field level and the form level.
  • After successful form submission, you can save data to the database or perform other actions, and it’s recommended to redirect the user to avoid resubmission.

Read More

If you can’t get enough from this article, Aihirely has plenty more related information, such as Django interview questions, Django interview experiences, and details about various Django job positions. Click here to check it out.

Related Posts

Trace Job opportunities

Hirely, your exclusive interview companion, empowers your competence and facilitates your interviews.

Get Started Now