We have 4 top level content classes user work with:
When the user creates a Norm (respectively Paper, or german “Papier”) through the web interface, he is internally creating a Page with the page.Page.function set to page.Page.NORM. The text of the page is saved in Text objects in page.Page.texts, that may have different variants.
Page is a subclass of delegateable.Delegateable.
The actual text of the proposal is saved as a Page object with the Page.function page.Page.DESCRIPTIION in an attribute page.Page.description.
In a Page a user can propose changes to a Page (Norm). These are saved as selection.Selection objects (see below).
Proposal is a subclass of delegateable.Delegateable.
Some of the more interesting models and support classes are:
Almost all model classes have a classmethod .create() to create a new instance of the model and setup the necessary data or relationships. Furthermore methods like .find() and .all() as convenient query method that support limiting the query to the current model.instance.Instance or in-/exclude deleted model instances.
To update the diagramms install graphviz and easy_install sqlalchemy_schemadisplay into the environment adhocracy is installed in. Then run python /adhocracy/scripts/generate-db-diagrams.py. It will create the diagrams as GIF files. Finally replace the GIF files in adhocracy/docs/development with the new versions.
A user can delegate his vote to another user for comment.Comment, proposal.Proposal and page.Page. This functionality is enabled by inheriting from Delegateable
Inheritance is done with sqlalchemy’s joint table inheritance where the delegateable table is polymorphic on delegateable.Delegateable.type
The model class page.Page has 2 uses in adhocracy that are differentiated by the value of page.Page.function.
Pages are delegateable and inherit from delegateable.Delegateable.
The text of the Page is not saved in the page table but created as a text.Text object. A page can contain different variants of the text, and for each variant an arbitrary number of versions, e.g.:
Text variants are used for Norms. For the initial text, variant is set to text.Text.HEAD. This text variant is handled special in the UI and labeled Status Quo in Norms. Other variants can be freely named. All text variants are listed in Page.variants.
Each variant can have a arbitrary number of versions. The newest version of the text is called the head (not to confuse with the default text variant Text.HEAD). You can get the newest version of a specific variant with Page.variant_head(). The newest versions of all variants is available as Page.heads. A shortcut to obtain the newest version of the HEAD variant is Page.head.
Text variants are not used for pages that are used as the description of proposal.Proposal objects (proposal.Proposal.description).
The poll tally of a variant or all variant can be optained with Page.variant_tally() or Page.variant_tallies()
Polls are set up per variant, not for the Page object.
Page objects (that have the funciton Norm) can be organized in a tree stucture by setting another Page (Norm) object as one of the Page.parents of the current page. Parents can be an arbitrary number of delegateable.Delegateable objects, but only one, not already deleted Page with the Page.function Page.NORM is allowed. Parents are taken into account when we compute a delegation graph.
The subpages of a page are available as Page.subpages.
Beside that Pages have functions and attributes to handle purging, deleting, renaming, Selections (Page (Norm) <-> Proposal relationships) and other things. See the api documentation for Page
Indexing and searching is done with sql(alchemy) and solr. Indexing with solr is done asyncronously most of the time while updates of the rdbm is done syncronously most of the time. The asyncronous indexing is done throug a rabbitmq job queue.
Beside rdbm intern indexes adhocracy maintains application specific indexes (that partly act as audit trails too):
adhocracy implements an sqlalchemy Mapperextension with hooks.HookExtension that provides hook method to sqlalchemy that will be called before and after insert, update and delete operations for every model instance that is part of a commit. To determinate what to do it will inspect the model instance for fitting hook methods.
The asyncronous system roughly works like this:
To have indexing and searching working propperly you need:
Read the install documentation for setup information.