Supercharging Snippets (with revisions, drafts, workflows, etc.) #8609
Replies: 16 comments 27 replies
-
Might be worth flagging Snippets bulk actions are well underway also #8574 |
Beta Was this translation helpful? Give feedback.
-
@laymonage a bit nitpicky but maybe we should rename |
Beta Was this translation helpful? Give feedback.
-
I have multiple questions on this work from a maintenance standpoint:
|
Beta Was this translation helpful? Give feedback.
-
Just wanted to say how wonderful it is to see some movement toward consistency here. I feel like this whole thing has been approached really sensibly. Wonderful work guys! One thing I feel might have been missed though: Believe me when I say: experienced Django devs are still 'converting' to Wagtail and taking care of business without support. They just want a clear migration path - and when you give them that, they'll thank you for it.
If Wagtail has clear answers to these questions, there's no need for |
Beta Was this translation helpful? Give feedback.
-
Are customisable snippet icons on the menu as well? (#4095, #4040). This feels like a worthwhile consideration to me as part of architectural changes, as icons are yet another bit of metadata which would ideally only be defined once per model and then propagated to the menu items, listing views, chooser widgets, etc. |
Beta Was this translation helpful? Give feedback.
-
Are stages 1 to 4 gonna make it to Wagtail 4? I'm trying out the 4.0rc2 but I don't see any of these features for Snippets? |
Beta Was this translation helpful? Give feedback.
-
We are currently looking into using non-page models more in our Wagtail, which brings me here. I would have some feedback on this discussion as well:
Maybe Snippets should be a "variant" of ModelAdmins, meaning being based on them and offering a quick and easy way to setup a opinionated ModelAdmin, but leaving the ModelAdmin escape hatch for a more low level approach. Basically having I would really appreciate if somebody could help me understand the difference here. Best regards, |
Beta Was this translation helpful? Give feedback.
-
Thought I’d get back to this discussion to ask whether there has been any discussions of snippets’ support in rich text? This strikes me as a natural fit for this project, as it currently takes a lot of work to implement any kind of "inline text with associated data". A generic snippet-focused API would be an excellent way to make this possible with higher-level, "server-side only no need to touch JS" APIs. And I don’t think it would necessarily be that much work, since we already have choosers for snippets – we’d just need to know which field(s) of the snippet to store in the rich text (id or otherwise) so the annotation is associated with the correct model instance, and which field(s) to use when displaying any kind of preview / "thumbnail"-type information which we might want to have access to outside the chooser (for example in the rich text tooltip). |
Beta Was this translation helpful? Give feedback.
-
I like where snippets are headed. Our team wanted workflow and revisioning for our re-usable content, so we setup a 'Reference' site with pages for all of our re-usable content. We considered snippets but they didn't meet our editorial needs. More full featured snippets might have changed our decision. Will there be advantages to using snippets in the future vs our approach of creating out of tree pages? It sounds like snippets, once all these features are added, will be fairly indistinguishable from pages. |
Beta Was this translation helpful? Give feedback.
-
Hi everyone, thanks for showing your interest in this discussion! Sorry I haven't been able to reply and answer your questions. In the past few months, we've been hard at work making workflows and locking available for snippets. The feature has been merged and will be included in Wagtail 4.2. For more details, see: Now that we've covered all the big features, I think the next thing we should focus on is to fill in the gaps: polishing the UX, clearing up tech debts, making snippets up to par with ModelAdmin, etc., then finally deprecating ModelAdmin. ModelAdmin parityThis involves making the
Tech debt
Miscellaneous
Edit: I've updated the main post to reflect the current status and include this update. |
Beta Was this translation helpful? Give feedback.
-
FormPage listing & form responses as snippetsI'd like to suggest that snippets be used under the hood to power the form responses (and maybe even form page listing) interaction. This would be a good use case for ensuring that Snippets and ViewSets can support many of the features the ModelAdmin can already support. It will also massively enhance the capabilities of form and form response management. I'm not sure if reports are a better way to integrate form submission listings though. Just an idea. |
Beta Was this translation helpful? Give feedback.
-
Settings as Snippets / Singleton SnippetsI would like to suggest that we explore the concept of a singleton (single instance) Snippet, one that is never shown as a listing but only ever has one 'truth' instance. If we had this, we could potentially implement it for the underlying approach of Setting models maybe. |
Beta Was this translation helpful? Give feedback.
-
Some thoughts on icons, views, and menu customisations: #4095 (comment) |
Beta Was this translation helpful? Give feedback.
-
@laymonage how do you feel about rebuilding modeladmin as a part of the core app, where it essentially becomes a 'convenient customisation layer' on top of the snippet views? |
Beta Was this translation helpful? Give feedback.
-
Preview / inspect snippets viewAs noted above, ModelAdmin has a great feature called inspect, basically a read only view for a model instance. I think porting this to Snippets would be expected, but maybe a different approach (or parallel feature) could be a standalone preview view. There already is the ability to Preview snippets and maybe this could be adapted to a single view and available to users without edit access to the snippets. |
Beta Was this translation helpful? Give feedback.
-
I wasn't sure where to put this question, since the parity-discussion #10206 is locked, so I hope it's ok here: @laymonage Are there any plans to actually get rid of the "Snippets" term and/or this extra level (e.g. in the URL, breadcrumbs,...)? We've actually never used snippets before, we've only used the ModelAdmin, since this extra level of "Snippets" (and the term itself) created much confusion in the beginning ("Everything is basically a model, why are pages, images, documents, forms,... in the root or in custom submenus, and some other models below 'Snippets'"?). Since this has been improved a lot by your amazing work, we are now trying to migrate everything (new) to the But even with Currently, we use the following tweaks for our
So I'm thinking of making the snippet-less configuration the default, but still allow to switch to the old setup (for a deprecation period vs. just keep the option). |
Beta Was this translation helpful? Give feedback.
-
Hey folks! 👋
As some of you may have seen in our latest What's New in Wagtail event, we are planning to "supercharge" the snippets feature in Wagtail.
This work is too broad to be an RFC, but we feel that we still need to give you a better idea on how we're going to do it. Thus, this post outlines the high-level overview of the work involved. Please note that we're still figuring things out as we go along, so things may be added, changed, or removed. RFCs will be created for certain implementation details that will be required for this project.
Background
As a CMS, Wagtail has plenty of useful features in its Page editor. However, a content management system manages content, not just pages. A page often consists of smaller bits of information (content) that can be managed individually and reused in other pages or inner mechanisms of the site. Since Wagtail is built on Django, you can use Django models to store such content in your database and use them in your pages. In addition, Wagtail also allows you to manage Django models in the Wagtail admin.
We currently have two ways of editing Django models in the Wagtail Admin, that is through Snippets and ModelAdmin.
Snippets
@register_snippet
decorator to your models and they will show up under the Snippets menu.ModelAdmin
ModelAdmin
, define the display, filters, and search fields, then callmodeladmin_register()
.django-filter
andwagtail.search
) but ModelAdmin is incompatible with Wagtail’s approaches.Having two completely separate implementations like this makes it more difficult for us to implement new features that work with both implementations (for example, wagtail-localize doesn’t support ModelAdmin). It can also be confusing for new users ("which one to use?").
Proposed solution
We want to have a single, "definitive", way to manage Django models in Wagtail Admin. To achieve this, we will start by refactoring and improving Snippets to reuse as much code in Wagtail as possible, by extending from Wagtail's generic admin views. Then, we will bring new features by implementing them in the generic admin views. With this approach, the new features can be used by any Django model and they are not tied to the concept of "Snippets". In the future, we might even stop using the "Snippets" terminology and treat them as regular Django models to reduce the gap when people come from Django to Wagtail.
Stages
We have broken down the work into stages, each of them is described below. Note that these stages aren't set in stone. We may add, change, or remove any of the stages as we continue with the work and find new challenges and rooms for improvements.
Stage "X" means that the stage can be done at any time, it can be pushed out (or pulled in if the prerequisites have been fulfilled), and it does not block the subsequent stages.
Stage 0: Make snippets views extend from generic views ✅
As of Wagtail 3.0, the Snippets views are a mix of class-based views (CBV) and function-based views (FBV). In this stage, we will refactor the views into CBVs and make them extend Wagtail’s generic admin views. This is done in:
Stage 1: Move snippets features into generic views ✅
Once the Snippets views extend from the generic views, we will lift parts of the Snippets views that contain generic features (e.g. locale, search, panels support) to the generic views. Thus, the Snippets views will only contain Snippets-specific customisation without the implementation details for those features. This is done in:
Stage 2: Wrap Snippet views into a
ViewSet
✅Currently, all registered snippet models must use the same CRUD and chooser views.
In this stage, we will update
@register_snippet
to instead generate and register aViewSet
for each snippet. This would allow the snippet views to be customised for individual snippet models. This is done in:Stage 3: Add revisions to Snippets ✅
In this stage, revisions will be available for Snippets. The History view for Snippets will allow the user to revert back to a previous revision and compare differences between revisions. This is done by refactoring the
PageRevision
model into a genericRevision
model and extractingsave_revision()
(and other revision-related methods and properties) fromPage
into aRevisionMixin
. Then, we'll update the generic views to callsave_revision()
every time an instance of a model that extends fromRevisionMixin
is created or edited. To do this, we'll need to:PageRevision
with genericRevision
model #8441Page.save_revision()
was given a specific page object #8573GenericForeignKey
andGenericRelation
forRevision
#8571Page
intoRevisionMixin
#8482RevisionMixin
#8495RevisionsCompareView
and add the ability to compare revisions for snippets #8531Screenshots
Stage 3.1: Implement new Page Editor UI on Snippets ✅
The draft state for Snippets will require some UI rework to the Snippets views to show the published/draft status and the scheduled publishing feature. To do this, we will copy across the new header info (including breadcrumbs, see #8472) and side panels from the new Page Editor so that we can display the status of the Snippet in the same way it’s displayed on Pages. This is done in:
Screenshots
Stage 4: Add Draft state to Snippets ✅
This includes the ability to save a draft of a Snippet and publish it, but not any moderation. We want Snippet draft/publishing/unpublishing to work in a similar fashion to Pages, so that:
We will create a
DraftStateMixin
for models. This mixin can only be applied if theRevisionMixin
is applied - so that any time you use theDraftStateMixin
you must have revisions enabled, but you can still use revisions on their own without having to use drafts. To ensure theDraftStateMixin
is never applied without theRevisionMixin
, we’ll perform a system check in theDraftStateMixin
. This is done in:Page
toDraftStateMixin
#8612The
DraftStateMixin
will include a way to show if the model is live (extracted from pages). We will also update the action buttons to add in a Publish button alongside Save, which publishes the Snippet. The basic version is done in:DraftStateMixin
#8624In addition, we still have to figure out what it means for a Snippet to be in a "draft" state. See the discussion in #8599 for more details.
Stage 4.1: Use
latest_revision
fromRevisionMixin
to find the draft title and updated date ✅The
Page
model has (denormalised)draft_title
andlatest_revision_created_at
fields to optimise the performance of the listing views by avoiding too many table joins on the database. Rather than adding these fields to every snippet, we’d like to add them to the revisions themselves, so we can get it from the latest/first revision instead. So that we know which is the latest revision, we’ll introduce alatest_revision
field to theRevisionMixin
. After this is done, we should also refactorPage
to use thislatest_revision
field instead of thedraft_title
andlatest_revision_created_at
fields.Stage X: Improve Snippets listing view and filters ✅
We want the listing of Snippets to be customisable, so that more metadata can be shown to help users find the right Snippet.
In order to do this, we will need to update the Snippet listing for all Snippets, regardless of them having the
DraftStateMixin
applied or not.Snippets listing differs from page listing as Snippets don’t have a common
title
field (though they do share some common metadata). The default listing view will show the following columns:For snippets that have the
RevisionMixin
, the name field will be thelatest_revision
'stitle
(which is thestr()
of the instance at the time thelatest_revision
is created). For basic snippets, this column will be populated by thestr()
representation of the snippet.RevisionMixin
we will show when the last revision was created.This will show the number of pages/model instances that reference the snippet. This will need the work outlined in Draft state for snippets and quickly and accurately finding an object's usage #8496.
This will show the "Live" and "Draft" status when the
DraftStateMixin
is applied.This is done in:
ReportView
to genericIndexView
#8851We will also add ordering and basic filters to the default listing view where they make sense.
Developers will be able to customise the display, order, and filter fields by overriding the
ViewSet
. We'll probably also add the possibility to register snippets under a different menu using theViewSet
. This will be documented later.Stage 5: Add Previews to Snippets ✅
In this stage we’ll change Previews so they are managed as a mixin independently of pages. Pages will use the Preview mixin, just as any other model will be able to.
To achieve this we will move these methods and attributes out of
Page
into a new mixin (e.g.PreviewableMixin
) so they can be generally used by other model types. The mixin will be added to the base class of the page, so all pages will still have previews and they still work the same way. This is done in:PreviewableMixin
fromPage
model #8709When the mixin is added to a Snippet, we will display a Preview button (as per pages). To add a preview to a model, the developers will add the mixin to their (snippet) model class, and define a template using a
preview_template
attribute.To add multiple preview modes to a model, the developer will override
get_preview_template
,get_preview_context
, and/orserve_preview
and provide separate templates for each mode, in the same way they currently do for Pages.This is implemented in:
PreviewableMixin
#8808We will need to update developer docs to show how this works, and some advice on how to use previews with non page models (e.g. Snippets).
Everything below this line is unlikely to make it into Wagtail 4.0, and instead will be part of the subsequent release(s).
Stage X: Snippet usage ✅
In order to unpublish and delete a Snippet, that Snippet should not be used anywhere on the site. To do this we will need to introduce a listing of where the Snippet is being used, which will mean creating a new usage index.
We can discuss the technical details for this in:
Stage 6: Introduce workflows for Snippets ✅
LockableMixin
is applied #9735 and Add the ability to lock snippets that extendLockableMixin
#9763.Next steps
ModelAdmin parity
This involves making the
SnippetViewSet
easier to configure, to act as the replacement of theModelAdmin
classes.For further discussion, head over to:
Tech debt
CreateEditOptionalFeaturesMixin
Miscellaneous
SnippetViewSet
sSnippetViewSet
. This is necessary as we need a single "canonical" viewset for linking stuff between features (e.g. link to the edit view from the dashboard of snippets that are in a workflow).ModelViewSet
instead?SnippetViewSet
and overrideget_urlpatterns()
... I suppose there should be an easier way to register the urls to the sidebar menu, though.Out of scope for now
cached_paths
)Thanks for reading, please let us know what you think about this!
Also check out previous/related discussions on specific parts of this project:
Last updated: 2023-01-24 16:40 GMT
Beta Was this translation helpful? Give feedback.
All reactions