Hello! My main area of activity is the development of mobile applications (iOS, Android). And most applications use interaction with other users, data storage and other tasks that require a single server. Therefore, for most applications, you have to write your backend
bike . And since I, basically, am a mobile developer, then writing this service always becomes a small problem - you have to use a web developer or look for a suitable BaaS service, even if you only need to write a couple of requests.
Therefore, it was decided to try to find a tool that allows you to quickly write a small web service that could be used in a mobile application.
The initial data were taken: knowledge of what is HTTP, REST, JSON and the initial level of development in Python (Django).
And the other day, I came across a small project on which it was possible to conduct field trials. The essence of the project - an application for a single event. It is necessary to display the speakers and their reports.
After a brief search, the following tools were taken as the basis: Python (as the main development language), Django (as the base platform) and Tastypie framework (presented as the framework for creating the web services API). So let's get started.
Create a Django application template:
python django-admin.py startproject EventApp
In the settings of the settings.py file, we register the necessary settings for the database, localization, time. Install package tastypie:
pip install django-tastypie
Please note that
Python2.6 + and
Django 1.5+ are required. Due to ignorance of this fact, I had to spend a little more time, because The framework refused to work. In addition, you need to install the python-mimeparse package in the same way.
Further, in the settings.py file, we register:
INSTALLED_APPS += ['tastypie']
or add already in the existing list application 'tastypie'.
Now we will write the models of our subject area:
We wrote a speaker model (Speaker) and a speech model (Event). Every speech must have a speaker. Now, we will do so that we can fully work with our models as resources through the REST protocol.
Create an api package in our application and a resources.py file (or you can create it in the main package).
from tastypie.resources import ModelResource from EventApp.models import Speaker, Event class SpeakerResource(ModelResource): class Meta: queryset = Speaker.objects.all() resource_name = 'speaker' class EventResource(ModelResource): speaker = fields.ForeignKey(SpeakerResources, 'speaker', blank=True, null=True) class Meta: queryset = Event.objects.all() resource_name = 'event'
In this file we have created classes, the so-called resources, the main objects in our REST service. These are the resources that we will turn to. Each class contains a link to the model that it represents. The queryset field returns us a set of objects obtained from the database when accessing this resource. The resource_name field is optional, and allows us to specify in addition the name of the resource by which it will be available to us.
One more thing, in the EventResources class, we specified a separate speaker field, which indicates that the event resource refers to the speaker resource.
Now it remains only to register in the
urls.py file the calls to our service. It makes it very simple.
from django.conf.urls.defaults import * from tastypie.api import Api from api.resources import EventResource, SpeakerResource v1_api = Api(api_name='v1') v1_api.register(SpeakerResource()) v1_api.register(EventResource()) urlpatterns = patterns('', (r'^api/', include(v1_api.urls)), )
Now we start our project.
python manage.py runserver
Now, if the server has started successfully, opening the page in the browser at
http: // localhost: 8000 / api / entry /? Format = json , we will see there that the framework sees all our resources and has displayed to us the scheme of our service:
{ "events": { "list_endpoint": "/api/v1/events/" , "schema": "/api/v1/events/schema/" } ,"speakers": { "list_endpoint": "/api/v1/speakers/" ,"schema": "/api/v1/speakers/schema/" } }
The format parameter forcibly indicates in what format we want to receive data, but instead of it, you can specify the header Content-type: application / json in the request. In addition to JSON, xml, yaml, bplist are supported.
At the schema address, you can see the description of the model structure (fields, types and description), and at the list_endpoint address you can already receive our resources, which we previously recorded in the database.
Now, by opening the address
http: // localhost: 8000 / api / v1 / events /? Format = json we will see there something like this:
{ "meta": { "limit": 20 ,"next": null ,"offset": 0 ,"previous": null ,"total_count": 4 } ,"objects": [ { "id": 3 ,"speaker": "/api/v1/speakers/2/" ,"start_time": "08:39:25" ,"end_time": "18:39:29" ,"title": " " ,"description": "" } ] }
As you can see - nothing complicated. In the meta section displays basic information about the resource: the number of records, the size of the issue and so on. At the same time, we can access a specific event by accessing the resource by its id -
http: // localhost: 8000 / api / v1 / events / 1 /We can create an entry by performing a POST request and passing the object into it in JSON format, update the PUT entry with the query and delete it using DELETE.
Also, in tastypie, the ModelResource class has a large set of redefinable fields and methods, with which we can completely change the structure of the output data. For example, instead of a link to the speaker, we want to immediately receive his name in order not to make an extra request. In the EventResource class, override the dehydrate method:
def dehydrate(self, bundle): try: speaker = Speaker.objects.filter(id=bundle.obj.speaker.id) bundle.data['speaker_name'] = speaker[0].name except Speaker.DoesNotExist: pass return bundle
In it, we find the speaker in the database and substitute it into the bundle object, which is a dictionary that is given to the resource. Now, the answer to the request will look like this (I will write only the main part):
{ "id": 3 ,"speaker": "/api/v1/speakers/2/" ,"speaker_name": "" ,"start_time": "08:39:25" ,"end_time": "18:39:29" ,"title": " " ,"description": "" }
What we needed! In addition, a request for a resource can be made with parameters for filtering.
For example, we need to select all events for one speaker. The following query would be logical:
http: // localhost: 8000 / api / v1 / events /? speaker = 1 which will return events for which we have speakers with id = 1. We just need to add another field to the resource class in the meta:
filtering = { 'speaker': ALL_WITH_RELATIONS }
Conclusion
Fine! Now we can access the server, receive data from it. But this is exactly what we needed.
If the article is of interest, then you can continue the story of how to add validation, authorization, and fasten a nice admin panel in such a short time.