Introduction
In this tutorial, we will walk you through the process of building a Countries API using Django, a powerful Python web framework. We will use MySQL as the database to store the information about countries and their attributes. Additionally, we'll enable searching for countries by their id
.
Prerequisites:
- Python installed on your system (https://www.python.org/downloads/)
- MySQL server installed and running (https://www.mysql.com/downloads/)
Let's get started!
Step 1: Set up a virtual environment and install Django
Open your terminal or command prompt and create a new directory for your project:
mkdir countries_api
cd countries_api
Create a virtual environment and activate it:
python3 -m venv env
# For Windows:
. env/Scripts/activate
# For macOS/Linux:
source venv/bin/activate
Install Django and Django REST framework:
pip install django djangorestframework mysqlclient
Step 2: Create a new Django project and app
Create a new Django project and navigate into it:
django-admin startproject countries_api .
(Note the dot .
at the end, which specifies the current directory as the project root.)
Create a new Django app within the project:
python manage.py startapp countries
Step 3: Define the Country model
Open the countries/models.py
file and define the Country
model:
from django.db import models
class Country(models.Model):
# Define the fields for the Country model
name = models.CharField(max_length=100)
iso3 = models.CharField(max_length=3, null=True)
numeric_code = models.CharField(max_length=3, null=True)
iso2 = models.CharField(max_length=2, null=True)
phonecode = models.CharField(max_length=255, null=True)
capital = models.CharField(max_length=255, null=True)
currency = models.CharField(max_length=255, null=True)
currency_name = models.CharField(max_length=255, null=True)
currency_symbol = models.CharField(max_length=255, null=True)
tld = models.CharField(max_length=255, null=True)
native = models.CharField(max_length=255, null=True)
region = models.CharField(max_length=255, null=True)
subregion = models.CharField(max_length=255, null=True)
timezones = models.TextField()
translations = models.TextField()
latitude = models.DecimalField(max_digits=10, decimal_places=8, null=True)
longitude = models.DecimalField(max_digits=11, decimal_places=8, null=True)
emoji = models.CharField(max_length=191, null=True)
emojiU = models.CharField(max_length=191, null=True)
created_at = models.DateTimeField(null=True)
updated_at = models.DateTimeField(auto_now=True)
flag = models.BooleanField(default=True)
wikiDataId = models.CharField(max_length=255, null=True, db_column='wikiDataId', db_comment='Rapid API GeoDB Cities')
def __str__(self):
return self.name
Step 4: Create the MySQL database and run migrations
Ensure your MySQL server is running. Then, open the countries_api/settings.py
file and update the DATABASES
settings:
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.
Run the migrations to create the database tables:
python manage.py makemigrations
python manage.py migrate
Step 5: Create the API views and serializers
Open the countries/views.py
file and define the API views:
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import Country
from .serializers import CountrySerializer
class CountryViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Country.objects.all()
serializer_class = CountrySerializer
@action(detail=True, methods=['GET'])
def search_by_id(self, request, pk=None):
try:
country = Country.objects.get(pk=pk)
serializer = CountrySerializer(country)
return Response(serializer.data)
except Country.DoesNotExist:
return Response({'error': 'Country not found'}, status=404)
Step 6: Register the app and REST framework in settings
Open the countries_api/settings.py
file and update the INSTALLED_APPS
and REST_FRAMEWORK
settings:
# countries_api/settings.py
# ...
INSTALLED_APPS = [
# ...
'rest_framework',
'countries',
# ...
]
# ...
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
],
}
Step 7: Configure the URLs
Open the countries_api/urls.py
file and configure the URLs for the API views:
# countries_api/urls.py
from django.urls import include, path
from rest_framework import routers
from countries.views import CountryViewSet
router = routers.DefaultRouter()
router.register(r'countries', CountryViewSet)
urlpatterns = [
path('', include(router.urls)),
]
Step 8: Run the development server
Finally, run the development server:
python manage.py runserver
Now your Countries API is up and running! You can access it at http://localhost:8000/countries/
. The API supports basic CRUD operations for the Country
model and allows you to search for countries by their id
using the /countries/search_by_id/<id>/
endpoint.
Github link: https://github.com/sosmongare/countries_api
Conclusion:
In this tutorial, we have learned how to create a Countries API using Django with MySQL as the database. We have also enabled searching for countries by their id
, making the API more powerful and flexible. By registering the app and the REST framework, we ensure that the API is properly integrated into the Django project.
Django provides a robust platform to build APIs, and MySQL offers a reliable database backend for storing your data. I hope you found this tutorial helpful in building your API. Incase of any assistance, kindly comment down.
Happy coding!
Top comments (2)
Great! The only thing I would correct is that, for Windows, the correct command to activate the virtual environment is .\env\Scripts\activate.
Thank you @ldnovaes for pointing this out. Mine works work well, however, when I try to use yours, I am getting an error: