From 9ca3eb362ec420112bb2a1f0dda25d27240fc645 Mon Sep 17 00:00:00 2001 From: Alisson Patricio Date: Thu, 24 Jun 2021 16:52:01 -0300 Subject: [PATCH] add django admin register (#56) now it works the list view and the form view --- django_neomodel/__init__.py | 66 ++++++++++++++++++++++++++++++++++--- django_neomodel/admin.py | 4 +++ tests/settings.py | 6 +++- tests/someapp/admin.py | 19 ++++++++--- tests/someapp/models.py | 18 ++++++++-- tests/urls.py | 4 ++- 6 files changed, 103 insertions(+), 14 deletions(-) create mode 100644 django_neomodel/admin.py diff --git a/django_neomodel/__init__.py b/django_neomodel/__init__.py index af036158..3b63d056 100644 --- a/django_neomodel/__init__.py +++ b/django_neomodel/__init__.py @@ -3,11 +3,13 @@ from django.db.models import signals from django.db.models.fields import BLANK_CHOICE_DASH from django.conf import settings -from django.forms import fields +from django.forms import fields as form_fields from django.db.models.options import Options from django.core.exceptions import ValidationError -from neomodel import RequiredProperty, DeflateError, StructuredNode +from neomodel import RequiredProperty, DeflateError, StructuredNode, UniqueIdProperty +from neomodel.core import NodeMeta +from neomodel.match import NodeSet __author__ = 'Robin Edwards' @@ -39,17 +41,29 @@ class DjangoField(object): concrete = True editable = True creation_counter = 0 + unique = False + primary_key = False + auto_created = False def __init__(self, prop, name): self.prop = prop self.name = name + self.remote_field = name + self.attname = name + self.verbose_name = name self.help_text = getattr(prop, 'help_text', '') + + if isinstance(prop, UniqueIdProperty): + # this seems that can be implemented in neomodel + # django-neomodel does have the needed code already but neomodel does not support + prop.primary_key = True + self.primary_key = getattr(prop, 'primary_key', False) self.label = prop.label if prop.label else name form_cls = getattr(prop, 'form_field_class', 'Field') # get field string - self.form_class = getattr(fields, form_cls, fields.CharField) + self.form_class = getattr(form_fields, form_cls, form_fields.CharField) self._has_default = prop.has_default self.required = prop.required @@ -133,7 +147,42 @@ def get_choices(self, include_blank=True): return first_choice + choices -class DjangoNode(StructuredNode): +class Query: + select_related = False + order_by = ['pk'] + + +class NeoNodeSet(NodeSet): + query = Query() + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.model = self.source + + def count(self): + return len(self) + + def _clone(self): + return self + + +class NeoManager: + def __init__(self, model): + self.model = model + + def get_queryset(self): + return NeoNodeSet(self.model) + + +class MetaClass(NodeMeta): + def __new__(cls, *args, **kwargs): + super_new = super().__new__ + new_cls = super_new(cls, *args, **kwargs) + setattr(new_cls, "_default_manager", NeoManager(new_cls)) + return new_cls + + +class DjangoNode(StructuredNode, metaclass=MetaClass): __abstract_node__ = True @classproperty @@ -142,10 +191,13 @@ def _meta(self): raise NotImplementedError('unique_together property not supported by neomodel') opts = Options(self.Meta, app_label=self.Meta.app_label) - opts.contribute_to_class(self.__class__, self.__class__.__name__) + opts.contribute_to_class(self, self.__name__) for key, prop in self.__all_properties__: opts.add_field(DjangoField(prop, key), getattr(prop, 'private', False)) + if getattr(prop, "primary_key", False): + self.pk = prop + self.pk.auto_created = True return opts @@ -178,6 +230,8 @@ def validate_unique(self, exclude): # see if any nodes already exist with each property for key in unique_props: + if key == 'pk' and getattr(self.__class__, key).auto_created: + continue val = getattr(self.__class__, key).deflate(props[key]) node = cls.nodes.get_or_none(**{key: val}) @@ -204,3 +258,5 @@ def post_delete(self): if getattr(settings, 'NEOMODEL_SIGNALS', True): signals.post_delete.send(sender=self.__class__, instance=self) + def serializable_value(self, attr): + return str(getattr(self, attr)) diff --git a/django_neomodel/admin.py b/django_neomodel/admin.py new file mode 100644 index 00000000..e46d4b87 --- /dev/null +++ b/django_neomodel/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin + +def register(model, model_admin): + admin.site.register([model], model_admin) \ No newline at end of file diff --git a/tests/settings.py b/tests/settings.py index d2a8047f..ac201648 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -53,6 +53,7 @@ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.sites', + 'django.contrib.staticfiles', # Third party 'django_neomodel', @@ -69,6 +70,9 @@ "django.contrib.messages.middleware.MessageMiddleware", ] +STATIC_ROOT = "./static/" +STATIC_URL = '/static/' + DJANGO_SUPERUSER_PASSWORD = "1234" DJANGO_SUPERUSER_EMAIL = "example@example.com" -DJANGO_SUPERUSER_USERNAME = "admin" +DJANGO_SUPERUSER_USERNAME = "admin" \ No newline at end of file diff --git a/tests/someapp/admin.py b/tests/someapp/admin.py index 49010d17..6bcded4d 100644 --- a/tests/someapp/admin.py +++ b/tests/someapp/admin.py @@ -1,12 +1,21 @@ -from django.contrib import admin +from django.contrib import admin as dj_admin +from django_neomodel import admin as neo_admin +from .models import Library, Book, Shelf -from .models import Library - -@admin.register(Library) -class LibraryAdmin(admin.ModelAdmin): +class LibraryAdmin(dj_admin.ModelAdmin): list_display = ( "id", "name", ) +dj_admin.site.register(Library, LibraryAdmin) + + +class BookAdmin(dj_admin.ModelAdmin): + list_display = ("title", "created") +neo_admin.register(Book, BookAdmin) + +class ShelfAdmin(dj_admin.ModelAdmin): + list_display = ("name",) +neo_admin.register(Shelf, ShelfAdmin) diff --git a/tests/someapp/models.py b/tests/someapp/models.py index e33f1c26..37eeef6f 100644 --- a/tests/someapp/models.py +++ b/tests/someapp/models.py @@ -13,7 +13,7 @@ class Meta: class Book(DjangoNode): - uid = UniqueIdProperty() + uid = UniqueIdProperty(primary_key=True) title = StringProperty(unique_index=True) format = StringProperty(required=True) # check required field can be omitted on update status = StringProperty(choices=( @@ -24,4 +24,18 @@ class Book(DjangoNode): created = DateTimeProperty(default=datetime.utcnow) class Meta: - app_label = 'someapp' + app_label = "someapp" + + def __str__(self): + return self.title + + +class Shelf(DjangoNode): + uid = UniqueIdProperty(primary_key=True) + name = StringProperty() + + class Meta: + app_label = "someapp" + + def __str__(self): + return self.name \ No newline at end of file diff --git a/tests/urls.py b/tests/urls.py index bd22e9e9..d78216a6 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -1,5 +1,7 @@ from django.conf.urls import url from django.contrib import admin +from django.conf import settings +from django.conf.urls.static import static -urlpatterns = [url(r"^admin/", admin.site.urls)] +urlpatterns = [url(r"^admin/", admin.site.urls)] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)