Last active
December 17, 2015 19:59
-
-
Save mhluongo/5664051 to your computer and use it in GitHub Desktop.
Some relationship magic to make modeling easier for situations where you want to aggregate across multiple rel-types in one relationship field. This is a very not-supported / non-standard approach, and could be broken in future versions of neo4django.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
>>> from .models import Family, Person | |
>>> | |
>>> family_1 = Family.objects.create(status='married') | |
>>> family_2 = Family.objects.create() | |
>>> | |
>>> pete = Person.objects.create(name='Pete') | |
>>> mary = Person.objects.create(name='Mary') | |
>>> | |
>>> family_1.spouses.add(pete, mary) | |
>>> family_2.children.add(pete) | |
>>> mary.families.all() | |
[<Family: Family object>] | |
>>> pete.families.all() | |
[<Family: Family object>, <Family: Family object>] | |
>>> pete.spouse_families.all() | |
[<Family: Family object>] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from neo4django.db import models | |
############################# | |
# CUSTOM RELATIONSHIP MAGIC # | |
############################# | |
from neo4django.db.models.query import (Clauses, Start, With) | |
from neo4django.db.models.relationships import (Relationship, | |
RelationshipQuerySet, | |
MultipleNodes, | |
RelationshipInstance) | |
class FamilyRelationshipQuerySet(RelationshipQuerySet): | |
def _get_start_clause(self): | |
return Clauses([ | |
Start({'m':'node({startParam})'}, ['startParam']), | |
'MATCH (m)<-[:SPOUSE|CHILD]-(n)', | |
With({'n':'n', 'typeNode':'typeNode'}) | |
]) | |
class FamilyRelationshipInstance(RelationshipInstance): | |
""" | |
The manager for the `person.families` side of the spouse|child / families | |
relationship. | |
""" | |
def remove(self, *args, **kwargs): | |
raise RuntimeError("This relationship is read-only.") | |
def clear(self, *args, **kwargs): | |
raise RuntimeError("This relationship is read-only.") | |
def add(self, *args, **kwargs): | |
raise RuntimeError("This relationship is read-only.") | |
def get_query_set(self): | |
return FamilyRelationshipQuerySet(self, self._rel, self._obj) | |
class MultipleFamilyNodes(MultipleNodes): | |
def _get_state(self, obj, states): | |
state = states.get(self.name) | |
if state is None: | |
states[self.name] = state = FamilyRelationshipInstance(self, obj) | |
return state | |
def _setup_reversed(self, target): | |
# don't set up a reverse relationship at all- target should be none | |
pass | |
class FamiliesRelationship(Relationship): | |
def _get_bound_relationship_type(self): | |
return MultipleFamilyNodes | |
##################### | |
# MODEL DEFINITIONS # | |
##################### | |
class Person(models.NodeModel): | |
class Meta: | |
app_label = 'test' | |
name = models.StringProperty() | |
born = models.DateTimeProperty() | |
died = models.DateTimeProperty() | |
sex = models.StringProperty() | |
friends = models.Relationship('self', rel_type='friends_with') | |
families = FamiliesRelationship('Family', rel_type='<<UNUSED_REL_TYPE>>') | |
class Evidence(models.NodeModel): | |
class Meta: | |
app_label = 'test' | |
name = models.StringProperty() | |
as_of = models.DateTimeProperty() | |
families = models.Relationship('Family',rel_type='FAMILY',related_name='evidence') | |
persons = models.Relationship('Person',rel_type='PERSON',related_name='evidence') | |
next = models.Relationship('self',rel_type='NEXT',related_name='prev') | |
class Family(models.NodeModel): | |
class Meta: | |
app_label = 'test' | |
status = models.StringProperty() # married, etc. | |
spouses = models.Relationship('Person',rel_type='SPOUSE', related_name='spouse_families') | |
children = models.Relationship('Person',rel_type='CHILD', related_name='children_families') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In response to http://stackoverflow.com/questions/16778888/neo4django-unexpected-warning/16782275?noredirect=1#comment24185959_16782275 .