Building a Food API with Django and MySQL
Tags: api, django, beginners, programming
Published: 2023-07-19 15:46:15

**Introduction:**

In this article, we'll walk through the process of building a Food API using Django, a powerful web framework for Python, and MySQL as the database backend. The API will allow users to perform CRUD (Create, Read, Update, Delete) operations on food items, including their name and description. By the end of this article, you'll have a fully functional Food API ready to use and extend for your food-related applications.

**Prerequisites:**

Before getting started, make sure you have the following installed:

**1. Python:** You can download Python from the official website (https://www.python.org/downloads/) and install it based on your operating system.

**2. MySQL:** Install and configure MySQL on your machine. You can download MySQL from the official website (https://dev.mysql.com/downloads/installer/) and follow the installation instructions.

**3. Django and Django REST framework:** Install Django and Django REST framework using pip (Python package manager) by running the following command:

```bash
pip install django djangorestframework mysqlclient
```

**Step 1: Set up the project**

Let's start by setting up a new Django project and app:

1. Open your terminal or command prompt and create a new directory for the project:

```bash
mkdir food_api
cd food_api
```

2. Create a virtual environment and activate it:

```bash
python3 -m venv env

# For Windows:
. env/Scripts/activate

# For macOS/Linux:
source venv/bin/activate
```

3. Install Django, Django REST framework and mysqlclient:

```bash
pip install django djangorestframework mysqlclient
```

4. Create a new Django project and app:

```bash
django-admin startproject food_api .
django-admin startapp food
```

**Step 2: Define the Food model**

Next, we'll define the Food model in the `food/models.py` file:

```python
from django.db import models

class Food(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()

    def __str__(self):
        return self.name
```

**Step 3: Configure the MySQL database**

Now, we need to configure the MySQL database settings for our project. Open the `food_api/settings.py` file and update the `DATABASES` settings:

```python
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'your_mysql_db_name',
        'USER': 'your_mysql_username',
        'PASSWORD': 'your_mysql_password',
        'HOST': 'your_mysql_host',  # Use 'localhost' if the database is on the same machine
        'PORT': 'your_mysql_port',  # Typically 3306 for MySQL
    }
}
```

Replace `'your_mysql_db_name'`, `'your_mysql_username'`, `'your_mysql_password'`, `'your_mysql_host'`, and `'your_mysql_port'` with your actual MySQL database credentials.

**Step 4: Create the API views and serializers**

Now, let's create the API views and serializers for our Food model.

Open the `food/views.py` file and define the API views:

```python
from django.shortcuts import render
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Food
from .serializers import FoodSerializer

# Create your views here.

@api_view(['GET', 'POST', 'PUT', 'DELETE'])
def food_list(request):
    if request.method == 'GET':
        foods = Food.objects.all()
        serializer = FoodSerializer(foods, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = FoodSerializer(data=request.data)
        if serializer.is_valid():
            food = serializer.save()
            # Customize the response for a successful creation
            response_data = {
                'message': 'Food item created successfully!',
                'data': serializer.data,
            }
            return Response(response_data, status=201)
        return Response(serializer.errors, status=400)

@api_view(['GET', 'PUT', 'DELETE'])
def food_detail(request, pk):
    try:
        food = Food.objects.get(pk=pk)
    except Food.DoesNotExist:
        # Customize the response for a food item not found
        return Response({'Error': 'Food not found'}, status=404)

    if request.method == 'GET':
        serializer = FoodSerializer(food)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = FoodSerializer(food, data=request.data)
        if serializer.is_valid():
            serializer.save()
            # Customize the response for a successful update
            response_data = {
                'message': 'Food item updated successfully!',
                'data': serializer.data,
            }
            return Response(response_data)
        return Response(serializer.errors, status=400)

    elif request.method == 'DELETE':
        food.delete()
        # Customize the response for a successful deletion
        return Response({'message': 'Food item deleted successfully!'}, status=204)
```

**Step 5: Create the API serializer**

Next, let's create the API serializer in the `food/serializers.py` file:

```python
from rest_framework import serializers
from .models import Food

class FoodSerializer(serializers.ModelSerializer):
    class Meta:
        model = Food
        fields = '__all__'
```

**Step 6: Register the app and REST framework in settings**

Open the `food_api/settings.py` file and update the `INSTALLED_APPS` and `REST_FRAMEWORK` settings:

```python
INSTALLED_APPS = [
    # ...
    'rest_framework',
    'food',
    # ...
]

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    ],
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
    ],
}
```

**Step 7: Configure the URLs**

Open the `food_api/urls.py` file and configure the URLs for the API views:

```python
from django.urls import path
from food.views import food_list, food_detail

urlpatterns = [
    path('food/', food_list),
    path('food/<int:pk>/', food_detail),
]
```

**Step 8: Run the development server**

Finally, run the development server:

```bash
python manage.py runserver
```

**Testing the food api**
Once the server is running, you should see output indicating that the development server is up and running. By default, it will listen on http://127.0.0.1:8000/ or http://localhost:8000/.

Use a tool such as **curl, Postman, or a web browser** to interact with your API endpoints and view the responses.

1. To test the food_list view, visit **http://localhost:8000/food/** in your web browser or use curl to make a GET request to the URL.

![View Food List](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kwoheq9y1383bkw100lo.png)

2.To test the food_detail view, replace <pk> with the ID of a specific food item you want to view. For example, visit http://localhost:8000/food/1/ in your web browser or use curl to make a GET request to the URL.

![View One Food Item](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kyiajztyxjmt6131115l.png)

3. To test the create_food view, use curl to make a POST request to http://localhost:8000/food/ with the data for creating a new food item.

![Before Create Food](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zbp5q6lp0tjicdr99x1.png)


![After Create Food](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j2q2e90v5ysej6rlki9z.png)

4. To test the update_food view, use curl to make a PUT request to http://localhost:8000/food/<pk>/ with the data for updating an existing food item. Replace <pk> with the ID of the food item you want to update.
**Before updating**
![Before Update Food](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6rmc39si8y0ov8aj97up.png)

**After updating**
![After Update Food](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4spv9npc8hhaboyskmwp.png)

4. To test the **delete_food** view, use curl to make a DELETE request to http://localhost:8000/food/<pk>/. Replace <pk> with the ID of the food item you want to delete.


![Delete food](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4kommtm042zcodylwqbq.png)


Observe the responses from the server and verify that the API is functioning as expected.

Remember to adjust the testing based on your specific API requirements and use case. You can also use tools like Postman for a more user-friendly API testing experience.


**Conclusion:**

Congratulations! You have successfully created a Food API using Django and MySQL. The API provides endpoints to list all food items, retrieve specific food items, create new food items, update existing food items, and delete food items. You can use this API as a foundation for building more complex food-related applications or extend it further based on your project requirements.

Remember to ensure proper security measures when deploying your API in production, such as handling authentication and authorization if needed.

**Github link:** https://github.com/sosmongare/food_api

Feel free to explore more about Django and Django REST framework to enhance your API and make it more robust and feature-rich. 

Happy coding!