Creating new content types
Introduction
This page is for the programmers, more specifically you need to know how to program in Python. If you don't know about Python it is good to hear that it is a powerful programming language that is rather easy to learn. There are plenty of sources about learning Python, books as well as online resources.
Here I will cover the basics of what you need to know to be successful in writing a new content type. You can also browse the source code in 'alive_cms_project/alive_cms/lib' directory to see how the content types are done that come with Alive CMS.
A new content type consists of a class that lives in your application's modules folder. The system will import it automagically, it does a "from .... import *" for every Python file in the modules directory, so it is a good idea to use an '__all__ = ["YourClass"]' line so only "YourClass" is imported.
A resource is uniquely defined by it's URL (path). Meta data of an
object (resource) is store with the path as the key. An object can also have content data, stored in a record which id is stored in the meta data. Finally you can create many records/data objects without their own
meta data (and only accessable via the object's data attribute), see below. Note
that any type of resource can live
at any path. I'm planning on implementing copy and paste for objects, when that is in place you can effectively move objects to any place after their creation.
Base class and required methods
There are a few requirements to get a content type that actually does something:
- Your content type should inherit from Obj, otherwise you have to implement a lot of stuff that Obj provides
- You need to override the 'view_item()' method, the view_item() method of Obj doesn't do anything, it's just a placeholder. And if your content type needs editing capablities you also need an 'edit_item()' method. Both view_item() and edit_item() are always public, i.e. exposed to the web and part of the url. Remember if there is no method in the url, the view_item is used
- Your public methods, like the view_item() method needs to return either the actual content (like HTML or image data) to the browser or return a dictionary. The keys of the dictionary must correspond to variables used in the template used for this content type, or variables used in the layout template
- If a public method like the view_item() method of your content type returns a dictionary (the normal case) then you also need a template with that name, so 'view_item.html' for the view_item() method. If you don't provide a template the system will try a generic view_item.html that expects 'content' as a dictionary key. Note that you can use another template name but then you have to put some extra code in the method that sets the 'tmpl' key in the skin dict.
- As described under the "Make new skins" section, the content type template lives in the 'content_types' folder of the skin (so you probably need a new skin as well since the default_skin is linked) in a sub directory with the name of your content type. That name is the same as your class name but all lower case
See the Hello world code example for some code and hopefully the comments in the code clarify the description above. You can put the code of the example in a site's modules folder and then you should have a content type you can add from the 'folder content' view.
Getting a little more advanced
The stuff above is kind of the bare minimum, let's talk about how to do more features:
- If you set a class attribute 'allowed_methods' to a list of methods (other then view_item and edit_item), then these methods become public accessable, i.e. accessable through the web
- To make your content type behave like a container (i.e. it can contain other objects), you set the class attribute 'is_container' to a True value
- You can restrict the adding of you content type with the class attribute 'type_resticted', a list of roles that have the permission to add your content type
- You can control the type of the parent with 'content_type_parent', a list of content types that are allowed to be the parent of this content type
- If you content type is a container (is_container = 1), then one other class attribute make sense, 'content_type_children', a list of content types that are allowed to be children of this content type
- The class attribute 'data_spec' is used to make permanent storage for your content type. So "data_spec = {'content': 'Hello World'}" will make one storage field with the default value of 'Hello World'. The storage field is acessed as self.data.content or as self.data['content']. When the instance is created the data is already loaded. Saving data after a change goes with self.save_data()
- The class attribute 'extra_data_spec' is used to make many storage records for
your content type. To add records use the 'add_data_item()' functon, which return a record id. As a programmer you need to keep track of this id in order to access that data later, for instance by storing the id in self.data
See the Hello foo code example. It shows very simple storage. Put the code in a site's modules folder and play.