Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to consume data from RESTFUL API in django

I'm trying to learn django so while I have a current solution I'm not sure if it follows best practices in django. I would like to display information from a web api on my website. Let's say the api url is as follows:

http://api.example.com/books?author=edwards&year=2009 

Thsis would return a list of books by Edwards written in the year 2009. Returned in the following format:

{'results':              [                 {                    'title':'Book 1',                    'Author':'Edwards Man',                    'Year':2009                 },                 {                    'title':'Book 2',                    'Author':'Edwards Man',                    'Year':2009}            ] } 

Currently I am consuming the API in my views file as follows:

class BooksPage(generic.TemplateView):     def get(self,request):         r = requests.get('http://api.example.com/books?author=edwards&year=2009')         books = r.json()         books_list = {'books':books['results']}         return render(request,'books.html',books_list) 

Normally, we grab data from the database in the models.py file, but I am unsure if I should be grabbing this API data in models.py or views.py. If it should be in models.py, can someone provide an example of how to do this? I wrote the above example sepecifically for stackoverflow, so any bugs are purely a result of writing it here.

like image 511
user2694306 Avatar asked May 15 '15 12:05

user2694306


People also ask

Can Django consume API?

Make your newly created app entry in Django settings fileOpen consume-api-in-django/bookapp/bookapp/settings.py file. Add 'myapp' in INSTALLED_APPS list in settings.py file. Save and close the file.


2 Answers

I like the approach of putting that kind of logic in a separate service layer (services.py); the data you are rendering is quite not a "model" in the Django ORM sense, and it's more than simple "view" logic. A clean encapsulation ensures you can do things like control the interface to the backing service (i.e., make it look like a Python API vs. URL with parameters), add enhancements such as caching, as @sobolevn mentioned, test the API in isolation, etc.

So I'd suggest a simple services.py, that looks something like this:

def get_books(year, author):     url = 'http://api.example.com/books'      params = {'year': year, 'author': author}     r = requests.get(url, params=params)     books = r.json()     books_list = {'books':books['results']}     return books_list 

Note how the parameters get passed (using a capability of the requests package).

Then in views.py:

import services class BooksPage(generic.TemplateView):     def get(self,request):         books_list = services.get_books('2009', 'edwards')         return render(request,'books.html',books_list) 

See also:

  • Separation of business logic and data access in django
like image 88
bimsapi Avatar answered Oct 17 '22 19:10

bimsapi


Use the serializer instead of .json, as it gives flexibility to return in a number of formats.As while using rest-api , the provided serializer use is preferred.

Also keep the data handling and get data requests in view.py.The forms are used for templating not as the business logic.

like image 23
Prateek099 Avatar answered Oct 17 '22 18:10

Prateek099