Skip to content

Instantly share code, notes, and snippets.

@bramd
Created April 25, 2013 15:27
Show Gist options
  • Save bramd/5460611 to your computer and use it in GitHub Desktop.
Save bramd/5460611 to your computer and use it in GitHub Desktop.
An example how to expose nodes through a custom Cypher query as a queryset. This assumes you are using Neo4Django. We have a Place (or point of interest) that has an address. The address is located in a city, is located in a state, is located in a country etc. For a given node we would like to retrieve the list of places in that node. Examples: …
from neo4django.db import connections
from neo4django.db.models.script_utils import LazyNode
from neo4django.db import models
from neo4django.db.models.manager import NodeModelManager
from django.utils.translation import ugettext_lazy as _
class Country(models.NodeModel):
code = models.StringProperty(verbose_name=_('Country code'), max_length=2, indexed=True)
name = models.StringProperty(verbose_name=_('Name'))
class Meta:
verbose_name = _('Country')
verbose_name_plural = _('Countries')
def __unicode__(self):
return self.name
class State(models.NodeModel):
country = models.Relationship(Country, rel_type='located_in', single=True, related_name='states',
verbose_name=_('Country'))
code = models.StringProperty()
name = models.StringProperty(verbose_name=_('Name'))
class Meta:
verbose_name = _('State')
verbose_name_plural = _('States')
def __unicode__(self):
return self.name
class City(models.NodeModel):
state = models.Relationship(State, rel_type='located_in',single=True, related_name='cities',
verbose_name=_('State'))
name = models.StringProperty(verbose_name=_('Name'))
class Meta:
verbose_name = _('City')
verbose_name_plural = _('Cities')
def __unicode__(self):
return self.name
class Street(models.NodeModel):
name = models.StringProperty(verbose_name=_('Name'))
city = models.Relationship(City, rel_type='located_in', single=True, related_name='streets')
class Meta:
verbose_name = _('Street')
verbose_name_plural = _('Streets')
def __unicode__(self):
return self.name
class Address(models.NodeModel):
street = models.Relationship(Street, rel_type='located_in', single=True, related_name='addresses')
house_number = models.StringProperty(verbose_name=_('House Number'))
postal_code = models.StringProperty(verbose_name=_('Postal Code'))
class Meta:
verbose_name = _('Address')
verbose_name_plural = _('Addresses')
def __unicode__(self):
return _('{street} {number}, {postal_code}, {city}, {state}, {country}').format(
street=self.street,
number=self.house_number,
postal_code=self.postal_code,
city=self.street.city,
state=self.street.city.state,
country=self.street.city.state.country)
class PlaceManager(NodeModelManager):
def located_in(self, node):
cypher_query = 'START n=node({node_id}) MATCH (p)-[:address]->()-[:located_in*]->(n) return ID(p);'
table = connections['default'].cypher(cypher_query, node_id=node.id)
place_ids = [r[0] for r in table.data]
return self.filter(id__in=place_ids)
class Place(models.NodeModel):
name = models.StringProperty(verbose_name=_('Name'), indexed=True)
address = models.Relationship(Address, rel_type='address', single=True, related_name='places')
objects = PlaceManager()
class Meta:
verbose_name = _('place')
verbose_name_plural = _('places')
def __unicode__(self):
return self.name
`from django.views.generic import ListView
from django.shortcuts import get_object_or_404
from models import Country, Place
class CountryPlaceListView(ListView):
def get_queryset(self):
country = get_object_or_404(Country, code__exact=self.kwargs.get('country_code').upper())
return Place.objects.located_in(country)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment