theboss
theboss

Reputation: 69

Django : 'empty_form' is not used in polymorphic formsets, use 'empty_forms' instead

I am newbie at Python/Django i have been charged to migrate old project from Python 3.7 / Django 2.2.5 to the Python 3.12 and Django 5.1 but when i did this some functionality didn't work now .

For exemple before i have in the Admin interface when i click on "Add watcher" i can create watcher and in the same page choose the realted Trigger, Indicator and other staff.

But in my new version when i choose Add Watcher i have this error :

RuntimeError at /admin/watchers/watcher/add/
'empty_form' is not used in polymorphic formsets, use 'empty_forms' instead.

I am using the last version of django-polymorphic, nested-admin , I know that django-polymorphic is listed as only supporting Django versions 2.2, 3.0, 3.1, 3.2 and 4.0. It does not support Django version 5.1 , I tried the a later version using pip install git+https://github.com/jazzband/[email protected]#egg=django-polymorphic and also Django 4.x i got the same error:

from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, PolymorphicInlineSupportMixin
import nested_admin
from django.db import transaction
from watchers.models import *
 
class TriggerInline(nested_admin.NestedStackedPolymorphicInline):
    model = apps.get_model('triggers', 'Trigger')
    child_inlines = tuple([type(f'{subclass.__name__}Inline', (nested_admin.NestedStackedPolymorphicInline.Child,),
                                {
                                    'model': subclass,
                                    'inlines': [
                                        TriggerComponentInline] if subclass.__name__ == "CompositeTrigger" else []
                                }) for subclass in apps.get_model('triggers', 'Trigger').__subclasses__()])

#Same that TriggerInline
class IndicatorInline(nested_admin.NestedStackedPolymorphicInline)    

class WatcherChildAdmin(PolymorphicChildModelAdmin):
    base_model = Watcher
    inlines = (IndicatorInline, TriggerInline,)
    #Other infos

#Register subclass
for subclass in Watcher.__subclasses__():
    admin_class = type(f'{subclass.__name__}Admin',
                       (nested_admin.NestedPolymorphicInlineSupportMixin,WatcherChildAdmin,),
                       {
                           'base_model': subclass,
                           'exclude': ['periodicTask', ],
                       })
    admin.site.register(subclass, admin_class)


@admin.register(Watcher)
class WatcherParentAdmin(PolymorphicInlineSupportMixin, PolymorphicParentModelAdmin):
    base_model = Watcher
    child_models = tuple(Watcher.__subclasses__())
    #Other Functions

Both Trigger and Indicator have watcher in the model, example :

class Indicator(PolymorphicModel): ..... watcher = models.OneToOneField(Watcher, null=True, on_delete=models.CASCADE)

If you help me you are better than Chatgpt,DeepSeek,Mistral (they could not find solution)

Full traceback =>

`Environment:


Request Method: GET
Request URL: http://localhost:7000/admin/watchers/watcher/add/?ct_id=24

Django Version: 5.1
Python Version: 3.12.5
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'indicators',
 'triggers',
 'watchers',
 'underlyings',
 'users',
 'frontend',
 'rest_framework',
 'polymorphic',
 'django_celery_beat',
 'webpush',
 'corsheaders',
 'taggit',
 'taggit_serializer',
 'phone_field',
 'ckeditor',
 'ckeditor_uploader',
 'nested_admin']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.gzip.GZipMiddleware',
 'corsheaders.middleware.CorsMiddleware']



Traceback (most recent call last):
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\contrib\admin\options.py", line 718, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\utils\decorators.py", line 188, in _view_wrapper
    result = _process_exception(request, e)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\utils\decorators.py", line 186, in _view_wrapper
    response = view_func(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\views\decorators\cache.py", line 80, in _view_wrapper
    response = view_func(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\contrib\admin\sites.py", line 241, in inner
    return view(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\polymorphic\admin\parentadmin.py", line 211, in add_view
    return real_admin.add_view(request, form_url, extra_context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\contrib\admin\options.py", line 1961, in add_view
    return self.changeform_view(request, None, form_url, extra_context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\utils\decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\utils\decorators.py", line 188, in _view_wrapper
    result = _process_exception(request, e)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\utils\decorators.py", line 186, in _view_wrapper
    response = view_func(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\contrib\admin\options.py", line 1820, in changeform_view
    return self._changeform_view(request, object_id, form_url, extra_context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\contrib\admin\options.py", line 1919, in _changeform_view
    media += inline_formset.media
             ^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\contrib\admin\helpers.py", line 466, in media
    for fs in self:
              ^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\django\contrib\admin\helpers.py", line 376, in __iter__
    self.formset.empty_form,
    ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\inetpub\wwwroot\orion\venv\Lib\site-packages\polymorphic\formsets\models.py", line 292, in empty_form
    raise RuntimeError(
    ^

Exception Type: RuntimeError at /admin/watchers/watcher/add/
Exception Value: 'empty_form' is not used in polymorphic formsets, use 'empty_forms' instead.
`

Thanks

Upvotes: 0

Views: 58

Answers (1)

Arina Zlatko
Arina Zlatko

Reputation: 11

Artificial intelligence, I think, could not offer a solution because there is none.

The django-polymorphic library only supports up to version 4.0 of Django and Python up to version 3.9 according to the official documentation and there is nothing that can be done about it. There are two options: suggest leaving the project on older versions of Django and Python or replace the framework.

In the second case, you can use the built-in Django Contenttypes (GenericForeignKey) or django-model-utils (for example, InheritanceManager and, by the way, django-model-utils supports Django 3.2+ so if you take a closer look at the functionality of this framework, it might suit you.).

Unfortunately, I can't offer any other solutions.

Maybe your code could look like this (using the tools provided (must be compared with everything in your model and other code! Do not use without testing!)):

from django.contrib import admin
from model_utils.managers import InheritanceManager
#Other imports


class Watcher(models.Model):
    name = models.CharField(max_length=100)

    objects = InheritanceManager()


class Trigger(models.Model):
    watcher = models.ForeignKey(Watcher, null=True, on_delete=models.CASCADE)


class TriggerInline(nested_admin.NestedStackedInline):
    model = Trigger
    
    child_inlines = tuple([
        type(f'{subclass.__name__}Inline', (nested_admin.NestedStackedInline.Child,),
             {
                 'model': subclass,
                 'inlines': [TriggerComponentInline] if subclass.__name__ == "CompositeTrigger" else []
             }) for subclass in Trigger.__subclasses__()
    ])


class IndicatorInline(nested_admin.NestedStackedInline):
    model = apps.get_model('indicators', 'Indicator')


class WatcherChildAdmin(admin.TabularInline):
    model = Watcher
    inlines = (IndicatorInline, TriggerInline,)


@admin.register(Watcher)
class WatcherParentAdmin(admin.ModelAdmin):
    inlines = (IndicatorInline, TriggerInline)

However, you can try. And I really hope that my answer helped at least a little.

Upvotes: 0

Related Questions