Skip to content
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

Plugin tree - possible? #29

Open
benzkji opened this issue Aug 6, 2024 · 11 comments
Open

Plugin tree - possible? #29

benzkji opened this issue Aug 6, 2024 · 11 comments

Comments

@benzkji
Copy link

benzkji commented Aug 6, 2024

I work with django-cms, and like the ability to have nested plugins. Simple use case, have a gallery plugin, place picture plugins in it. Or even picture AND video plugins, mixed, if the frontend allows.

Is this somehow possible, with django-content-editor? Or is it not, by design, and will never be? I guess the later, but hope not.

@matthiask
Copy link
Member

Hi @benzkji

Right now it's not possible. What we do instead is use subregions to automatically group related plugins (e.g. a list of images is automatically grouped into a gallery) https://feincms3.readthedocs.io/en/latest/guides/rendering.html#grouping-plugins-into-subregions

You could add a GalleryPlugin, (for example having a title field or something) and register it with the renderer as follows:

renderer.register(models.GalleryPlugin, "", subregion="gallery")
renderer.register(models.Image, template_renderer("plugins/image.html"), marks={"default", "gallery"})
renderer.register(models.Video, template_renderer("plugins/video.html"), marks={"default", "gallery"})

In the renderer implementation, you'd have something like this:

def handle_gallery(self, plugins, context):
    gallery = plugins.popleft()
    yield render_in_context(
        context,
        "subregions/gallery.html",
       {"gallery": gallery, "slides": [self.render_plugin(plugin, context) for plugin in self.takewhile_mark(plugins, "gallery")]},
    )

So, the content model is powerful enough to do what you want, even though the editor interface doesn't support nesting at this time.

Or what we're doing more recently is adding configurable sections, something like this:

CLOSE_SECTION = "close"


class Section(JSONPluginBase, PagePlugin):
   class Meta:
       verbose_name = _("section")
       verbose_name_plural = _("sections")

   def __str__(self):
       return self.type


class SectionInline(JSONPluginInline):
   color = "#1aa4c5"


DidYouKnowBox = Section.proxy(
   "did_you_know",
   verbose_name=_("did you know box"),
   schema={
       "type": "object",
       "properties": {
           "title": {"type": "string", "title": _("title")},
       },
   },
)
KeepInMindStrategiesBox = Section.proxy(
   "keep_in_mind",
   verbose_name=_("keep in mind / strategies box"),
   schema={
       "type": "object",
       "properties": {
           "title": {"type": "string", "title": _("title")},
       },
   },
)

And then customize the renderer to automatically add plugins to those sections.

I want to clean up the code and add section nesting to the CMS for those more advanced use cases.

@benzkji
Copy link
Author

benzkji commented Aug 6, 2024

Thank you @matthiask !

With the first solution, I could add one gallery per region, as all images and videos would be rendered in there, is that correct? And the visual appearance would not be correct, in the admin, as images and videos would be on the same level as the gallery plugin?

I don't really understand the second example. But if you say "I want to clean up the code and add section nesting to the CMS for those more advanced use cases", does it mean a real tree (with django-tree-inline ;), or something different?

IMHO, hierarchical plugins would be a benefit for this library. It' way more simple (from my developer view), quite a few workarounds would be obsolete, and you just know that you can have hierarchical plugins if you need, or not, if you don't. But yea, it would add complexity.

@benzkji
Copy link
Author

benzkji commented Aug 6, 2024

ah, just now realized the gallery = plugins.popleft(). Thanks again for the insights.

@matthiask
Copy link
Member

I don't really understand the second example. But if you say "I want to clean up the code and add section nesting to the CMS for those more advanced use cases", does it mean a real tree (with django-tree-inline ;), or something different?

It wouldn't be a "real" tree in the sense of django-tree-queries or something, but would still be a tree with nodes and leaves and everything.

IMHO, hierarchical plugins would be a benefit for this library. It' way more simple (from my developer view), quite a few workarounds would be obsolete, and you just know that you can have hierarchical plugins if you need, or not, if you don't. But yea, it would add complexity.

Yeah, that's the thing. It's always a trade off. The main benefit of using django-content-editor is that you have very little additional code -- almost everything is handled by the Django admin interface's inlines/formsets. Once you leave that path you need much more code to handle all the new cases you get. So, it's either simple in the way how the data structure directly represents the tree or simple in the way how it's implemented. You cannot have both.

ah, just now realized the gallery = plugins.popleft(). Thanks again for the insights.

Yes, you just need to add a plugin with different marks in-between, or add the GalleryPlugin itself (since it doesn't have the gallery mark in my example!) to start another gallery.

@benzkji
Copy link
Author

benzkji commented Aug 6, 2024

It wouldn't be a "real" tree in the sense of django-tree-queries or something, but would still be a tree with nodes and leaves and everything.

yes, nodes and leaves, no need for left, right and other such things ;) is this feature in the development pipeline, or is it more of a nice to have, for you?

@matthiask
Copy link
Member

I'm not 100% certain it will happen but it's definitely something I want to do. Automatic grouping of plugins is nice, but a more explicit way to present it would be better.

@gradel
Copy link
Contributor

gradel commented Aug 6, 2024

In cases like that I tend to use a normal model of its own e.g. Gallery, which may be a PluginBase or not depending on it having mixed content. And for the Page a GalleryPlugin, which is just a foreign key to Gallery. So editing is two steps: editing a gallery and adding it to the page via the GalleryPlugin. Bonus: you can add the plugin multiple times if needed and when you have say hundreds of images in one gallery sorting them may be easier in its own model.

@matthiask
Copy link
Member

Yes, I like that approach as well!

@benzkji
Copy link
Author

benzkji commented Aug 6, 2024

@gradel yep, know this, that's my default with forms.

@matthiask
Copy link
Member

By the way, nested sections are now possible: https://406.ch/writing/django-content-editor-now-supports-nested-sections/

@gradel
Copy link
Contributor

gradel commented Oct 16, 2024

Played around and built an accordion app with "chained" foreign keys to mimic a plugin tree.
https://github.com/gradel/feincms3-accordion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants