wagtail-nest / wagtail-modeladmin

Add any model in your project to the Wagtail admin. Formerly wagtail.contrib.modeladmin.
Other
22 stars 8 forks source link

modeladmin PROTECTED with related_name="+" #30

Open m3brown opened 3 years ago

m3brown commented 3 years ago

Issue Summary

This is a bug related to wagtail/wagtail#5437, which added exception handling for deletion of objects that throw a ProtectedError.

I observed that the existing code does not work if the ForeignKey/OneToOneField relationship uses related_name="+".

AttributeError at /admin/videos/video/delete/18/
'Video' object has no attribute '+'
...
Exception Location: /wagtail/contrib/modeladmin/views.py in post, line 814

The code at line 814 is qs = getattr(self.instance, rel.get_accessor_name()), and it makes sense that the code fails when rel.get_accessor_name() == "+".

Steps to Reproduce

  1. Start a new project with wagtail start myproject
  2. Create a videos app with a Video model (code sample below)
  3. Create a VideoPage model (code sample below)
  4. Register the model admin (code sample below)
  5. Create a couple sample videos and video pages
  6. Select a video in the admin interface that is associated with a page, and delete the video
  7. Confirm the AttributeError occurs
# models.py
class Video(models.Model):
    title = models.CharField(max_length=255)

    panels = [
        FieldPanel("title"),
    ]

class VideoPage(Page):
    video = models.ForeignKey(
        "videos.Video",
        on_delete=models.PROTECT,
        related_name="+",
    )

    content_panels = Page.content_panels + [
        FieldPanel("video", widget=VideoChooser),
    ]
# wagtail_hooks.py
from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register

class VideoModelAdmin(ModelAdmin):
    @cached_property
    def model(self):
        from videos.models import Video

        return Video

modeladmin_register(VideoModelAdmin)

Any other relevant information. For example, why do you consider this a bug and what did you expect to happen instead?

The workarounds for this scenario I'm aware of are:

Technical details