-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
On add new nested polymorphic inline it presents all child inlines #138
Comments
Looks like this https://github.com/theatlantic/django-nested-admin/blob/master/nested_admin/static/nested_admin/src/nested-admin/jquery.djangoformset.js#L305 action is not triggered correctly. |
Could you provide an example admin.py and models.py that exhibits the issue? |
We have the same issue: models.py from django.db import models
from polymorphic.models import PolymorphicModel
class Survey(models.Model):
title = models.CharField(max_length=255)
class Question(PolymorphicModel):
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
position = models.PositiveSmallIntegerField("Position", null=True)
class Meta:
ordering = ["position"]
class FreeText(Question):
pass
class Poll(Question):
pass
class QuestionComponent(PolymorphicModel):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
position = models.PositiveSmallIntegerField("Position", null=True)
class Meta:
ordering = ["position"]
class Text(QuestionComponent):
value = models.TextField()
class Textarea(QuestionComponent):
pass
class RadioGroup(QuestionComponent):
pass
class Radio(models.Model):
radio_group = models.ForeignKey(RadioGroup, on_delete=models.CASCADE)
label = models.CharField(max_length=255)
value = models.CharField(max_length=255)
position = models.PositiveSmallIntegerField("Position", null=True) admin.py from django.contrib import admin
import nested_admin
from .models import FreeText
from .models import Poll
from .models import Question
from .models import Radio
from .models import RadioGroup
from .models import Survey
from .models import Text
from .models import Textarea
class RadioInline(nested_admin.NestedTabularInline):
model = Radio
sortable_field_name = "position"
extra = 0
min_num = 1
max_num = 8
class TextInline(nested_admin.NestedTabularInline):
model = Text
extra = 1
min_num = 1
max_num = 1
class TextareaInline(nested_admin.NestedTabularInline):
model = Textarea
extra = 1
min_num = 1
max_num = 1
class RadioGroupInline(nested_admin.NestedTabularInline):
model = RadioGroup
inlines = (RadioInline,)
extra = 0
min_num = 1
max_num = 1
class QuestionInline(nested_admin.NestedStackedPolymorphicInline):
class FreeTextInline(nested_admin.NestedStackedPolymorphicInline.Child):
model = FreeText
inlines = (TextInline, TextareaInline,)
class PollInline(nested_admin.NestedStackedPolymorphicInline.Child):
model = Poll
inlines = (TextInline, RadioGroupInline,)
model = Question
extra = 0
sortable_field_name = "position"
child_inlines = (FreeTextInline, PollInline,)
@admin.register(Survey)
class SurveyAdmin(nested_admin.NestedPolymorphicModelAdmin):
inlines = (QuestionInline,) Expected: Actual: |
Thank you for that example. I see the issue now, it might take me a bit to figure out the best way to resolve it. |
@arthurio @pod2metra could you try the branch |
@fdintino Thanks for the quick turn around! It works in term of UI (i.e. only the proper elements are displayed), but there seems to be a bug with the order in which components are created/deleted. Or it could be something where you need to create/delete the Here are two different scenarii: DeleteDeleting the Traceback (most recent call last):
File "***/lib/python3.7/site-packages/django/contrib/staticfiles/handlers.py", line 65, in __call__
return self.application(environ, start_response)
File "***/lib/python3.7/site-packages/django/core/handlers/wsgi.py", line 142, in __call__
response = self.get_response(request)
File "***/lib/python3.7/site-packages/django/core/handlers/base.py", line 78, in get_response
response = self._middleware_chain(request)
File "***/lib/python3.7/site-packages/django/core/handlers/exception.py", line 36, in inner
response = response_for_exception(request, exc)
File "***/lib/python3.7/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
File "***/lib/python3.7/site-packages/django/core/handlers/exception.py", line 125, in handle_uncaught_exception
return debug.technical_500_response(request, *exc_info)
File "***/lib/python3.7/site-packages/django_extensions/management/technical_response.py", line 37, in null_technical_500_response
six.reraise(exc_type, exc_value, tb)
File "***/lib/python3.7/site-packages/six.py", line 692, in reraise
raise value.with_traceback(tb)
File "***/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "***/lib/python3.7/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "***/lib/python3.7/site-packages/django/core/handlers/base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "***/lib/python3.7/site-packages/django/contrib/admin/options.py", line 607, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "***/lib/python3.7/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "***/lib/python3.7/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "***/lib/python3.7/site-packages/django/contrib/admin/sites.py", line 223, in inner
return view(request, *args, **kwargs)
File "***/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1650, in change_view
return self.changeform_view(request, object_id, form_url, extra_context)
File "***/lib/python3.7/site-packages/django/utils/decorators.py", line 45, in _wrapper
return bound_method(*args, **kwargs)
File "***/lib/python3.7/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "***/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1536, in changeform_view
return self._changeform_view(request, object_id, form_url, extra_context)
File "***/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1576, in _changeform_view
self.save_related(request, form, formsets, not add)
File "***/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1122, in save_related
self.save_formset(request, form, formset, change=change)
File "***/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1110, in save_formset
formset.save()
File "***/lib/python3.7/site-packages/nested_admin/formsets.py", line 143, in save
instance = self.get_saved_instance_for_form(form, commit, form_instances)
File "***/lib/python3.7/site-packages/nested_admin/formsets.py", line 229, in get_saved_instance_for_form
instances = self.save_existing_objects([form], commit)
File "***/lib/python3.7/site-packages/nested_admin/formsets.py", line 324, in save_existing_objects
self.delete_existing(obj, commit=commit)
File "***/lib/python3.7/site-packages/django/forms/models.py", line 655, in delete_existing
obj.delete()
File "***/lib/python3.7/site-packages/django/db/models/base.py", line 878, in delete
collector.collect([self], keep_parents=keep_parents)
File "***/lib/python3.7/site-packages/django/db/models/deletion.py", line 201, in collect
parent_objs = [getattr(obj, ptr.name) for obj in new_objs]
File "***/lib/python3.7/site-packages/django/db/models/deletion.py", line 201, in <listcomp>
parent_objs = [getattr(obj, ptr.name) for obj in new_objs]
File "***/lib/python3.7/site-packages/polymorphic/models.py", line 175, in accessor_function
attr = model._base_objects.get(pk=self.pk)
File "***/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "***/lib/python3.7/site-packages/django/db/models/query.py", line 399, in get
self.model._meta.object_name
nested_polymorphic.models.QuestionComponent.DoesNotExist: QuestionComponent matching query does not exist. Create
|
@fdintino You changes fixed that issue. Thank you. |
@arthurio thank you again for the detailed example! I was able to use them to create failing test cases, which made fixing them much easier. Could you pull down the latest commits on the polymorphic-fixes branch and verify that it is working now? One note: if you get an IntegrityError when you test deleting a nested polymorphic inline, that means you're encountering jazzband/django-polymorphic#229. The workaround in this comment appears to address the issue: jazzband/django-polymorphic#229 (comment) def NON_POLYMORPHIC_CASCADE(collector, field, sub_objs, using):
return models.CASCADE(collector, field, sub_objs.non_polymorphic(), using)
class MyModel(PolymorphicModel):
fk_field = models.ForeignKey(on_delete=NON_POLYMORPHIC_CASCADE) |
@fdintino The free text question works now but the choice one still doesn't. I get: Traceback (most recent call last):
File "***/lib/python3.7/site-packages/django/contrib/staticfiles/handlers.py", line 65, in __call__
return self.application(environ, start_response)
File "***/lib/python3.7/site-packages/django/core/handlers/wsgi.py", line 142, in __call__
response = self.get_response(request)
File "***/lib/python3.7/site-packages/django/core/handlers/base.py", line 78, in get_response
response = self._middleware_chain(request)
File "***/lib/python3.7/site-packages/django/core/handlers/exception.py", line 36, in inner
response = response_for_exception(request, exc)
File "***/lib/python3.7/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
File "***/lib/python3.7/site-packages/django/core/handlers/exception.py", line 125, in handle_uncaught_exception
return debug.technical_500_response(request, *exc_info)
File "***/lib/python3.7/site-packages/django_extensions/management/technical_response.py", line 37, in null_technical_500_response
six.reraise(exc_type, exc_value, tb)
File "***/lib/python3.7/site-packages/six.py", line 692, in reraise
raise value.with_traceback(tb)
File "***/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "***/lib/python3.7/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "***/lib/python3.7/site-packages/django/core/handlers/base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "***/lib/python3.7/site-packages/django/contrib/admin/options.py", line 607, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "***/lib/python3.7/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "***/lib/python3.7/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "***/lib/python3.7/site-packages/django/contrib/admin/sites.py", line 223, in inner
return view(request, *args, **kwargs)
File "***/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1647, in add_view
return self.changeform_view(request, None, form_url, extra_context)
File "***/lib/python3.7/site-packages/django/utils/decorators.py", line 45, in _wrapper
return bound_method(*args, **kwargs)
File "***/lib/python3.7/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "***/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1536, in changeform_view
return self._changeform_view(request, object_id, form_url, extra_context)
File "***/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1576, in _changeform_view
self.save_related(request, form, formsets, not add)
File "***/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1122, in save_related
self.save_formset(request, form, formset, change=change)
File "***/lib/python3.7/site-packages/django/contrib/admin/options.py", line 1110, in save_formset
formset.save()
File "***/lib/python3.7/site-packages/nested_admin/formsets.py", line 149, in save
instance = self.get_saved_instance_for_form(form, commit, form_instances)
File "***/lib/python3.7/site-packages/nested_admin/formsets.py", line 237, in get_saved_instance_for_form
instances = self.save_new_objects([form], commit)
File "***/lib/python3.7/site-packages/nested_admin/formsets.py", line 387, in save_new_objects
new_objects.append(self.save_new(form, commit=commit))
File "***/lib/python3.7/site-packages/django/forms/models.py", line 946, in save_new
pk_value = getattr(self.instance, self.fk.remote_field.field_name)
File "***/lib/python3.7/site-packages/polymorphic/models.py", line 175, in accessor_function
attr = model._base_objects.get(pk=self.pk)
File "***/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs) Edit: I got a different error after my initial post... |
Ha! Found the issue, because my radio group doesn't have any field in it, when saving, I think it's good to ship 🎉 Thanks so much for looking into it! |
Glad to hear! We have some handling for situations where the parent form Thanks again for your helpful feedback. |
So,
When I try to add any type of child model it will present all nested inlines that presented to any child. It looks like that this is JS/render template problem cause after save on new rendered models it presents only that inline that is really needed.
The text was updated successfully, but these errors were encountered: