public
Created

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: places in Amsterdam, places in The Netherlands etc.

  • Download Gist
models.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
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
views.py
Python
1 2 3 4 5 6 7 8
`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)

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.