How to create an easy Restful API for a simple model
In this first blog I would like to show how you can create a simple project with a restful api for a single model. The tools will be django and django rest framework.
After you do:
pip install django
pip install djangorestframework
You may want to start by creating a new django project/app.
> django-admin.py startproject citiesprj
> cd citiesprj
> django-admin.py startapp cities
Remember to add rest_framework to INSTALLED_APPS in your project settings.py
Once you got your app folder go to models and a new model City
class City(models.Model):
city = models.CharField(max_length=50)
state = models.CharField(max_length=2)
zip_code = models.CharField(max_length=10, blank=True, db_index=True)
@property
def city_state_zip(self):
return self.city + " " + self.state + ", " + self.zip_code
class Meta:
verbose_name_plural = "Cities"
def __unicode__(self):
return self.city_state_zip
In order to check that our API is working we would like to use the admin so you can go to the admin.py file and add:
from . import models
@admin.register(models.City)
class CityAdmin(admin.ModelAdmin):
list_display = ('city', 'state', 'zip_code')
search_fields = ('city', 'zip_code')
list_filter = ('state', )
Remember to run ./manage.py makemigrations and ./manage.py migrate in order to create the table for our new model. All these is well documented in https://docs.djangoproject.com/en/1.9/intro/tutorial01/
Now we are ready for our first serializer(just a class that allow us to conver to json to python and viceversa). Go to http://www.restapibuilder.com/ home page and enter the name of your model in the input box, in our case, City, then hit the button
The you will see a div with information about the Serializer, ModelViewSet and the new url you will need in order to have your API with posting to cities and get the list of cities, get only one city and patch that city with new information based on the id of the city.
So you need to create a new file in the cities folder called serializers.py and enter this:
from rest_framework import serializers
from .models import City
class CitySerializer(serializers.ModelSerializer):
class Meta:
model = City
The in the views.py file you enter:
from rest_framework import filters, viewsets
from .serializers import CitySerializer
from .models import City
class CityViewSet(viewsets.ModelViewSet):
model = City
serializer_class = CitySerializer
queryset = City.objects.all()
Finally you need to create the url that will be your endpoint for your cities API.
Add a new urls.py file in your cities app folder and type somehting like this:
from __future__ import unicode_literals
from django.conf.urls import patterns, url
from rest_framework import routers
from . import views
router = routers.SimpleRouter(trailing_slash=True)
router.register(r'cities', views.CityViewSet)
urlpatterns = patterns('',
)
urlpatterns += router.urls
We should go to our citiesprj/urls.py and add a new line for our cities urls.
url(r'^api/v1/cities/', include('cities.urls', namespace='cities')),
In order to use include you should add include to your import:
from django.conf.urls import url, include
Now we are ready to test our API. I included the api/v1 because your apis should be have version so v1 stands for version 1.
So if you run ./manage.py server you should be able to go to http://localhost:8000/api/v1/cities and test that your API is working. If you go to http://localhost:8000/admin you can test that the data is being posted correctly.
Congratulations!!! you made your first Django Rest Framework API.
Let me know if this was helpful to you.
Thanks.
PD. You could install localflavor via pip install django-localflavor and use it in models.py
from localflavor.us.models import USStateField, USZipCodeField
class City(models.Model):
city = models.CharField(max_lenght=50)
state = models.USStateField()
zip_code = models.USZipCodeField(db_index=True)
@property
def city_state_zip(self):
return self.city + " " + self.state + ", " + self.zip_code
class Meta:
verbose_name_plural = "Cities"
def __unicode__(self):
return self.city_state_zip
You can check the repo https://github.com/edilio/citiesprj in order to see a more complete sample.