I started by grabbing the files from the model folder from here.... adding...
NEO4J_RESOURCE_URI = '/Users/tomsmith/neo4django_db'
...to my settings.py file and then adding this code to a models.py file...
from neo4j.model import django_model as models
class Actor(models.NodeModel):
name= models.Property(indexed=True)
href = property(lambda self:('/actor/%s/' % self.node.id))
def __unicode__(self):
return self.name
class Movie(models.NodeModel):
title = models.Property(indexed=True)
year = models.Property()
href = property(lambda self:('/movies/%s/' % self.node.id))
actors = models.Relationship(Actor,type=models.Outgoing.ACTS_IN,related_name="acts_in",)
def title_length(self):
return len(self.title)
def __unicode__(self):
return self.title
... and then from within python manage.py shell I could...
>> import stuff.models as m
>> movie = m.Movie(title="Fear and Loathing in Las Vegas",year=1998)
>> movie.save()
>>> movie.save()
>>> movie.id
4L
>>>>> movie = m.Movie(title="The Brothers Grimm",year=2005)
>>> movie.save()
>>> movie.id
5L
>>> movie = m.Movie(title="Twelve Monkeys",year=1995)
>>> movie.save()
>>> movie = m.Movie(title="Memento",year=2000)
>>> movie.save()
... now I can...
>> movies = m.Movie.objects.all()
>>> for movie in movies:print movie.id, movie, movie.href
...
7 Memento /movies/7/
6 Twelve Monkeys /movies/6/
5 The Brothers Grimm /movies/5/
4 Fear and Loathing in Las Vegas /movies/4/
3 The Book of Eli /movies/3/
1 10,000 years B.C. /movies/1/
>>>
... which is fantastic! Don't you think?! The django_model is handling the db.transaction stuff. I can even do a ...
>> reload( m )
... and it doesn't break (because the database is already connected) as my earlier code did. (I think I can even run my django instance AND be connected to the neo4j database at the same time.. phew!).
What I think is fantastic about it is that using this approach I get to work with objects in a familiar way. And by that, I mean, having a schema-less database is all well and good, but almost the first thing I seem to find myself doing is creating similar types of objects. So being able to create classes (maybe even with subclasses) seems perfect for my needs ... in theory. In theory, I'd like to be able to define classes with properties but then on-the-fly maybe add extra properties to objects (without changing my class definition).
AND I can add methods to my classes... or can I ? I added a simple function to my Movie class...
def title_length(self):
return len(self.title)
...and ran...
>>> movies = m.Movie.objects.all()
>>> for movie in movies:print movie.id, movie, movie.href, movie.title_len()
...and got...
AttributeError: 'Movie' object has no attribute 'title_len'
... Boo! At this point after doing looking at the Movie objects, I found ...
>>> dir( m.Movie.objects )
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slotnames__', '__str__', '__subclasshook__', '__weakref__', '_copy_to_model', '_inherited', '_insert', '_set_creation_counter', '_update', 'aggregate', 'all', 'annotate', 'complex_filter', 'contribute_to_class', 'count', 'create', 'creation_counter', 'dates', 'defer', 'distinct', 'exclude', 'extra', 'filter', 'get', 'get_empty_query_set', 'get_or_create', 'get_query_set', 'in_bulk', 'iterator', 'latest', 'model', 'none', 'only', 'order_by', 'reverse', 'select_related', 'update', 'values', 'values_list']
...so I did a ...
>>> movies = m.Movie.objects.all().order_by('year')
...and got ...
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'NodeQuerySet' object has no attribute 'order_by'
...and the same is true for .get_or_create() or .values() or many other methods.
... so (and this isn't a criticism) it seems that the Django model is a "work in progress" (the cat ate his source code) with some of the methods still to be completed. At this point I should probably start looking at the django_model source code and begin adding to the functionality it offers... except ...
- I probably don't have the ability to create a database adapter, especially for one I don't understand
- I don't know if shoe-horning neo4j into Django is a good idea. I'm not saying it isn't ( so far, it's tantalising ) I'm just saying I don't know.
- When I find errors I'm not sure if it's me or not...
...for example, I tried...
>>> actor = m.Actor(name="Joseph Melito")
>>> actor.save()
>>> actor.id
10L
>>> actor = m.Actor(name="Bruce Willis")
>>> actor.save()
>>> actor = m.Actor(name="Jon Seda")
>>> actor.save()
...and all was fine and dandy and then I tried ...
>>> movie = m.Movie.objects.get(title="Twelve Monkeys")
>>> movie.actors.add ( actor )
... and got...
Traceback (most recent call last):
File "", line 1, in
File "/opt/local/lib/python2.5/site-packages/Neo4j.py-0.1_SNAPSHOT-py2.5.egg/neo4j/model/django_model/__init__.py", line 623, in __get__
return self._get_relationship(obj, self.__state_for(obj))
File "/opt/local/lib/python2.5/site-packages/Neo4j.py-0.1_SNAPSHOT-py2.5.egg/neo4j/model/django_model/__init__.py", line 708, in _get_relationship
states[self.name] = state = RelationshipInstance(self, obj)
File "/opt/local/lib/python2.5/site-packages/Neo4j.py-0.1_SNAPSHOT-py2.5.egg/neo4j/model/django_model/__init__.py", line 750, in __init__
self.__removed = pyneo.python.set() # contains relationships
AttributeError: 'module' object has no attribute 'set'
... I wonder if Tobias has done more work on the Relationships class at all?
No comments:
Post a Comment