wagtail / wagtail

A Django content management system focused on flexibility and user experience
https://wagtail.org
BSD 3-Clause "New" or "Revised" License
17.91k stars 3.78k forks source link

Add functionality for 'singleton snippets' (aka Settings) #368

Closed mx-moth closed 9 years ago

mx-moth commented 10 years ago

Sites often have user-editable content, like site title, tag line, contact details, etc. These should be accessible from the admin, should not be pages, and should only ever allow one instance of themselves (multiple site titles does not make sense!)

This sounds much like snippets, except for the single instance restriction, hence the 'singleton snippets'. Whether this is implemented using snippets is another matter entirely.

I can think of multiple ways this functionality could be implemented, each with their own pros and cons:

  1. Extend snippets to allow singletons. This area of the admin already exists, and can be used for this kind of 'global' content that is not tied to a page. However, snippets would have to be modified to have a 'singleton' option, as well as some (potentially confusing and inconsistent) UI changes to handle this.
  2. Add a new section to the admin for 'site-wide settings', or something of the sort. Allow models to register themselves to the settings section, much like snippets. The UI (and possibly some model options) would enforce the singleton aspect. Other wagtail plugins can then register themselves to this system as well.
  3. Other approaches?

Personally, I prefer approach number 2. If the devs think this is a worthy feature, and a consensus on how to implement can be reached, I will develop it.

tmsndrs commented 10 years ago

Could this section include the option to define the homepage in the CMS rather than in the django admin as well? Option two looks much better from a UX perspective.

davecranwell commented 10 years ago

@tmsndrs that is already being tackled by a Torchbox developer and is potentially quite different to this. Lets keep this about a general "Settings" system.

davecranwell commented 10 years ago

@timheap We've discussed this between ourselves before but haven't tackled it yet.

What you're proposing is the start, but the remit is quite wide ranging and complex. A truly extensible, convenient "settings" system must store settings defined by Wagtail itself, as well as those defined by the implementer. Additionally there are some settings that only a developer would understand (and only they should therefore access it) versus some that an Admin would need to change.

An example of such settings:

Generally though, we're acutely aware of the problem of storing configuration in the database. We've been bitten way too many times by Drupal on this front. We'd want to carefully consider how a site's settings might affect deployment. How do you deploy such-and-such from a staging server to production without also having to manually duplicate the N settings it depends on? Perhaps a concept of "defaults" that get used before database settings have been created? Perhaps the solution is that no settings that an admin wouldn't change, should be stored?

Back to your suggestions, personally I dislike the reuse of snippets here. Even use of the term seems to imply we're bolting functionality onto something that isn't essentially designed for the purpose. If we're making a settings system, I'd prefer that we call it that. It's certainly more marketable.

If you want to take this on, @timheap, I'd recommend you do so without making any decisions about it's position or appearance in the menu quite yet. That is shortly to change.

mx-moth commented 10 years ago

@davecranwell I agree that reusing the snippets functionality is a bad idea. The code and concepts behind the snippets however could be reused, or at least enough similarities between them could be thought up to be useful.

The system I am thinking about is much like the snippets:

class SitewideCopy(models.Model):
    site_title = models.CharField(max_length=255)
    tagline = models.CharField(max_length=255)
    contact_number = PhoneNumberField()

class SiteSettings(models.Model):
    site_header = models.ImageField(....)
    webmaster_email = models.EmailField(...)
    google_analytics_key = models.CharField(max_length=20)

register_setting(SitewideCopy)
register_setting(SiteSetting)

This would allow both Wagtail core, various Wagtail plugins, and the final site created to all use the settings system to register their own chunk of 'settings', defining whatever is needed, using exactly the same functionality.

I am not sure how you would handle migrating settings from staging to production. Hopefully, developers would use a sensible combination of defaults and South migrations to make upgrades sensible, but I am not sure how to make this easier.

As for permission based restrictions, the standard Django permission system could be used. Each model has a "app.change_model" permission that would work fine. Show the link to the setting or not based upon the users permission level.

If I was to develop this, I would just put a link in the side menu for now, much like every other app. I would hold off doing anything fancy until the mentioned change had happened.

gasman commented 10 years ago

Additionally there are some settings that only a developer would understand (and only they should therefore access it) versus some that an Admin would need to change.

Up to now it's been a guiding principle of Wagtail's design that developer-facing configuration should always be done in code - and I'll need a lot of convincing to change that :-) Can you give an example of a "setting that only a developer would understand" that is more appropriate to have in wagtail admin than in settings.py?

davecranwell commented 10 years ago

Actually I can't :P which is why I tacked on the suggestions that perhaps no settings that an admin shouldn't change, should be stored.

sixpearls commented 10 years ago

Like @gasman, I'm generally against mixing and matching the access between developers and admins.

One solution that would perhaps give @timheap what he needs without putting in the wagtail codebase is to extend the wagtailcore Site model. Then on a per project basis (or as a separate re-usable "settings" app), each developer can give whatever settings to the admin that is desired. By putting the settings in Site derived model, the settings should be accessible from anywhere. Templates should be able to access the site from the request variable (thanks to the site middleware) and developers should get access to the site through some of the Page methods/manager.

It would be more acceptable to me to add a get_site_model function to allow this type of override than to put a settings module like this in the codebase. Perhaps wagtailadmin's Site support could be dynamic and inspect the class from get_site_model and generate the appropriate fields.

@davecranwell Is the Site support publicly accessible anywhere?

kaedroho commented 10 years ago

Another solution could be to add those fields to the page at your site root (your homepage in most cases).

You can then access your settings in templates by doing {{ request.site.root_page.specific.<setting name> }}.

davecranwell commented 10 years ago

Very good point that i'd completely overlooked, @sixpearls: settings would absolutely have to be per-site, not per installation. Every one of the examples I provided above would change per site.

Site support is currently being worked on by @nimasmi, I think.

davecranwell commented 10 years ago

@kaedroho Are you suggesting that rather than any kind of abstract settings concept, we could just add content fields to the Page model of each site's homepage? That's certainly a short-term solution, but it's not enterprise. Large sites we've created with our previous CMS had hundreds of settings. Most wouldn't be needed with wagtail, but still. If @timheap is going to develop this as a proper feature of Wagtail it should be as awesome as the rest of it!

kaedroho commented 10 years ago

@davecranwell Nope, just throwing it out there as its a way of adding settings to sites now. I'd like a proper solution to be developed for this in the future though.

On 25 June 2014 16:34, Dave Cranwell notifications@github.com wrote:

@kaedroho https://github.com/kaedroho Are you suggesting that rather than any kind of abstract settings concept, we could just add content fields to the Page model of each site's homepage? That's certainly a short-term solution, but it's not enterprise. Large sites we've created with our previous CMS had hundreds of settings. Most wouldn't be needed with wagtail, but still. If @timheap https://github.com/timheap is going to develop this as a proper contribution to Wagtail it should be as awesome as the rest of it!

— Reply to this email directly or view it on GitHub https://github.com/torchbox/wagtail/issues/368#issuecomment-47118113.

tomdyson commented 10 years ago

Not sure about @davecranwell's non-pejorative use of 'enterprise' :)

@kaedroho's idea has the benefit of being something Wagtail developers can do right now, in a reasonably transparent way. We could certainly come up with a better UI, but like @gasman I'm anxious that we don't encourage developers to bung all their configuration into the database, where it's hidden from deployment tools.

davecranwell commented 10 years ago

Yeah definitely. It should be convenient but actively discouraging :P

sixpearls commented 10 years ago

Also, let the record show the snippet module has very confusing name. I've seen a number of people misunderstand the module upon first contact, myself included.

davecranwell commented 10 years ago

Duly noted :P

davecranwell commented 10 years ago

Discussion today has raised some issues.

We scoured an old, particularly large client's codebase for inspiration and found several key needs for settings:

Our chief concerns are:

We're going to plan this a little more with specific use-cases in mind.

mx-moth commented 10 years ago

Copied from https://github.com/torchbox/wagtail/pull/377#issuecomment-49109065, some possible settings we thought up over here:

mx-moth commented 10 years ago

Until an official solution is developed, I have packaged the settings module I created for #377 and uploaded it to PyPI: https://pypi.python.org/pypi/wagtailsettings/0.1.0

chrxr commented 9 years ago

In our weekly meeting we've agreed to reference @timheap's wagtailsettings module in our docs.

mx-moth commented 9 years ago

Haha, seeing that it is now officially endorsed or some such, I suppose I better polish it up!

I've just released 0.3.2, which fixes some issues in the README/docs, and adds tests. There are no functionality changes. Also note that as of version 0.3.0, wagtailsettings does not support Wagtail 0.8 or below, due to backwards incompatible changes in the internal Wagtail EditHandler API wagtailsettings uses.

The latest version can be found at https://pypi.python.org/pypi/wagtailsettings/

mx-moth commented 9 years ago

Also I am happy for this to be closed if you are not planning on adding a settings module to core. The wagtailsettings module covers all the functionality I wanted.

mx-moth commented 9 years ago

Closing in favour of wagtailsettings

denisvlr commented 8 years ago

wagtailsettings hasn't been maintained and doesn't work with Django 1.9. What is today the recommended solution to handle site-wide content such as a title, footer, etc?

To be very specific, i'm trying to build a fully configurable footer with multiple text fields, links, etc. A snippet looked like a nice solution, except it cannot be defined as a singleton.

gasman commented 8 years ago

Hi @denisvlr - wagtailsettings is now a contrib module within Wagtail itself: http://docs.wagtail.io/en/v1.6/reference/contrib/settings.html

(Please use the Wagtail support Google group for support queries)