Вы находитесь на странице: 1из 7

4/14/2016

BuildingaRESTfulAPIwithDjangorestframeworkAgiliqBlog|Djangowebappdevelopment

W ar smal, intelligen App


developmen studi. W lov "Buildin
Amin App", solvin problem an
cultivatin stron relationship wit our
client.
Home

Blog

Dec. 2014

Building a RESTful API with Django-rest-framework

Building a RESTful API with Django-restframework


By : Rakesh Vidya Chandra

RECENT ARTICLES
Template fragment caching gotchas
Retrying celery failed tasks

4th Dec., 2014


API's turned to be the heart of every application in our time. With the rise of
social media, API's are being developed at a faster pace and gaining a lot of

Comments

attention. Gone are the days where RPC architectures like CORBA and XML-RPC
are used to enable the exchange of information and REST has taken its place
making its mark in getting the things pretty straight forward.
We use APIs in our everyday life. Take an instance booking a ticket for a movie
through some website. Here is the process that takes place in the background.
When dealing with the payment for the ticket, the website connects to the bank
and sends your credit card details to the remote application and it gets verified.
And once, the payment is confirmed by the remote application, it sends a
confirmation response to the movie booking website to issue the tickets. The
payment stuff turned possible here as the bank facilitates an API through which a
website can connect to it and deal with the payments which resulted us an
effective and seamless transaction.
In this post we will get to know how to build a Restful API for an application using
a Django-rest-framework. Before dipping ourselves in the API building stuff, let us
acquire a picture on REST.

REST
In simple words REST is a web architecture which lives on top of HTTP. It's a way
in which we should use HTTP where it acts as a set of guiding principles behind
the given application. It allows the clients and servers to communicate with each
other in all the possible ways like getting the resource, posting the resource,
deleting etc. REST is a resource based on which we use an HTTP verb to dictate
what operation we want to do on a URI which can be GET, POST and so on. In
REST we represent the resource data in JSON and XML format. An API is called a
Restful API if it adheres to all the interaction constraints of REST.

Django-rest-framework
Django-rest-framework makes the process of building web API's simple and
flexible. With its batteries included it won't be a tedious task to create an API.
Before creating our own API let us look into some vital parts of the REST
framework The important parts of Django-rest-framework are:
Serialization and Deserialization: The first part in the process of building an
API is to provide a way to serialize and deserialize the instances into
representations. Serialization is the process of making a streamable
representation of the data which will help in the data transfer over the
network. Deserialization is its reverse process. In our process of building an
API we render data into JSON format. To achieve this Django-rest-framework
provides JSONRenderer and JSONParser. JSONRenderer renders the request
data into JSON, using utf-8 encoding and JSONParser parses the JSON request
content.
Without dipping inside the technicalities let us see how it takes place.
Serializing data with JSONRenderer:
A JSONRenderer converts the request data into JSON using utf-8 encoding.
Normally we use this when we want our data to be streamable.
>>>data

http://agiliq.com/blog/2014/12/buildingarestfulapiwithdjangorestframework/

1/7

4/14/2016

>>>data

BuildingaRESTfulAPIwithDjangorestframeworkAgiliqBlog|Djangowebappdevelopment

{'cal_id':u'2','username':u'tester'}
>>>content=JSONRenderer().render(data)
>>>content
'{"cal_id":"2","username":"tester"}'

Deserializing data with JSONParser:


A JSONParser parses the JSON request content. Firstly, we parse a stream into
Python native datatypes with BytesIO and then we will restore those native
datatypes into to a fully populated object instance afterwards. We use JSONParser
to desrialize the data.
>>>content
'{"cal_id":"2","username":"tester"}'
>>>stream=BytesIO(content)
>>>data=JSONParser().parse(stream)
>>>data
{u'username':u'tester',u'cal_id':u'2'}

Requests and Responses


Requests and responses are the essential parts of Django-rest-framework which
provides flexibility while parsing.
Request objects:
The request object in REST framework has more abilities. The attribute
request.DATA in Request object is similar to Request.POST added with the
capabilities of handling arbitrary data which works for 'POST', 'PUT' and 'PATCH'
methods. And also we can use the different attributes like request.FILES,
request.QUERY_PARAMS, request.parsers, request.stream which will help in
dealing with the request a hassle free task.
Response objects:
The Response object helps to render the correct content type as requested by the
client unlike the normal HttpResponse.
Syntax: Response(data, status=None, template_name=None, headers=None,
content_type=None)
Status Codes: Instead of using the normal HTTP status codes, we will make use of
explicit identifiers for every status code to make the process of reading the status
code much simple. Here are some status codes that we represent in a REST
framework we use normally.
HTTP_200_OK
HTTP_201_CREATED
HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_403_FORBIDDEN

Views: APIView is a view provided by Django-rest-framework which


subclasses the Django's view class. If we use this view the requests passed to
the handler methods will no more Django's HttpRequest instances and they
will be REST framework's Request instances. And while dealing with the
responses they work to set the correct renderer on the response. The process
of authentication and the permissions stuff also will be dealt with it.

Creating an API with Django-rest-framework


Using all the above stuff lets us build a simple API which gives the details of a
user. The procedure goes the following way:
We will be using Django's built in user in this example. We will create a
serializers.py file where we create serializers which are similar to Django forms.
Just like model forms we have got model serializers here, which will stop
replication of code. And we create a view which lists all the users, creates a new
user, retrieve a user and update a user.
1. Here we go with the installation with virtual environment activated:
pipinstalldjangorestframework

http://agiliq.com/blog/2014/12/buildingarestfulapiwithdjangorestframework/

2/7

4/14/2016

BuildingaRESTfulAPIwithDjangorestframeworkAgiliqBlog|Djangowebappdevelopment
2. Create a Django project and an app. I created it with a name rest_example
and restapp
djangoadmin.pystartprojectrest_example
cdrest_example
pythonmanage.pystartapprestapp

3. Add rest_framework and the app name to the installed apps.


INSTALLED_APPS=(
...
'rest_framework',
'restapp')

4. Run syncdb command


pythonmanage.pysyncdb

5. Create a restapp/serializers.py which should look like the below way.


fromdjango.contrib.auth.modelsimportUser
fromrest_frameworkimportserializers
classUserSerializer(serializers.ModelSerializer):
classMeta:
model=User
fields=('id','username','first_name','last_name',

6. Create a restapp/views.py file for listing all users, creating a new user and so
on.
fromdjango.contrib.auth.modelsimportUser
fromdjango.httpimportHttp404
fromrestapp.serializersimportUserSerializer
fromrest_framework.viewsimportAPIView
fromrest_framework.responseimportResponse
fromrest_frameworkimportstatus
classUserList(APIView):
"""
Listallusers,orcreateanewuser.
"""
defget(self,request,format=None):
users=User.objects.all()
serializer=UserSerializer(users,many=True)
returnResponse(serializer.data)
defpost(self,request,format=None):
serializer=UserSerializer(data=request.DATA)
ifserializer.is_valid():
serializer.save()
returnResponse(serializer.data,status=status.HTTP_201_CREATED
returnResponse(serializer.errors,status=status.HTTP_400_BAD_REQUEST
defdelete(self,request,pk,format=None):
user=self.get_object(pk)
user.delete()
returnResponse(status=status.HTTP_204_NO_CONTENT)
classUserDetail(APIView):
"""
Retrieve,updateordeleteauserinstance.
"""
defget_object(self,pk):
try:
returnUser.objects.get(pk=pk)
exceptUser.DoesNotExist:

http://agiliq.com/blog/2014/12/buildingarestfulapiwithdjangorestframework/

3/7

4/14/2016

BuildingaRESTfulAPIwithDjangorestframeworkAgiliqBlog|Djangowebappdevelopment
raiseHttp404
defget(self,request,pk,format=None):
user=self.get_object(pk)
user=UserSerializer(user)
returnResponse(user.data)
defput(self,request,pk,format=None):
user=self.get_object(pk)
serializer=UserSerializer(user,data=request.DATA)
ifserializer.is_valid():
serializer.save()
returnResponse(serializer.data)
returnResponse(serializer.errors,status=status.HTTP_400_BAD_REQUEST
defdelete(self,request,pk,format=None):
user=self.get_object(pk)
user.delete()
returnResponse(status=status.HTTP_204_NO_CONTENT)

7. Update the root urls.py


fromdjango.conf.urlsimportpatterns,include,url
fromdjango.contribimportadmin
fromrestappimportviews
admin.autodiscover()
urlpatterns=patterns('',
url(r'^admin/',include(admin.site.urls)),
url(r'^users/',views.UserList.as_view()),
url(r'^users/(?P<pk>[09]+)/$',views.UserDetail.as_view()),)

Voila!! we are done creating our API.


Let us test our API now.
pythonmanage.pyrunserver

Now go to your browser and try localhost:8000/users/1/ or use curl on your


command line
curlhttp://127.0.0.1:8000/users/1/

You can get the user details what you have filled while creating the super user.
which would look like this.
{"id":1,"username":"restapp","first_name":"","last_name":"",

Now we can try posting data:


curlXPOSThttp://127.0.0.1:8000/users/d'{"username":"rakhi","email":"rakhi@agiliq.com"}'H"ContentType:application/json"

And it creates a new user with the username "rakhi" and email
"rakhi@agiliq.com"
{"id":6,"username":"rakhi","first_name":"","last_name":""

You can check out the example application on github

You can read all of Rakesh's post, and follow Rakesh on Twitter

Related Posts
First step to startup - Getting your pitch
New tutorial - Building a search engine with Appengine and Yahoo

http://agiliq.com/blog/2014/12/buildingarestfulapiwithdjangorestframework/

4/7

4/14/2016

BuildingaRESTfulAPIwithDjangorestframeworkAgiliqBlog|Djangowebappdevelopment
Google Appengine - First Impressions
Using Appengine with Django, why it is pretty much unusable
Two Django+Appengine Tutorials
Can we help you build amazing apps? Contact us today.
Topics: django API python Django-rest-framework REST

22Comments

http://agiliq.com/blog

Recommend 2

Share

Login

SortbyOldest

Jointhediscussion
Manjunathhugar ayearago

GoodworkRakesh.
1

Reply Share

RakeshVidyaChandra>Manjunathhugar ayearago

Thanksalotdude:)

Reply Share

Neha ayearago

Needyourhelpsolvingtheerrors.

Reply Share

AlissonMller ayearago

Veryinterestingpost!:D
Justaremark:onurls.py,aren'tthe'users'and'user'URLsinverted?
Like,theyshouldbe:
url(r'^users/',views.UserList.as_view()),
url(r'^user/(?P<pk>[09]+)/$',views.UserDetail.as_view()),)insteadof:
url(r'^user/',views.UserList.as_view()),
url(r'^users/(?P<pk>[09]+)/$',views.UserDetail.as_view()),)

Reply Share

Thiscommentwasdeleted.

AlissonMller>Guest ayearago

Oops,nowIsawthatapparently,itisgoodpracticetousethe
pluralform,evenfortheshow/delete/updateactions.
So,thoseURLscansimplybe:
url(r'^users/$',views.UserList.as_view()),
url(r'^users/(?P<pk>[09]+)/$',views.UserDetail.as_view()),
Sorryforthetrouble!
Sources:
https://bourgeois.me/rest/
https://zapier.com/learn/apis/...
1

Reply Share

GenoraInfotech ayearago

Wow!!itsanicepost.Thanksforsharingthiswithus.Formoreinfoyoumay
visit:
www.genorainfotech.com

Reply Share

ShirishGone ayearago

Guys,whatsthepointofcopypastingthedocumentation.
Withyourexperience,trytoblogsomethinguseful.

Reply Share

Blubberbot ayearago

IfoundmyissuewithaddinganewuserviaCUrl.Thereisatypeointhesection
http://agiliq.com/blog/2014/12/buildingarestfulapiwithdjangorestframework/

5/7

4/14/2016

BuildingaRESTfulAPIwithDjangorestframeworkAgiliqBlog|Djangowebappdevelopment
IfoundmyissuewithaddinganewuserviaCUrl.Thereisatypeointhesection
"Nowwecantrypostingdata:"TheCUrllinetheytellyoutouseiswrong.

Wrong:curlXPOSThttp://127.0.0.1:8000/user/d...
Right:curlXPOSThttp://127.0.0.1:8000/users/d...
1

Reply Share

RakeshVidyaChandra>Blubberbot 9monthsago

Thanksforpointingitout@Blubberbot

Reply Share

agilitynerd 10monthsago

Thanksforthedemo!InyourcurlPOSTexampleyouneedtoupdatetheURLto
http://127.0.0.1:8000/users/(insteadof/user/).
YoudemomadeiteasyformetoseehowDRFrespondedwhentherearefield
validationerrorsinaPOST.Incaseanyoneelseisinterestedifyoucreateuser
'rakhi'andthentrytocreatethatuseragainalsowithaninvalidemailaddress:
curlvXPOSThttp://127.0.0.1:8000/users/d'{"username":"rakhi",
"email":"rakhi"}'H"ContentType:application/json"
*Abouttoconnect()to127.0.0.1port8000(#0)
*Trying127.0.0.1...connected
>POST/users/HTTP/1.1
>UserAgent:curl/7.22.0(i686pclinuxgnu)libcurl/7.22.0OpenSSL/1.0.1
zlib/1.2.3.4libidn/1.23librtmp/2.3
>Host:127.0.0.1:8000
>Accept:*/*
>ContentType:application/json
>ContentLength:37
seemore

Reply Share

RakeshVidyaChandra>agilitynerd 9monthsago

Thanksalot@agilitynerd:)FIxedit.
1

Reply Share

StevenMcConnon 10monthsago

Thankyou!ThiswasbyfarthesimplesttutorialoutthereforDjangoRest
Framework.Combinewithfcgiviathistutorial:http://flailingmonkey.com/inst...
andabeginnercanlaunchanapponsharedhosting.

Reply Share

NishantNawarkhede 8monthsago
try:
returnUser.objects.get(pk=pk)
exceptUser.DoesNotExist:
raiseHttp404

Thiscanbewrittenas,
user=get_object_or_404(User,pk=pk)

Reply Share

RabiaIftikhar 7monthsago

curl:(7)Failedtoconnectto127.0.0.1port8000:Connectionrefused
Iamgettingthiserror.Needyourhelpsolvingthiserror.

Reply Share

AshishVerma 7monthsago

HiRakesh,Ineedtosendmultiplerequestinonejsonobject.
Example:
curlXPOSThttp://127.0.0.1:8000/users/d'{"username":"rakhi",
http://agiliq.com/blog/2014/12/buildingarestfulapiwithdjangorestframework/

6/7

4/14/2016

BuildingaRESTfulAPIwithDjangorestframeworkAgiliqBlog|Djangowebappdevelopment

curlXPOSThttp://127.0.0.1:8000/users/d'{"username":"rakhi",
"email":"rakhi@agiliq.com"}'H"ContentType:application/json"
curlXPOSThttp://127.0.0.1:8000/users/d'{"username":"raj",
"email":"raj@agiliq.com"}'H"ContentType:application/json"
canImakethemin1postcommand.
Thanks

Reply Share

EmadMokhtar 4monthsago

Nicepost,thanksforit.
Butwhataboutthepasswordfield?Ithinkserializer.save()willcallUser.save()
functionwhichwon'tgenerate/hashingthepasswordfortheuser.I'mwriting
thisbecauseIfacedthesameissuetoday.

Reply Share

SaurabhJhingan>EmadMokhtar 19daysago

HiEmad,
Haveyougotthecodeforthepasswordfield?
Ifnotletmeknow,Ihavemanagedtocreateone.

Reply Share

EmadMokhtar>SaurabhJhingan 19daysago

Thanks@SaurabhJhinganI'vecreatedone.

Reply Share

holdnet 2monthsago

Forallthosewhoaretryingpythonmanage.pysyncdbandgettingerror.Itis
becauseinnewerversionofdjangoithasbeenreplacedbypythonmanage.py
migrate

Reply Share

NigelLegg 22daysago

Getting:
returnResponse(serializer.data,status=status.HTTP_201_CREATED)
SyntaxError:'return'outsidefunction
??usingDjango1.7
Thelineisfromthepostfunctionintheviews.Anythoughts?

Reply Share

NigelLegg>NigelLegg 22daysago

itwasduetoincorrectindentations.
Thoughgetting500errorwithpost...

Reply Share

SaurabhJhingan 21daysago

Thanksalotbuddy.Waslookingforsomethinglikeforalongtime.
Appreciateit.

Reply Share

ALSOONHTTP://AGILIQ.COM/BLOG

UsingaPostmanhttpclientfor
efficientHTTPtestingAgiliqBlog

RetryingceleryfailedtasksAgiliq
Blog|Djangowebappdevelopment

2commentsayearago

1comment8monthsago

AvatarIshanGirdharIhavecreatedaHeader

Avatarshivakrshn49Awesomepost!!

Presetbyaddingtheessentialheaders.
ButForeverynewrequest,Ihaveto

GettingstartedwithCeleryandRedis
AgiliqBlog|Djangowebapp

Travisandcoverallsforprivaterepo
AgiliqBlog|Djangowebapp

2comments9monthsago

1commentayearago

AvatarkamalkumarjeldiHiAkshar,Thisis

AvatarDongMingHowdoesthebadgework
withtheprivaterepo?Iamhaving
troublegettingthatparttoworkandI

anexcellenttutforbeginners.butIam
facingsomeissueintheoutputof

Subscribe

AddDisqustoyoursiteAddDisqusAdd

Privacy

http://agiliq.com/blog/2014/12/buildingarestfulapiwithdjangorestframework/

7/7

Вам также может понравиться