# Django Neomodel (beta!)
![neomodel](https://raw.githubusercontent.com/neo4j-contrib/neomodel/master/doc/source/_static/neomodel-300.png)
This module allows you to use the [neo4j](https://www.neo4j.org) graph database with Django using [neomodel](http://neomodel.readthedocs.org)
## Warnings
* Admin functionality is very experimental. [Please see todos / issues here](https://github.com/neo4j-contrib/django-neomodel/projects/1)
## Live Examples (add yours here)
* [Syracuse](https://syracuse.1145.am>): a database of company linkages created from unstructured text. Repo at [syracuse-neo](https://github.com/alanbuxton/syracuse-neo.git)
# Getting started
Install the module:
$ pip install django_neomodel
Add the following settings to your `settings.py`:
NEOMODEL_NEO4J_BOLT_URL = os.environ.get('NEO4J_BOLT_URL', 'bolt://neo4j:foobarbaz@localhost:7687')
# Make sure django_neomodel comes before your own apps
INSTALLED_APPS = (
# django.contrib.auth etc
'django_neomodel',
'yourapp'
)
Write your first node definition in `yourapp/models.py`:
from neomodel import StructuredNode, StringProperty, DateProperty
class Book(StructuredNode):
title = StringProperty(unique_index=True)
published = DateProperty()
Create any constraints or indexes for your labels. This needs to be done after you change your node definitions
much like `manage.py migrate`:
$ python manage.py install_labels
Now in a view `yourapp/views.py`:
from .models import Book
def get_books(request):
return render('yourapp/books.html', request, {'books': Book.nodes.all()})
In your `yourapp/admin.py`:
from django_neomodel import admin as neo_admin
from .models import Book
class BookAdmin(dj_admin.ModelAdmin):
list_display = ("title", "created")
neo_admin.register(Book, BookAdmin)
And you're ready to go. Don't forget to check the neomodel_ documentation.
## Model forms
Switch the base class from `StructuredNode` to `DjangoNode` and add a 'Meta' class:
from datetime import datetime
from django_neomodel import DjangoNode
from neomodel import StructuredNode, StringProperty, DateTimeProperty, UniqueIdProperty
class Book(DjangoNode):
uid = UniqueIdProperty()
title = StringProperty(unique_index=True)
status = StringProperty(choices=(
('Available', 'A'),
('On loan', 'L'),
('Damaged', 'D'),
), default='Available')
created = DateTimeProperty(default=datetime.utcnow)
class Meta:
app_label = 'library'
Create a model form class for your `DjangoNode`:
class BookForm(ModelForm):
class Meta:
model = Book
fields = ['title', 'status']
This class may now be used just like any other Django form.
## Settings
The following config options are available in django settings (default values shown).
These are mapped to neomodel.config as django is started:
NEOMODEL_NEO4J_BOLT_URL = 'bolt://neo4j:neo4j@localhost:7687'
NEOMODEL_SIGNALS = True
NEOMODEL_FORCE_TIMEZONE = False
NEOMODEL_MAX_CONNECTION_POOL_SIZE = 50
## Signals
Signals work with `DjangoNode` sub-classes:
from django.db.models import signals
from django_neomodel import DjangoNode
from neomodel import StringProperty
class Book(DjangoNode):
title = StringProperty(unique_index=True)
def your_signal_func(sender, instance, signal, created):
pass
signals.post_save.connect(your_signal_func, sender=Book)
The following are supported: `pre_save`, `post_save`, `pre_delete`, `post_delete`.
On freshly created nodes `created=True` in the `post_save` signal argument.
## Testing
You can create a setup method which clears the database before executing each test:
from neomodel import db, clear_neo4j_database
class YourTestClass(DjangoTestCase):
def setUp(self):
clear_neo4j_database(db)
def test_something(self):
pass
## Management Commands
The following django management commands have been included.
### install_labels
Setup constraints and indexes on labels for your node definitions. This should be executed after any schema changes:
$ python manage.py install_labels
Setting up labels and constraints...
Found tests.someapp.models.Book
+ Creating unique constraint for title on label Book for class tests.someapp.models.Book
Finished 1 class(es).
### clear_neo4j
Delete all nodes in your database, warning there is no confirmation!
## Requirements
- Python 3.8+
- neo4j 5.x, 4.4 (LTS)
## Docker Example
Using Docker Compose.
Commands to setup Docker Container docker-entrypoint.sh:
# Go to tests
$ cd tests/
# Docker Command (Make sure Docker is running and up to date)
$ docker-compose up
# login in admin with username=admin password=1234
Go to http://localhost:7474/browser/
Go to http://localhost:8000/admin/
## Running Tests
Setup Neo4j Desktop with a local database with password 'foobarbaz' and version 5.x or 4.4.x (Neo4j LTS version).
Commands to run tests:
# create local venv and install dependencies.
$ pip install -e '.[dev]'; export DJANGO_SETTINGS_MODULE=tests.settings;
$ tests/manage.py install_labels
$ tests/manage.py migrate
$ pytest
# example output:
platform darwin -- Python 3.9.0, pytest-6.1.2, py-1.9.0, pluggy-0.13.1
pick 0900469 Neo4J-update-t-4.1
collected 16 items
someapp/tests/test_atomicity.py . [ 6%]
someapp/tests/test_commands.py .. [ 18%]
someapp/tests/test_model_form.py ........... [ 87%]
someapp/tests/test_sanity.py . [ 93%]
someapp/tests/test_signals.py .
16 passed, 11 warnings in 1.62s
Raw data
{
"_id": null,
"home_page": null,
"name": "django-neomodel",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "Marius Conjeaud <marius.conjeaud@outlook.com>",
"keywords": "graph, neo4j, django, plugin, neomodel",
"author": null,
"author_email": "Robin Edwards <robin.ge@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/b0/c2/46e9ab2a76f7e006c4955abc0ad7c70f3db5d48bcd60d9b0ac368403c911/django_neomodel-0.2.0.tar.gz",
"platform": null,
"description": "# Django Neomodel (beta!)\n\n![neomodel](https://raw.githubusercontent.com/neo4j-contrib/neomodel/master/doc/source/_static/neomodel-300.png)\n\nThis module allows you to use the [neo4j](https://www.neo4j.org) graph database with Django using [neomodel](http://neomodel.readthedocs.org)\n\n\n## Warnings\n\n* Admin functionality is very experimental. [Please see todos / issues here](https://github.com/neo4j-contrib/django-neomodel/projects/1)\n\n## Live Examples (add yours here)\n\n* [Syracuse](https://syracuse.1145.am>): a database of company linkages created from unstructured text. Repo at [syracuse-neo](https://github.com/alanbuxton/syracuse-neo.git)\n\n# Getting started\n\nInstall the module:\n\n $ pip install django_neomodel\n\nAdd the following settings to your `settings.py`:\n\n NEOMODEL_NEO4J_BOLT_URL = os.environ.get('NEO4J_BOLT_URL', 'bolt://neo4j:foobarbaz@localhost:7687')\n\n # Make sure django_neomodel comes before your own apps\n INSTALLED_APPS = (\n # django.contrib.auth etc\n 'django_neomodel',\n 'yourapp'\n )\n\nWrite your first node definition in `yourapp/models.py`:\n\n from neomodel import StructuredNode, StringProperty, DateProperty\n\n class Book(StructuredNode):\n title = StringProperty(unique_index=True)\n published = DateProperty()\n\nCreate any constraints or indexes for your labels. This needs to be done after you change your node definitions\nmuch like `manage.py migrate`:\n\n $ python manage.py install_labels\n\nNow in a view `yourapp/views.py`:\n\n from .models import Book\n\n def get_books(request):\n return render('yourapp/books.html', request, {'books': Book.nodes.all()})\n\nIn your `yourapp/admin.py`:\n\n from django_neomodel import admin as neo_admin\n from .models import Book\n\n class BookAdmin(dj_admin.ModelAdmin):\n list_display = (\"title\", \"created\")\n neo_admin.register(Book, BookAdmin)\n\nAnd you're ready to go. Don't forget to check the neomodel_ documentation.\n\n## Model forms\n\nSwitch the base class from `StructuredNode` to `DjangoNode` and add a 'Meta' class:\n\n from datetime import datetime\n from django_neomodel import DjangoNode\n from neomodel import StructuredNode, StringProperty, DateTimeProperty, UniqueIdProperty\n\n class Book(DjangoNode):\n uid = UniqueIdProperty()\n title = StringProperty(unique_index=True)\n status = StringProperty(choices=(\n ('Available', 'A'),\n ('On loan', 'L'),\n ('Damaged', 'D'),\n ), default='Available')\n created = DateTimeProperty(default=datetime.utcnow)\n\n class Meta:\n app_label = 'library'\n\nCreate a model form class for your `DjangoNode`:\n\n class BookForm(ModelForm):\n class Meta:\n model = Book\n fields = ['title', 'status']\n\nThis class may now be used just like any other Django form.\n\n## Settings\nThe following config options are available in django settings (default values shown).\nThese are mapped to neomodel.config as django is started:\n\n NEOMODEL_NEO4J_BOLT_URL = 'bolt://neo4j:neo4j@localhost:7687'\n NEOMODEL_SIGNALS = True\n NEOMODEL_FORCE_TIMEZONE = False\n NEOMODEL_MAX_CONNECTION_POOL_SIZE = 50\n\n## Signals\nSignals work with `DjangoNode` sub-classes:\n\n from django.db.models import signals\n from django_neomodel import DjangoNode\n from neomodel import StringProperty\n\n class Book(DjangoNode):\n title = StringProperty(unique_index=True)\n\n def your_signal_func(sender, instance, signal, created):\n pass\n\n signals.post_save.connect(your_signal_func, sender=Book)\n\nThe following are supported: `pre_save`, `post_save`, `pre_delete`, `post_delete`.\nOn freshly created nodes `created=True` in the `post_save` signal argument.\n\n## Testing\n\nYou can create a setup method which clears the database before executing each test:\n\n from neomodel import db, clear_neo4j_database\n\n class YourTestClass(DjangoTestCase):\n def setUp(self):\n clear_neo4j_database(db)\n\n def test_something(self):\n pass\n\n## Management Commands\n\nThe following django management commands have been included.\n\n### install_labels\nSetup constraints and indexes on labels for your node definitions. This should be executed after any schema changes:\n\n $ python manage.py install_labels\n Setting up labels and constraints...\n\n Found tests.someapp.models.Book\n + Creating unique constraint for title on label Book for class tests.someapp.models.Book\n Finished 1 class(es).\n\n### clear_neo4j\nDelete all nodes in your database, warning there is no confirmation!\n\n## Requirements\n\n- Python 3.8+\n- neo4j 5.x, 4.4 (LTS)\n\n## Docker Example\n\nUsing Docker Compose.\n\nCommands to setup Docker Container docker-entrypoint.sh:\n\n # Go to tests\n $ cd tests/\n # Docker Command (Make sure Docker is running and up to date)\n $ docker-compose up\n # login in admin with username=admin password=1234\n\nGo to http://localhost:7474/browser/\n\nGo to http://localhost:8000/admin/\n\n\n## Running Tests\n\nSetup Neo4j Desktop with a local database with password 'foobarbaz' and version 5.x or 4.4.x (Neo4j LTS version).\n\nCommands to run tests:\n\n # create local venv and install dependencies.\n $ pip install -e '.[dev]'; export DJANGO_SETTINGS_MODULE=tests.settings;\n $ tests/manage.py install_labels\n $ tests/manage.py migrate\n $ pytest\n\n # example output:\n\n platform darwin -- Python 3.9.0, pytest-6.1.2, py-1.9.0, pluggy-0.13.1\n pick 0900469 Neo4J-update-t-4.1\n collected 16 items\n\n someapp/tests/test_atomicity.py . [ 6%]\n someapp/tests/test_commands.py .. [ 18%]\n someapp/tests/test_model_form.py ........... [ 87%]\n someapp/tests/test_sanity.py . [ 93%]\n someapp/tests/test_signals.py .\n 16 passed, 11 warnings in 1.62s\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Use Neo4j with Django!",
"version": "0.2.0",
"project_urls": {
"repository": "http://github.com/robinedwards/django-neomodel"
},
"split_keywords": [
"graph",
" neo4j",
" django",
" plugin",
" neomodel"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "ca192f00a8c94b3c5c11cb0d7098adc1ef1f1baec6aad5575e9542ddb20d5a82",
"md5": "17262cac434f2f920dff882f97957c45",
"sha256": "0a1aab1bcf9f8882af6bae785e7cb8296db14e956de547857a9cbf3347230646"
},
"downloads": -1,
"filename": "django_neomodel-0.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "17262cac434f2f920dff882f97957c45",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 18156,
"upload_time": "2024-05-22T12:42:17",
"upload_time_iso_8601": "2024-05-22T12:42:17.193013Z",
"url": "https://files.pythonhosted.org/packages/ca/19/2f00a8c94b3c5c11cb0d7098adc1ef1f1baec6aad5575e9542ddb20d5a82/django_neomodel-0.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b0c246e9ab2a76f7e006c4955abc0ad7c70f3db5d48bcd60d9b0ac368403c911",
"md5": "d2032e0b0556455101ff0ee78267e75b",
"sha256": "8b4fb95924df227b323937ea7991337f7385739df5e0fbda820e0da0f4fa119a"
},
"downloads": -1,
"filename": "django_neomodel-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "d2032e0b0556455101ff0ee78267e75b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 24329,
"upload_time": "2024-05-22T12:42:18",
"upload_time_iso_8601": "2024-05-22T12:42:18.331916Z",
"url": "https://files.pythonhosted.org/packages/b0/c2/46e9ab2a76f7e006c4955abc0ad7c70f3db5d48bcd60d9b0ac368403c911/django_neomodel-0.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-22 12:42:18",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "robinedwards",
"github_project": "django-neomodel",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "neomodel",
"specs": [
[
"~=",
"5.3.0"
]
]
},
{
"name": "django",
"specs": [
[
"~=",
"4.2.8"
]
]
}
],
"lcname": "django-neomodel"
}