72
HI! TIBERIU ICHIM 12+ years experience with Plone 2+ years experience with Kotti

Kotti CMS 101

Embed Size (px)

Citation preview

HI! TIBERIU ICHIM

12+ years experience with Plone2+ years experience with Kotti

KOTTI 101

A short introduction to the

Web Application FrameworkKotti

IN THIS PRESENTATIONWhat is Kotti?First impressionsOverview of featuresMajor alternativesAdvantages and drawbacksKotti in the future

WHAT IS KOTTI?

Started in 2011, at a Plone conferenceDevelopers with common history: PloneDeveloped in several sprintsAlready stable for many years

BSD licensed1.0.0 in January 2015current version: 1.2.0~9k downloads per monthstill small, butactive, healthy and welcoming community

fastlightflexiblewell tested

SCREENSHOTS

CODE SAMPLES

CREATING AN ADDON$ bin/pip install Kotti

$ bin/pcreate -s kotti kotti_myaddonAuthor name [John Doe]:Author email [[email protected]]:Github username [Kotti]:[… lot of output …]

$ cd kotti_myaddon$ ../bin/pserve development.ini

CUSTOM CONTENT TYPE

from kotti.resources import Contentfrom sqlalchemy import *

class Document(Content):

id = Column(Integer(), ForeignKey('contents.id'), primary_key=True)

body = Column(UnicodeText())

mime_type = Column(String(30))

type_info = Content.type_info.copy(name=u'Document', title=_(u'Document'), add_view=u'add_document', addable_to=[u'Document'])

THE NODE CLASSadjacency list pattern

parentchildren

single root node => node treedictionary protocol

DICTIONARY PROTOCOLfrom kotti.resources import Documentfrom kotti.resources import get_root

>>> root = get_root()>>> root['about']<Document 2 at /about>

>>> root['doc1'] = Document(title='Foo', description='foo', body='<p>some HTML</p>')

TRAVERSALroot['a'] = Document(title='A', description='Document A')root['a']['b'] = Document(title='B', description='Document B')root['a']['b']['c'] = Document(title='C', description='Document C')

JOINED TABLE INHERITANCE

class hierarchy is broken up among dependent tableseach model class has its own tablethat table only includes attributes local to that class

POLYMORPHIC QUERIES>>> from kotti.resources import get_root>>> from kotti.resources import Node

>>> root = get_root()>>> for c in root.children:... print(type(c))<class 'kotti.resources.Document'><class 'kotti.resources.File'>

>>> print Node.query.filter(Node.title == 'My Document').one()<Document 5 at /my-document>

VIEWSSIMPLEST VIEW ATTACHED TO A CONTENT TYPE

from pyramid.view import view_config

@view_config(name='view', context=Document, permission='view', renderer='kotti:templates/view/document.pt')def document_view(context, request): return {}

TEMPLATE<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml" metal:use-macro="api.macro('kotti:templates/view/master.pt')"> <article metal:fill-slot="content" class="document-view content"> <h1>${context.title}</h1> <p class="lead">${context.description}</p> <div tal:replace="api.render_template('kotti:templates/view/tags.pt')" /> <div class="body" tal:content="structure context.body | None"> </div> </article></html>

SCHEMA DEFINITION: FORM CREATION, VALIDATIONimport colanderimport deformfrom kotti.views.edit.content import ContentSchema

class DocumentSchema(ContentSchema): body = colander.SchemaNode( colander.String(), title=_(u'Body'), widget=deform.widget.RichTextWidget(), missing=u"")

ADD / EDIT FORMSfrom kotti.resources import Documentfrom kotti.views.form import AddFormViewfrom kotti.views.form import EditFormViewfrom pyramid.view import view_config

@view_config(name=Document.type_info.add_view, permission='add', renderer='kotti:templates/edit/node.pt')class DocumentAddForm(AddFormView): schema_factory = DocumentSchema add = Document item_type = _(u"Document")

@view_config(context=Document, name='edit', permission='edit', renderer='kotti:templates/edit/node.pt')class DocumentEditForm(EditFormView): schema_factory = DocumentSchema

CONFIGURATION[app:kotti]use = egg:kottisqlalchemy.url = sqlite:///%(here)s/Kotti.dbkotti.configurators = kotti_tinymce.kotti_configure kotti_youraddon.kotti_configure[filter:fanstatic]use = egg:fanstatic#fanstatic[pipeline:main]pipeline = fanstatic kotti[server:main]use = egg:waitress#mainhost = 127.0.0.1port = 5000

CHOICES MADE BY KOTTI

PYRAMID

probably the most advanced ORM for Pythondatabase agnostichas many nice, useful features

hybrid propertiesassociation proxiesordering list

transactions integrated to pyramid request lifecycle

BOOTSTRAPCSS

has all the components for modern UIsresponsivewell knowneasy to customize

COLANDER & DEFORM

COLANDER

define data schemavalidate & deserialize

HTML formsJSONXML

serialize Python structures tostringsmappingslists

DEFORM

render HTML forms from structures serialized by Colanderoutputs Bootstrap 3 forms (Deform 2)

REPOZE.WORKFLOW

a content workflow systemstates define

role / permission mappingtransitions define

from_stateto_staterequired_permission

guards

FILEDEPOT

storing and serving files in web applicationsmultiple backends

local filesystemS3GridFSroll your own

integrates with SQLAlchemyfiles are handled like a plain model attributetransaction aware

... and many others:

BleachBabelAlembicpy.testjQueryetc.

OVERVIEW OF FEATURESUser friendlyDeveloper friendly

USER FRIENDLY

BUILTIN CONTENT TYPES

DocumentFileImage

USER INTERFACE

create contentedit contentdeletechange statefolder contents view for batch operations

Obviously inspired by Plone

...

workflowssecurity: roles, permissions, groups, sharing tabuser managementmulti file uploadeditors can choose which view is used on any contentitem

BUILT FOR DEVELOPERSSimplicityTraversalEasy polymorphism

...

Transactionseasy configuration from .ini or python codeflexible user input sanitization

...

events systemflexible blob storagei18n interface

...

slots (like viewlets)inlining viewsmacrosoverride templates (like z3c.jbot)

...

95% coverage of python codescale data from single file to replicated clusterable to use countless other pyramid extensions

ALTERNATIVE TO...PloneDjangoSubstanceD

PLONE

fully featured CMSmany add-onsTTW developmentwell established, large community

many many featuresheavy on resourceshard to learn and understandover 300 packages

MANY COMPETING TECHNOLOGIES

For models and schemas:

CMFArchetypesDexterityzope.schema

...

Package infrastructure:

Zope2ZCAGrok

...

Presentation layer:

Diazobrowser viewsportal_view_customizationsportal_skins

...

Forms:

CMFFormControllerArchetypeszope.formlibz3c.formplone.autoform

KOTTI VS. PLONEPlone is source of inspirationmore similar to CMF in scopeno application server, only one global site

no local settingsno need for GenericSetupno need for most portal_* utilitiesnative SQL indexing, no need for portal_catalog

obviously no TTW development

DJANGOmany add-onslarge communitynot quite a CMSweird for Zope/Plone developer

SUBSTANCEDvery good pedigreesimilar features on the surfaceZODB vs SQLAlchemyhas undo, audit log

KOTTI, ON ITS OWNAdvantagesDrawbacks

ADVANTAGES

Best set of core libraries

pyramidsqlalchemydeform

Avoid burnout

smaller dev stacksmaller time in server startupsmaller time in testingno lengthy builds

Knowledge transfer

Easier to dive into Plone if you know Kotti

... but if you're already a Plone developer

Zope Page Templatesslots, like viewletsZCA & .zcmlmany concepts that are similar or reimplemented

DRAWBACKS

no undo or versioning, yetsmall number of Kotti extensions.smaller number of builtin featuresnot tweakable by editorsNo:

TTW content typescomposable layoutsportlet management

THE FUTUREwill always stay

“lean and mean in all of the right ways”

the core is stablepython 3 support (almost done)undo/versioning, using sqlalchemy-continuumREST api (partially) implementing JSONAPIsplit up some functionality from core

WHERE TO GO NEXTKotti documentation websitegithub.com/Kotti/kotti.git#[email protected] on IRC