Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Well my answer was a bit vague so I'm gonna post how a solved the problem with some code:</p> <p>Assume that I want to create an airport resource with some attributes. I will structure this in 3 different files (for readability reasons). </p> <ul> <li>First : <code>airport.py</code></li> </ul> <p>This file will contain all the resource attributes and a constructor too : </p> <pre><code>from models import * class Airport(object): def __init__ (self, iata, icao, name, asciiName, geonamesId, wikipedia, id, latitude, longitude): self.icao = icao self.iata = iata self.name = name self.geonamesId = geonamesId self.wikipedia = wikipedia self.id = id self.latitude = latitude self.longitude = longitude self.asciiName = asciiName </code></pre> <p>This file will be used in order to create resources.</p> <hr> <ul> <li><p>Then the second file : <code>AirportResource.py</code>: This file will contain the resource attributes and some basic methods depending on which request we want our resource to handle.</p> <pre><code>class AirportResource(Resource): iata = fields.CharField(attribute='iata') icao = fields.CharField(attribute='icao') name = fields.CharField(attribute='name') asciiName = fields.CharField(attribute='asciiName') latitude = fields.FloatField(attribute='latitude') longitude = fields.FloatField(attribute='longitude') wikipedia= fields.CharField(attribute='wikipedia') geonamesId= fields.IntegerField(attribute='geonamesId') class Meta: resource_name = 'airport' object_class = Airport allowed_methods=['get', 'put'] collection_name = 'airports' detail_uri_name = 'id' def detail_uri_kwargs(self, bundle_or_obj): kwargs = {} if isinstance(bundle_or_obj, Bundle): kwargs['id'] = bundle_or_obj.obj.id else: kwargs['id'] = bundle_or_obj.id return kwargs </code></pre></li> </ul> <p>As mentioned in the docs, if we want to create an API that handle CREATE, GET, PUT, POST and DELETE requests, we must override/implement the following methods : </p> <p><code>def obj_get_list(self, bundle, **kwargs)</code> : to GET a list of objects </p> <p><code>def obj_get(self, bundle, **kwargs)</code> : to GET an individual object</p> <p><code>def obj_create(self, bundle, **kwargs)</code> to create an object (CREATE method)</p> <p><code>def obj_update(self, bundle, **kwargs)</code> to update an object (PUT method)</p> <p><code>def obj_delete(self, bundle, **kwargs)</code> to delete an object (DELETE method)</p> <p>(see <a href="http://django-tastypie.readthedocs.org/en/latest/non_orm_data_sources.html" rel="nofollow">http://django-tastypie.readthedocs.org/en/latest/non_orm_data_sources.html</a>) </p> <p>Normally, in <code>ModelResource</code> all those methods are defined and implemented, so they can be used directly without any difficulty. But in this case, they should be customized according to what we want to do.</p> <p>Let's see an example of implementing <code>obj_get_list</code> and <code>obj_get</code> : </p> <p>For obj_get_list:</p> <p>In <code>ModelResource</code>, the data is FIRSTLY fetched from the database, then it could be FILTERED according to the filter declared in META class ( see <a href="http://django-tastypie.readthedocs.org/en/latest/interacting.html" rel="nofollow">http://django-tastypie.readthedocs.org/en/latest/interacting.html</a>). But I didn't wish to implement such behavior (get everything then filter), so I made a query to Neo4j given the query string parameters:</p> <pre><code>def obj_get_list(self,bundle, **kwargs): data=[] params= [] for key in bundle.request.GET.iterkeys(): params.append(key) if "search" in params : query= bundle.request.GET['search'] try: results = manager.searchAirport(query) data = createAirportResources(results) except Exception as e: raise NotFound(e) else: raise BadRequest("Non valid URL") return data </code></pre> <p>and for obj_get: </p> <pre><code>def obj_get(self, bundle, **kwargs): id= kwargs['id'] try : airportNode = manager.getAirportNode(id) airport = createAirportResources([airportNode]) return airport[0] except Exception as e : raise NotFound(e) </code></pre> <p>and finally a generic function that takes as parameter a list of nodes and returns a list of Airport objects:</p> <pre><code>def createAirportResources(nodes): data= [] for node in nodes: iata = node.properties['iata'] icao = node.properties['icao'] name = node.properties['name'] asciiName = node.properties['asciiName'] geonamesId = node.properties['geonamesId'] wikipedia = node.properties['wikipedia'] id = node.id latitude = node.properties['latitude'] longitude = node.properties['longitude'] airport = Airport(iata, icao, name, asciiName, geonamesId, wikipedia, id, latitude, longitude) data.append(airport) return data </code></pre> <hr> <ul> <li>Now the third <code>manager.py</code> : which is in charge of making queries to the database and returning results : </li> </ul> <p>First of all, I get an instance of the database using <code>neo4j rest client</code> framework : </p> <pre><code>from neo4jrestclient.client import * gdb= GraphDatabase("http://localhost:7474/db/data/") </code></pre> <p>then the function which gets an airport node : </p> <pre><code>def getAirportNode(id): if(getNodeType(id) == type): n= gdb.nodes.get(id) return n else: raise Exception("This airport doesn't exist in the database") </code></pre> <p>and the one to perform search (I am using a server plugin, see Neo4j docs for more details): </p> <pre><code>def searchAirport(query): airports= gdb.extensions.Search.search(query=query.strip(), searchType='airports', max=6) if len(airports) == 0: raise Exception('No airports match your query') else: return results </code></pre> <p>Hope this will help :)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload