1

I am trying to use django-treebeard in the admin section, following suggestions at https://tabo.pe/projects/django-treebeard/docs/2.0/admin.html

Using django 1.8 and treebeard 3.0 on python 3.4.

models.py:

class Site(models.Model):
    stype = models.IntegerField()
    name = models.CharField(max_length=255)


class SiteTree(NS_Node):
    site = models.ForeignKey(Site)

Please note that I need models defined this way as one site can be located at multiple points in the hierarchy. I found no tree library that would support this out of the box, so I just went with nested sets and many-to-one relationship to actual data.

I tried to add my tree to admin control panel like so (admin.py):

from django.contrib import admin
from .models import *
from treebeard.admin import admin_factory

# Register your models here.
admin.site.register((Site, SiteTree, admin_factory(SiteTree)))

What I get from this is

Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "D:\Python34\lib\site-packages\django\core\management\__init__.py", line 338, in execute_from_command_line
    utility.execute()
  File "D:\Python34\lib\site-packages\django\core\management\__init__.py", line 312, in execute
    django.setup()
  File "D:\Python34\lib\site-packages\django\__init__.py", line 18, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "D:\Python34\lib\site-packages\django\apps\registry.py", line 115, in populate
    app_config.ready()
  File "D:\Python34\lib\site-packages\django\contrib\admin\apps.py", line 22, in ready
    self.module.autodiscover()
  File "D:\Python34\lib\site-packages\django\contrib\admin\__init__.py", line 24, in autodiscover
    autodiscover_modules('admin', register_to=site)
  File "D:\Python34\lib\site-packages\django\utils\module_loading.py", line 74, in autodiscover_modules
    import_module('%s.%s' % (app_config.name, module_to_search))
  File "D:\Python34\lib\importlib\__init__.py", line 109, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 2254, in _gcd_import
  File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
  File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1129, in _exec
  File "<frozen importlib._bootstrap>", line 1471, in exec_module
  File "<frozen importlib._bootstrap>", line 321, in _call_with_frames_removed
  File "D:\Android\Projects\ApartmentTerminal\ScantronServer\settings\admin.py", line 6, in <module>
    admin.site.register((SiteTree, admin_factory(SiteTree)))
  File "D:\Python34\lib\site-packages\django\contrib\admin\sites.py", line 85, in register
    if model._meta.abstract:
  AttributeError: type object 'SiteTreeAdmin' has no attribute '_meta'

Nothing changes if I use the inheritance way of declaring the view.

What am I doing wrong?

velis
  • 8,747
  • 4
  • 44
  • 64

1 Answers1

1

The way you are calling admin.site.register is invalid - you have wrapped all your arguments in a tuple which means they get passed to the function as one argument. Try this:

admin.site.register(SiteTree, admin_factory(SiteTree))

Alternatively you can create the admin class manually like so:

from django.contrib import admin
from .models import *
from treebeard.admin import TreeAdmin
from treebeard.forms import movenodeform_factory

class SiteTreeAdmin(TreeAdmin):
    form = movenodeform_factory(SiteTree)

# Register your models here.
admin.site.register(Site)
admin.site.register(SiteTree, SiteTreeAdmin)
solarissmoke
  • 30,039
  • 14
  • 71
  • 73
  • Even after trying this, I have no idea why this would help. Iterating over tuple would require me to at most move the Site model after SiteTree and SiteTreeAdmin. Naturally, moving any of the registrations into separate calls doesn't do anything for my problem. Added full stach trace to the OP. – velis Oct 19 '15 at 06:27
  • 1
    I don't really understand your comment. Are you saying that you modified your code as I suggested, and you still get the same error? – solarissmoke Oct 19 '15 at 06:29
  • yes, that is what I'm saying. I also tried moving the `admin_factory(SiteTree)` with no success. The problem is that `treebeard.admin.TreeAdmin` class doesn't declare the necessary _meta. – velis Oct 19 '15 at 06:32
  • That error appears because `admin.site.register` is trying to treat what you supplied is as a `Model` rather than an `Admin` instance. This indicates that you are still supplying the arguments in the wrong way (e.g., wrapped in a tuple). – solarissmoke Oct 19 '15 at 06:34
  • Hm, I changed it to `admin.site.register(admin_factory(SiteTree))`, but now I get `TypeError: 'MediaDefiningClass' object is not iterable`. It would seem `admin.site.register` requires an iterable. Edit: changed to `admin.site.register(SiteTree, admin_factory(SiteTree))` and now I get `: (admin.E016) The value of 'form' must inherit from 'BaseModelForm'.`. Much more promising, but still not working. – velis Oct 19 '15 at 06:37
  • Changing to inheritance declaration fixed the problem. Let me check whether it works. Edit: it works as intended. Seems I used the factory incorrectly or maybe factory has bugs with django 1.8. – velis Oct 19 '15 at 06:42