Giter VIP home page Giter VIP logo

cmsplugin-sections's Introduction

cmsplugin-sections

This is a plugin "system" (really just two) for making "single-page scroller" websites super easy.

It provides a Section Container plugin and a generic Section plugin out of the box. Section Containers allow Section plugins to be added inside them. Section plugins will allow anything inside them, but have some basic configuration of their own, namely:

  1. Title - The title of the section;

  2. Show title - If unchecked, will not emit a heading for the section;

  3. Label - A menu title for the section. This is by default identical to the title, but allows for a menu label different than the section title;

  4. Show in menu - If unchecked, this section will not appear in the menu.

  5. Slug - a slug. If left blank, will be derived from the title.

The Section Container will render all of its children plugins, but first, it will emit basic menu markup of the contained sections.

Now your operators can move sections around, and the in-page menu will stay up to date.

For your section-linking convenience, each Section plugin will also emit links to the previous and next sections, if present.

You will need to provide some CSS styling and possibly some JS for nice, smooth, intra-page link scrolling. I use something like this in my projects that use jQuery:

(function($){
  $(function(){
    //
    // Provide graceful scrolling around the page
    //
    $("nav.page").on('click', 'a', function(evt) {
      var $this = $(this),
          target = $this.attr('href');

      if (target[0] === '#') {
        evt.preventDefault();
        $('html,body').stop().animate({
          'scrollTop': $(target).offset().top
        }, 800, 'swing');
      }
    });
  });
}(window.jQuery));

INSTALLATION

pip install cmsplugin-sections

Then, add 'cmsplugin_sections' to your INSTALLED_APPS.

If using Django 1.7, then add:

'cmsplugin_sections': 'cmsplugin_sections.migrations_django'

to settings.MIGRATION_MODULES

NORMAL USAGE

  1. Add a Section Container plugin to the page;
  2. Add one or more Section plugins into the Section Container;
  3. Add content to each Section plugin as per usual;
  4. Style with CSS to suite your needs;
  5. Optionally add the above JS to your project to provide smooth scrolling between sections;
  6. Optionally override or extend the provided templates to further suite your needs.

ADVANCED USAGE

In most cases, you could easily just create normal CMS Plugins which can then be added to a Section plugin to get the variety of content you wish your operators to choose from. However, there may be some cases where it makes sense to just create a custom Section plugin.

Both the Section Container and the Section plugin were built in a manner that provides easy extention via subclassing a "base" plugin and a "base" plugin model. This makes it pretty straightforward to create your own, pluggable sections types for your operators.

If you plan to create your own, custom Sections for your project, your models.py might looks something like this:

from django.db import models
from cmsplugin_sections.models import AbstractSectionBasePluginModel

class SplashSectionPluginModel(AbstractSectionBasePluginModel):
	#
    # Include project-specific Section Plugin configuration here. Or not. See
	# note below.
	#
    pass

NOTE:

If is entirely optional to create your own pluginmodel if you don't need
to add configuration options. You *could* just use the provided one, but,
if you ever change your mind, it will be rather complicated to migrate any
existing Section plugins to your new model. If instead you create an
intermediate base class like the one shown above, even if its body is
simply: `pass`, you will thank yourself in the future when you decide to
add a configuration parameter to any existing sections of this type.

Your cms_plugins.py might look like this:

from cmsplugin_sections.cms_plugins import BaseSectionPlugin
# Assumes models.py and cms_plugins.py are at the same level in your project.
from .models import SplashSectionPluginModel

class SplashSectionPlugin(BaseSectionPlugin):

	# Many of these options are configurable. See source for hints.
    cache = True
    model = SplashSectionPluginModel
    name = 'Splash Section'
    render_template = "YOUR_APP/splash_section.html"

	def render_plugin(self, context, instance, placeholder):
		# Do your own thing here ...
		return context

plugin_pool.register_plugin(SplashSectionPlugin)

cmsplugin-sections's People

Contributors

mkoistinen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

cmsplugin-sections's Issues

Error when adding sections container

Hi,
And thanks for what seems to be a very useful plugin.

I get a 'NoneType' object is not iterable type error when trying to add a section container:

Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/en/?edit

Django Version: 1.8.9
Python Version: 2.7.9
Installed Applications:
('djangocms_admin_style',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.admin',
'django.contrib.sites',
'django.contrib.sitemaps',
'django.contrib.staticfiles',
'django.contrib.messages',
'cms',
'menus',
'sekizai',
'treebeard',
'djangocms_text_ckeditor',
'djangocms_style',
'djangocms_column',
'djangocms_file',
'djangocms_googlemap',
'djangocms_inherit',
'djangocms_link',
'djangocms_picture',
'djangocms_teaser',
'djangocms_video',
'reversion',
'grounded_change',
'cmsplugin_sections')
Installed Middleware:
('cms.middleware.utils.ApphookReloadMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'cms.middleware.user.CurrentUserMiddleware',
'cms.middleware.page.CurrentPageMiddleware',
'cms.middleware.toolbar.ToolbarMiddleware',
'cms.middleware.language.LanguageCookieMiddleware')

Template error:
In template /Users/.../templates/fullwidth.html, error at line 7
'NoneType' object is not iterable

1 : {% extends "base.html" %}

2 : {% load cms_tags %}

3 :

4 : {% block title %}{% page_attribute "page_title" %}{% endblock title %}

5 :

6 : {% block content %}

7 : {% placeholder "content" %}

8 : {% endblock content %}

9 :

Traceback:
File "/Users/.../lib/python2.7/site-packages/django/core/handlers/base.py" in get_response

  1.             response = response.render()
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/response.py" in render
  2.         self.content = self.rendered_content
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/response.py" in rendered_content
  3.     content = template.render(context, self._request)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/backends/django.py" in render
  4.     return self.template.render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in render
  5.                 return self._render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in _render
  6.     return self.nodelist.render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in render
  7.             bit = self.render_node(node, context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/debug.py" in render_node
  8.         return node.render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  9.     return compiled_parent._render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in _render
  10.     return self.nodelist.render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in render
  11.             bit = self.render_node(node, context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/debug.py" in render_node
  12.         return node.render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/classytags/core.py" in render
  13.     return self.render_tag(context, **kwargs)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/sekizai/templatetags/sekizai_tags.py" in render_tag
  14.     rendered_contents = nodelist.render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in render
  15.             bit = self.render_node(node, context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/debug.py" in render_node
  16.         return node.render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/classytags/core.py" in render
  17.     return self.render_tag(context, **kwargs)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/cms/templatetags/cms_tags.py" in render_tag
  18.     rendered_contents = nodelist.render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in render
  19.             bit = self.render_node(node, context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/debug.py" in render_node
  20.         return node.render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  21.             result = block.nodelist.render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in render
  22.             bit = self.render_node(node, context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/django/template/debug.py" in render_node
  23.         return node.render(context)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/classytags/core.py" in render
  24.     return self.render_tag(context, **kwargs)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/cms/templatetags/cms_tags.py" in render_tag
  25.         content = get_placeholder_content(context, request, page, name, inherit, nodelist)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/cms/templatetags/cms_tags.py" in get_placeholder_content
  26.     content = render_placeholder(placeholder, context, name)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/cms/plugin_rendering.py" in render_placeholder
  27. content.extend(render_plugins(plugins, context, placeholder, processors))
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/cms/plugin_rendering.py" in render_plugins
  28.     out.append(plugin.render_plugin(context, placeholder, processors=processors))
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/cms/models/pluginmodel.py" in render_plugin
  29.         context = plugin.render(context, instance, placeholder_slot)
    
    File "/Users/.../.virtualenvs/gc/lib/python2.7/site-packages/cmsplugin_sections/cms_plugins.py" in render
  30.     for child in instance.child_plugin_instances:
    

Exception Type: TypeError at /en/
Exception Value: 'NoneType' object is not iterable

Slugs should only be unique per page

Hey, I have a multilingual site, and there are some menu items that have the same name, and thus the same slug. Since these are fragments I think it really only makes sense for them to be unique on the same page.

Although, I ask myself if I really need to enforce that. I feel inclined to let it be. You would need two sections with the same name for them to conflict, which is unlikely. Even then, you could just edit the slug and choose another name.

Change suggestions

Hey, I'm doing a set of changes to this plugin. I can extend your base classes in my own app or I can PR some of these to you:

  • Internationalize app (gettext);
  • Add setting to section container to include prev/next links;
  • Add setting to section container to include menu;
  • Add plugin that renders menu (allows placing menu in separate placeholder independently);
  • Break section-container.html into partials to override less;
  • Provide to template all sections, not just the ones in menu (otherwise sections.0.section_menu_slug may not work as expected);
  • Better default HTML5 tags (i.e., <main> instead of <div> for main content and <article> instead of <section> for section content?

What do you think?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.