I want to automatically create a Collection when a Page instance is saved and link it to the page using a FK, and it needs to be deleted if the page instance is deleted.
class CustomProject(BasePage):
description = models.TextField(_("description"), default="", blank=True)
main_section_image = models.ForeignKey(
"wagtailimages.Image",
verbose_name=_("Main section image"),
on_delete=models.PROTECT,
related_name="+",
)
images_collection = models.ForeignKey(
Collection,
on_delete=models.PROTECT,
null=True,
blank=True,
editable=False,
)
content_panels = BasePage.content_panels + [
FieldPanel("description", classname="full"),
FieldPanel("main_section_image"),
HelpPanel(_(
"To manage the project's photos, firstly save this page's changes "
"(either as Draft or Published) and then go to the "
"<a href=\"/cms/images\">%(url_label)s</a>, "
"select the collection with the same namne as this project and "
"there add the images."
) % {"url_label": "Images section"}),
]
parent_page_types = ["cms_site.CustomProjectsPage"]
page_description = _("Custom project page.")
template = "pages/custom_projects/custom_project.html"
def save(self, clean=True, user=None, log_action=False, **kwargs):
self.create_or_update_collection()
return super().save(clean, user, log_action, **kwargs)
def delete(self, *args, **kwargs):
print("calling delete")
self.delete_collection()
super().delete(self, *args, **kwargs)
def create_or_update_collection(self):
collection_name = f"[Projecte a mida] {self.title}"
if not self.images_collection:
root_node = Collection.objects.get(id=get_root_collection_id())
new_collection = root_node.add_child(name=collection_name)
self.images_collection = new_collection
else:
self.images_collection.name = collection_name
self.images_collection.save()
def delete_collection(self):
if self.images_collection:
Collection.objects.get(id=self.images_collection.id).delete()
The delete() method is not called at all, neither deleting a Draft or a Published instance.
The save() is working perfectly fine in both cases.
Is that the expected behavior for some reason?
Should I rely only in something like signals or hooks for this purpose? (I imagine that's the answer, but I still don't get why the save is called and the delete is not)
BassePage is not messing with it, I don't think it's relevant but i paste it here to share the full code:
class BasePage(Page):
header_image = models.ForeignKey(
"wagtailimages.Image",
verbose_name=_("Header image"),
on_delete=models.PROTECT,
related_name="+",
null=True,
blank=False,
)
content_panels = Page.content_panels + [
FieldPanel("header_image"),
]
show_in_menus_default = False
class Meta:
abstract = True
Thanks a lot!
Edit: in case someone wants an example on how to implement it using hooks, is really simple and well documented.
Just create a wagtail_hooks.py file at the root of your app with:
from wagtail import hooks
from wagtail.models import Collection
from apps.cms_site.models import CustomProject
@hooks.register("after_delete_page")
def after_delete_custom_project(request, page):
if (
request.method == 'POST'
and page.specific_class is CustomProject
and page.images_collection
):
Collection.objects.get(id=page.images_collection.id).delete()