with instalar framework documentar con django api rest neo4j neo4django

instalar - documentar api rest django



Crear API REST con Neo4J y Django (4)

¡Gracias a contribuciones recientes , Neo4django ahora es compatible con Tastypie fuera de la caja! Me encantaría saber qué piensas si lo pruebas.

EDITAR:

Acabo de leer el sabroso tutorial y publiqué una idea general con el ejemplo resultante. Noté que los recursos anidados son un poco divertidos, pero por lo demás funciona muy bien. Estoy bastante seguro de que los caballeros que contribuyeron con los parches que permiten este soporte también saben cómo cuidar los recursos anidados; les pediré que hablen.

EDITAR:

Siempre que las relaciones se especifiquen en ModelResource , funcionan de maravilla. Si alguien quisiera ver ejemplos, házmelo saber.

Estoy tratando de crear una API REST con Neo4j y Django en el back-end.

El problema es que incluso cuando tengo modelos Django que usan Neo4Django, no puedo usar frameworks como Tastypie o Piston que normalmente serializan modelos en JSON (o XML).

Lo siento si mi pregunta es confusa o no clara, soy un novato en los servicios web.

Gracias por tu ayuda

EDITAR: Empecé con Tastypie y seguí el tutorial en esta página http://django-tastypie.readthedocs.org/en/latest/tutorial.html . Estoy buscando mostrar la respuesta Neo4j JSON en el navegador, pero cuando intento acceder a http://127.0.0.1:8000/api/node/?format=json obtengo este error:

{"error_message": "''NoneType'' object is not callable", "traceback": "Traceback (most recent call last):/n/n File /"/usr/local/lib/python2.6/dist-packages/tastypie/resources.py/", line 217, in wrapper/n response = callback(request, *args, **kwargs)/n/n File /"/usr/local/lib/python2.6/dist-packages/tastypie/resources.py/", line 459, in dispatch_list/n return self.dispatch(''list'', request, **kwargs)/n/n File /"/usr/local/lib/python2.6/dist-packages/tastypie/resources.py/", line 491, in dispatch/n response = method(request, **kwargs)/n/n File /"/usr/local/lib/python2.6/dist-packages/tastypie/resources.py/", line 1298, in get_list/n base_bundle = self.build_bundle(request=request)/n/n File /"/usr/local/lib/python2.6/dist-packages/tastypie/resources.py/", line 718, in build_bundle/n obj = self._meta.object_class()/n/nTypeError: ''NoneType'' object is not callable/n"}

Aquí está mi código:

api.py archivo:

class NodeResource (ModelResource): #it doesn''t work with Resource neither class meta: queryset= Node.objects.all() resource_name = ''node''

archivo urls.py:

node_resource= NodeResource() urlpatterns = patterns('''', url(r''^api/'', include(node_resource.urls)),

archivo models.py:

class Node(models.NodeModel): p1 = models.StringProperty() p2 = models.StringProperty()


Aconsejaría que evite pasar las respuestas de API REST de Neo4j directamente a través de su aplicación. No solo no controlará la estructura de estos formatos de datos a medida que evolucionan y desaprueban (lo que hacen) sino que estaría exponiendo elementos internos innecesarios de su capa de base de datos.

Además de Neo4Django, tienes algunas otras opciones que quizás quieras considerar. Neomodel es otra capa de modelo diseñada para Django y pretende actuar como el ORM integrado; también tiene la opción de la capa de OGM sin procesar proporcionada por py2neo que puede ayudar pero no es específica de Django.

Vale la pena recordar que Django y sus plug-ins se han diseñado en torno a un RDBMS tradicional, no a una base de datos de gráficos, por lo que ninguna de estas soluciones será perfecta. Independientemente de lo que elija, es probable que deba realizar una buena cantidad de trabajo de transformación para crear la API de su aplicación.


Bueno, mi respuesta fue un poco vaga, así que voy a publicar cómo resolvió el problema con algún código:

Supongamos que quiero crear un recurso de aeropuerto con algunos atributos. Voy a estructurar esto en 3 archivos diferentes (por razones de legibilidad).

  • Primero: airport.py

Este archivo contendrá todos los atributos del recurso y un constructor también:

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

Este archivo se usará para crear recursos.

  • Luego, el segundo archivo: AirportResource.py : este archivo contendrá los atributos del recurso y algunos métodos básicos según la solicitud que deseemos que maneje nuestro recurso.

    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

Como se menciona en los documentos, si queremos crear una API que maneje solicitudes CREATE, GET, PUT, POST y DELETE, debemos anular / implementar los siguientes métodos:

def obj_get_list(self, bundle, **kwargs) : para OBTENER una lista de objetos

def obj_get(self, bundle, **kwargs) : OBTENER un objeto individual

def obj_create(self, bundle, **kwargs) para crear un objeto (método CREATE)

def obj_update(self, bundle, **kwargs) para actualizar un objeto (método PUT)

def obj_delete(self, bundle, **kwargs) para eliminar un objeto (método DELETE)

(ver http://django-tastypie.readthedocs.org/en/latest/non_orm_data_sources.html )

Normalmente, en ModelResource todos esos métodos están definidos e implementados, por lo que se pueden usar directamente sin ninguna dificultad. Pero en este caso, deben personalizarse de acuerdo con lo que queremos hacer.

Veamos un ejemplo de implementación de obj_get_list y obj_get :

Para obj_get_list:

En ModelResource , los datos se obtienen PRIMERO de la base de datos, luego se pueden FILTRAR según el filtro declarado en la clase META (ver http://django-tastypie.readthedocs.org/en/latest/interacting.html ). Pero no deseaba implementar dicho comportamiento (obtener todo y luego filtrar), así que hice una consulta a Neo4j dados los parámetros de la cadena de consulta:

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

y para obj_get:

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)

y finalmente una función genérica que toma como parámetro una lista de nodos y devuelve una lista de los objetos del aeropuerto:

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

  • Ahora el tercer manager.py : que se encarga de realizar consultas a la base de datos y devolver los resultados:

Antes que nada, obtengo una instancia de la base de datos usando el neo4j rest client :

from neo4jrestclient.client import * gdb= GraphDatabase("http://localhost:7474/db/data/")

luego la función que obtiene un nodo de aeropuerto:

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")

y el que realiza la búsqueda (estoy usando un complemento de servidor, vea los documentos de Neo4j para más detalles):

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

Espero que esto ayude :)


Django-Tastypie permite crear API REST con bases de datos NoSQL y también se menciona en http://django-tastypie.readthedocs.org/en/latest/non_orm_data_sources.html .

El principio es usar tastypie.resources.Resource y no tastypie.resources.ModelResource que es ESPECÍFICO para RDBMS, entonces las funciones principales deben redefinirse para proporcionar un JSON con los parámetros deseados.

Así que tomé el ejemplo dado en el enlace, lo modifiqué y usé Neo4j REST Client para Python para obtener una instancia de la base de datos y realizar solicitudes, y funcionó como un amuleto.

Gracias por todas tus respuestas :)