Adventures in Machine Learning

Building a RESTful API with Django and Django REST Framework: A Step-By-Step Guide

Introduction to Django REST Framework

Django REST Framework is a powerful tool that allows developers to build APIs quickly and easily. The framework is built on top of the Django web framework, which provides a solid foundation for developing web applications.

In this article, well explore the benefits of using Django REST Framework and demonstrate how to set up a Django project with the REST Framework installed.

Benefits of using REST Framework

Django REST Framework has a number of benefits for developers. Here are a few of the most important ones:

1.

Serialization: Django REST Framework provides powerful serialization capabilities that allow developers to easily convert complex data types like Python objects and models into JSON, XML, or other formats that can be easily transmitted and processed. 2.

Authentication: The framework provides easy-to-use authentication methods that allow APIs to be secured against unauthorized access. Built-in support for OAuth2, token-based authentication, and session-based authentication makes it easy to add security to your APIs.

3.

Customizable and flexible: Django REST Framework is highly customizable and flexible, which makes it easy to adapt to different needs. Whether youre building a simple prototype or a complex enterprise application, you can tailor the framework to meet your specific requirements.

4. Browsable APIs: With Django REST Framework, you can provide browsable APIs that allow developers to interact with your API using their web browser.

This can be particularly useful during development and testing, as it allows developers to easily explore and test the API. 5.

Documentation: Django REST Framework provides powerful tools for generating API documentation, making it easy to keep your documentation up-to-date and accessible to developers.

Creating the puppies app

Now that weve explored some of the benefits of using Django REST Framework, lets dive into setting up a Django project with the framework installed. For this tutorial, well be creating an app called Puppies that will allow us to manage data about puppies.

First, lets create a new Django project. Open your terminal or command prompt and navigate to the directory where you want to create the project.

Then, enter the following command:

“`bash

django-admin startproject puppiesproject

“`

This will create a new Django project called puppiesproject. Now, lets create a new app within the project.

Enter the following command:

“`bash

python manage.py startapp puppies

“`

This will create a new app called puppies within your Django project.

Installing REST Framework

Next, lets install Django REST Framework. To do this, open your terminal or command prompt and navigate to the directory where your Django project is located.

Then, enter the following command:

“`bash

pip install djangorestframework

“`

This will install Django REST Framework and all of its dependencies.

Now that weve installed Django REST Framework, we need to add it to our projects settings.

Open the settings.py file in your projects root directory and add the following code at the bottom of the file:

“`python

INSTALLED_APPS = [

# … ‘rest_framework’,

‘puppies’,

]

“`

This will add Django REST Framework and our new puppies app to our projects list of installed apps.

We also need to add some configuration options for Django REST Framework. Add the following code to your settings.py file:

“`python

REST_FRAMEWORK = {

‘DEFAULT_PERMISSION_CLASSES’: [

‘rest_framework.permissions.AllowAny’,

],

‘DEFAULT_RENDERER_CLASSES’: [

‘rest_framework.renderers.JSONRenderer’,

]

}

“`

This code sets the default permissions to allow any user to access our API and sets the default renderer to JSON.

Conclusion

Django REST Framework is a powerful tool for building APIs. It provides a wide range of benefits to developers, including powerful serialization capabilities, easy authentication methods, and customizable and flexible options. By following the steps outlined in this article, you can quickly set up a Django project with the REST Framework installed and start building your own APIs.

Database and Model Setup

In the previous section, we saw how to create a new Django project and install Django REST Framework. In this section, well continue building our Puppies app by setting up a Postgres database and defining a Puppy model.

Setting up Postgres database

PostgreSQL is a popular open-source database management system that provides high scalability and data integrity. To use PostgreSQL with Django, we need to install the psycopg2 library, which is a PostgreSQL adapter for Python.

First, make sure you have PostgreSQL installed and running on your computer. Next, open your terminal or command prompt and run the following command to install psycopg2:

“`bash

pip install psycopg2

“`

Next, we need to add the database configuration to our Django projects settings. Open settings.py and add the following code:

“`python

DATABASES = {

‘default’: {

‘ENGINE’: ‘django.db.backends.postgresql’,

‘NAME’: ‘puppiesdb’,

‘USER’: ‘puppiesadmin’,

‘PASSWORD’: ‘mypassword’,

‘HOST’: ‘localhost’,

‘PORT’: ‘5432’,

}

}

“`

These settings tell Django to use the PostgreSQL database engine, and to connect to a database called puppiesdb with a username of puppiesadmin and a password of mypassword.

The database is assumed to be running locally on port 5432.

Note: Its important to replace these values with their actual values in your specific setup.

Defining the Puppy model

Now that we have our database setup, we can define our Puppy model. Open puppies/models.py and add the following code:

“`python

from django.db import models

class Puppy(models.Model):

name = models.CharField(max_length=50)

age = models.IntegerField()

breed = models.CharField(max_length=50)

color = models.CharField(max_length=50)

created_at = models.DateTimeField(auto_now_add=True)

updated_at = models.DateTimeField(auto_now=True)

def __str__(self):

return self.name

“`

This model defines a Puppy with a name, age, breed, and color.

Weve also added two timestamp fields, created_at and updated_at, which will automatically track when a Puppy is created and updated.

Sanity Check

Lets do a quick sanity check to make sure everything is set up correctly. Open your terminal or command prompt and navigate to your project directory.

Then, enter the following command to create the database tables:

“`bash

python manage.py migrate

“`

This will create all of the necessary database tables based on the models weve defined.

Next, lets verify that the puppies_puppy table has been created in the database.

Connect to your PostgreSQL database using the psql command:

“`bash

psql -U puppiesadmin -d puppiesdb

“`

This will connect to the puppiesdb database as the puppiesadmin user. At the psql prompt, enter the following command to see a list of tables:

“`sql

dt

“`

You should see a puppies_puppy table in the list.

Writing a unit test for the Puppy model

Now that we have our model and database set up, its time to write a unit test to verify that our code is working properly. Open puppies/tests.py and add the following code:

“`python

from django.test import TestCase

from .models import Puppy

class PuppyModelTest(TestCase):

@classmethod

def setUpClass(cls):

super().setUpClass()

Puppy.objects.create(

name=’Fido’,

age=2,

breed=’Dalmatian’,

color=’Black and White’

)

def test_puppy_name(self):

puppy = Puppy.objects.get(id=1)

expected_name = f'{puppy.name}’

self.assertEquals(expected_name, ‘Fido’)

def test_puppy_age(self):

puppy = Puppy.objects.get(id=1)

expected_age = f'{puppy.age}’

self.assertEquals(expected_age, ‘2’)

def test_puppy_breed(self):

puppy = Puppy.objects.get(id=1)

expected_breed = f'{puppy.breed}’

self.assertEquals(expected_breed, ‘Dalmatian’)

def test_puppy_color(self):

puppy = Puppy.objects.get(id=1)

expected_color = f'{puppy.color}’

self.assertEquals(expected_color, ‘Black and White’)

“`

This test defines a new Testcase and creates a new Puppy for testing purposes in the setUpClass() method.

We then define four test cases, each of which tests one of the fields in the Puppy model.

To run this test, enter the following command in your terminal or command prompt:

“`bash

python manage.py test puppies.tests.PuppyModelTest

“`

This will run the test and output the results.

If everything is working properly, you should see all four tests pass.

Conclusion

In this section, we explored how to set up a Postgres database for our Django project and defined a Puppy model. We also did a quick sanity check to ensure that everything is working properly, and wrote a unit test to verify that our model is functioning correctly.

By following these steps, we now have a solid foundation for creating our Puppies app and building out its functionality.

Serializers

In the previous section, we saw how to set up a Postgres database and define a Puppy model. In this section, well explore serializers, which are an essential part of building APIs with Django REST Framework.

Definition of serializers

Serializers allow us to convert complex data types (such as Django models) into JSON, XML, or other formats that can be easily transmitted and processed over HTTP. In other words, serializers are responsible for controlling the input and output of data from our APIs.

Django REST Framework provides two types of serializers: the Serializer class and the ModelSerializer class.

The Serializer class provides a flexible way to define and validate input and output data for a specific resource. The ModelSerializer class provides a shortcut for automatically generating serializers based on a model, saving lots of development time.

Defining a ModelSerializer for the Puppy model

Well be using the ModelSerializer class to define a serializer for our Puppy model. Open puppies/serializers.py and add the following code:

“`python

from rest_framework import serializers

from .models import Puppy

class PuppySerializer(serializers.ModelSerializer):

class Meta:

model = Puppy

fields = [‘id’, ‘name’, ‘age’, ‘breed’, ‘color’, ‘created_at’, ‘updated_at’]

“`

This code defines a new PuppySerializer class that inherits from the ModelSerializer class. Weve specified the fields we want to include in the serialized output (the same fields as the Puppy model) and set the model to use to the Puppy model.

RESTful Structure

Now that we have a serializer for our Puppy model, we can start building out the structure of our API. In this section, well explore RESTful APIs and endpoints, and define the URLs for our API.

Explanation of RESTful APIs and endpoints

RESTful APIs are designed to be stateless, meaning that each request is self-contained and contains all the information needed to fulfill that request. RESTful APIs are based on a set of principles, including using HTTP methods (such as POST and GET) to perform actions on resources, and using URLs to identify and locate resources.

Endpoints are the URLs that map to specific resources in our API. They specify the HTTP method to use (such as GET or POST) when accessing that resource.

An example of an endpoint for our Puppy resource might be:

“`

GET /api/puppies/

“`

This endpoint would return a list of all puppies in our database.

Defining the URLs for the API

Now that we understand RESTful APIs and endpoints, we can define the URLs for our own API. Open puppies/urls.py and add the following code:

“`python

from django.urls import path, include

from rest_framework import routers

from . import views

router = routers.DefaultRouter()

router.register(r’puppies’, views.PuppyViewSet)

urlpatterns = [

path(‘api/’, include(router.urls)),

]

“`

This code defines a new Django router and registers our Puppy viewset with the router.

The URLs for the router are then included under the ‘api/’ namespace.

We also need to define the viewset that will be used to retrieve data for the Puppy resource.

Add the following code to your views.py file:

“`python

from rest_framework import viewsets

from .models import Puppy

from .serializers import PuppySerializer

class PuppyViewSet(viewsets.ModelViewSet):

queryset = Puppy.objects.all()

serializer_class = PuppySerializer

“`

This code defines a new viewset that inherits from the ModelViewSet class provided by Django REST Framework. Weve set the queryset to fetch all puppies from the database and set the serializer class to our PuppySerializer.

Conclusion

In this section, weve explored serializers and their role in API development. Weve defined a ModelSerializer for our Puppy model, which we then used to build out the structure of our API with RESTful principles.

By following these steps, we now have a fully functional API for managing Puppy resources in our Django project.

Routes and Testing (TDD)

In the previous section, we saw how to define the URLs for our API. In this section, well explore using a test-first approach to building our API, and creating skeleton view functions for all routes.

Using a test-first approach

Test-driven development (TDD) is an approach to software development that emphasizes writing tests before writing code. With TDD, you write a failing test first, then write code to fulfill the requirements of the test.

This helps ensure that your code is correct and that it meets the requirements of the test.

Creating skeleton view functions for all routes

With TDD in mind, lets create skeleton view functions for all the routes we defined in the previous section. Open puppies/views.py and add the following code:

“`python

from django.shortcuts import render

from django.http import JsonResponse

from rest_framework import status

from rest_framework.decorators import api_view

from rest_framework.response import Response

from .models import Puppy

from .serializers import PuppySerializer

@api_view([‘GET’])

def api_overview(request):

pass

@api_view([‘GET’])

def puppy_list(request):

pass

@api_view([‘GET’])

def puppy_detail(request, pk):

pass

@api_view([‘POST’])

def puppy_create(request):

pass

@api_view([‘PUT’])

def puppy_update(request, pk):

pass

@api_view([‘DELETE’])

def puppy_delete(request, pk):

pass

“`

This code defines six view functions corresponding to the routes we defined earlier. We havent written any code yet – instead, were following a test-first approach where well write tests to ensure that these functions work as expected.

Writing tests for creating a new Puppy record

Lets start by writing tests to ensure that we can create a new Puppy record using our API. Open puppies/tests.py and add the following code:

“`python

from django.urls import reverse

from django.test import TestCase, Client

from rest_framework import status

from rest_framework.test import APITestCase, APIClient

from .models import Puppy

from .serializers import PuppySerializer

class PuppyTestCase(APITestCase):

def setUp(self):

self.client = APIClient()

self.puppy_data = {‘name’: ‘Fido’, ‘age’: 2, ‘breed’: ‘Dalmatian’, ‘color’: ‘Black and White’}

self.response = self.client.post(reverse(‘puppy_create’), self.puppy_data, format=’json’)

def test_create_puppy(self):

self.assertEqual(self.response.status_code, status.HTTP_201_CREATED)

def test_create_puppy_invalid(self):

response = self.client.post(reverse(‘puppy_create’), {‘name’: ‘Fido’, ‘age’: ‘not a number’, ‘breed’: ‘Dalmatian’, ‘color’: ‘Black and White’}, format=’json’)

self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

“`

This code defines a new test case for creating a new Puppy record. Weve set up a client and defined some dummy data for the new record.

We then send a POST request to the puppy_create URL with the data and ensure that the response status code is 201, indicating that the record was created successfully.

Weve also included a second test case for creating an invalid Puppy

Popular Posts