# HG changeset patch # User Laure Bourgois # Date 1227631511 -3600 # Node ID d5acef862c588d58049c1c03cfcd7991bc86938c # Parent 3159772915c4764d84ed8b40bde923ad9b315c02# Parent 6d008838f2c9d48a8f1c1edec9ca2891638a9653 erge diff -r 3159772915c4 -r d5acef862c58 cwconfig.py --- a/cwconfig.py Tue Nov 25 17:44:54 2008 +0100 +++ b/cwconfig.py Tue Nov 25 17:45:11 2008 +0100 @@ -264,9 +264,9 @@ cube = CW_MIGRATION_MAP.get(cube, cube) try: return getattr(__import__('cubes.%s.__pkginfo__' % cube), cube).__pkginfo__ - except ImportError: + except Exception, ex: raise ConfigurationError('unable to find packaging information for ' - 'cube %s' % cube) + 'cube %s (%s: %s)' % (cube, ex.__class__.__name__, ex)) @classmethod def cube_version(cls, cube): diff -r 3159772915c4 -r d5acef862c58 debian/changelog --- a/debian/changelog Tue Nov 25 17:44:54 2008 +0100 +++ b/debian/changelog Tue Nov 25 17:45:11 2008 +0100 @@ -1,3 +1,9 @@ +cubicweb (2.99.2-1) DISTRIBUTION; urgency=low + + * new upstream release + + -- Adrien Di Mascio Mon, 17 Nov 2008 15:02:16 +0100 + cubicweb (2.99.1-1) DISTRIBUTION; urgency=low * new upstream release diff -r 3159772915c4 -r d5acef862c58 devtools/devctl.py --- a/devtools/devctl.py Tue Nov 25 17:44:54 2008 +0100 +++ b/devtools/devctl.py Tue Nov 25 17:45:11 2008 +0100 @@ -362,7 +362,7 @@ runserver() -class NewTemplateCommand(Command): +class NewCubeCommand(Command): """Create a new cube. @@ -371,6 +371,15 @@ name = 'newcube' arguments = '' + options = ( + ("verbose", + {'short': 'v', 'type' : 'yn', 'metavar': '', + 'default': 'n', + 'help': 'verbose mode: will ask all possible configuration questions', + } + ), + ) + def run(self, args): if len(args) != 1: @@ -378,6 +387,7 @@ cubename, = args if ServerConfiguration.mode != "dev": self.fail("you can only create new cubes in development mode") + verbose = self.get('verbose') cubedir = ServerConfiguration.CUBES_DIR if not isdir(cubedir): print "creating apps directory", cubedir @@ -389,19 +399,27 @@ if exists(cubedir): self.fail("%s already exists !" % (cubedir)) skeldir = join(BASEDIR, 'skeleton') - distname = raw_input('Debian name for your cube (just type enter to use the cube name): ').strip() - if not distname: + if verbose: + distname = raw_input('Debian name for your cube (just type enter to use the cube name): ').strip() + if not distname: + distname = 'cubicweb-%s' % cubename.lower() + elif not distname.startswith('cubicweb-'): + if confirm('do you mean cubicweb-%s ?' % distname): + distname = 'cubicweb-' + distname + else: distname = 'cubicweb-%s' % cubename.lower() - elif not distname.startswith('cubicweb-'): - if confirm('do you mean cubicweb-%s ?' % distname): - distname = 'cubicweb-' + distname - shortdesc = raw_input('Enter a short description for your cube: ') - longdesc = raw_input('Enter a long description (or nothing if you want to reuse the short one): ') - includes = self._ask_for_dependancies() - if len(includes) == 1: - dependancies = '%r,' % includes[0] + + longdesc = shortdesc = raw_input('Enter a short description for your cube: ') + if verbose: + longdesc = raw_input('Enter a long description (or nothing if you want to reuse the short one): ') + if verbose: + includes = self._ask_for_dependancies() + if len(includes) == 1: + dependancies = '%r,' % includes[0] + else: + dependancies = ', '.join(repr(cube) for cube in includes) else: - dependancies = ', '.join(repr(cube) for cube in includes) + dependancies = '' from mx.DateTime import now context = {'cubename' : cubename, 'distname' : distname, @@ -431,5 +449,5 @@ register_commands((UpdateCubicWebCatalogCommand, UpdateTemplateCatalogCommand, LiveServerCommand, - NewTemplateCommand, + NewCubeCommand, )) diff -r 3159772915c4 -r d5acef862c58 doc/book/en/01-00-introduction.en.txt --- a/doc/book/en/01-00-introduction.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -.. -*- coding: utf-8 -*- - -.. _Overview: - -Quick overview of `CubicWeb` -============================ - -`CubicWeb` allows us to develop web applications instances based on -one or more `cubes`. - -What we call a `cube` is a model defining the data types and views. -A `cube` is a reusable component grouped with others cubes in the file -system. - -An `instance` refers to a specific installation of one or more `cubes` - where are grouped configuration files of the final web application. - -In this document, we will show you how to create a `cube` and how to use it -in an `instance` for your web application. - -.. include:: 01-01-create-cube.en.txt -.. include:: 01-05-components.en.txt -.. include:: 01-06-maintemplate.en.txt -.. include:: 01-07-rss-xml.en.txt diff -r 3159772915c4 -r d5acef862c58 doc/book/en/01-01-create-cube.en.txt --- a/doc/book/en/01-01-create-cube.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,314 +0,0 @@ -.. -*- coding: utf-8 -*- - -Create your cube ----------------- - -After you installed your `CubicWeb` development environment, you can start -to build your first cube: :: - - cubicweb-ctl newcube blog - -This will create in ``/path/to/forest/cubes`` a directory containing: :: - - blog/ - | - |-- data/ - | |-- cubes.blog.css - | |-- cubes.blog.js - | |-- external_resources - | - |-- debian/ - | |-- changelog - | |-- compat - | |-- control - | |-- copyright - | |-- cubicweb-blog.prerm - | |-- rules - | - |-- entities.py - | - |-- i18n/ - | |-- en.po - | |-- fr.po - | - |-- __init__.py - | - |-- MANIFEST.in - | - |-- migration/ - | |-- postcreate.py - | |-- precreate.py - | - |-- __pkginfo__.py - | - |-- schema.py - | - |-- setup.py - | - |-- site_cubicweb.py - | - |-- sobjects.py - | - |-- test/ - | |-- data/ - | |-- bootstrap_cubes - | |-- pytestconf.py - | |-- realdb_test_blog.py - | |-- test_blog.py - | - |-- views.py - -Any changes applied to your data model should be done in this -directory. - - -Define your data schema ------------------------ - -The data model or schema is hte core of your `CubicWeb` application. -This is where is defined the type of content you application will handle. - -The data model is defined in the file ``schema.py`` of your cube -``blog`` such as follows. - -:: - - from cubicweb.schema import format_constraint - class Blog(EntityType): - title = String(maxsize=50, required=True) - description = String() - - class BlogEntry(EntityType): - title = String(required=True, fulltextindexed=True, maxsize=256) - publish_date = Date(default='TODAY') - content = String(required=True, fulltextindexed=True) - entry_of = SubjectRelation('Blog', cardinality='?*') - - -A Blog has a title and a description. The title is a string that is -required by the class EntityType and must be less than 50 characters. -The description is a string that is not constrained. - -A BlogEntry has a title, a publish_date and a content. The title is a -string that is required and must be less than 100 characters. The -publish_date is a Date with a default value of TODAY, meaning that -when a BlogEntry is created, its publish_date will be the current day -unless it is modified. The content is a string that will be indexed in -the full-text index and has no constraint. - -A BlogEntry also has a relationship ``entry_of`` that links it to a -Blog. The cardinality ``?*`` means that a BlogEntry can be part of -zero or one Blog (``?`` means `zero or one`) and that a Blog can -have any number of BlogEntry (``*`` means `any number including -zero`). For completeness, remember that ``+`` means `one or more`. - - -Create your instance --------------------- - -:: - - cubicweb-ctl create blog blogdemo - - -This command will create a directory ``~/etc/cubicweb.d/blogdemo`` -which will contain all the configuration files required to start -you web application. - -The instance ``blogdemo`` is based on the cube ``blog``. - - -Welcome in your web application -------------------------------- - -Run your application with the following command: :: - - cubicweb-ctl start -D blogdemo - - -You can now access to your web application to create blogs and post messages -by visitin the URL http://localhost:8080/. -A login form will first be prompted. By default, the application will not allow -anonymous user to get in the application. You should then use the admin -account you created at the time you initialized the database with -``cubicweb-ctl create``. - -.. image:: images/login-form.png - - -Once authenticated, you can start playing with your application -and create entities. Bravo! - -.. image:: images/blog-demo-first-page.png - -Please notice that so far, `CubicWeb` franework managed all aspects of -the web application based in the schema provided at first. - - -Create entities ---------------- - -We will now create a couple of entities in our web application. - -Create a Blog -~~~~~~~~~~~~~ - -Let us create a few of these entities. Click on the `[+]` at the right -of the link Blog. Call this new Blog ``Tech-blog`` and type in -``everything about technology`` as the description, then validate the -form by clicking on ``Validate``. - -.. image:: images/cbw-create-blog.en.png - :alt: from to create blog - -Click on the logo at top left to get back to the home page, then -follow the Blog link that will list for you all the existing Blog. -You should be seeing a list with a single item ``Tech-blog`` you -just created. - -.. image:: images/cbw-list-one-blog.en.png - :alt: displaying a list of a single blog - -Clicking on this item will get you to its detailed description except -that in this case, there is not much to display besides the name and -the phrase ``everything about technology``. - -Now get back to the home page by clicking on the top-left logo, then -create a new Blog called ``MyLife`` and get back to the home page -again to follow the Blog link for the second time. The list now -has two items. - -.. image:: images/cbw-list-two-blog.en.png - :alt: displaying a list of two blogs - -Create a BlogEntry -~~~~~~~~~~~~~~~~~~ - -Get back to the home page and click on [+] at the right of the link -BlogEntry. Call this new entry ``Hello World`` and type in some text -before clicking on ``Validate``. You added a new blog entry without -saying to what blog it belongs. There is a box on the left entitled -``actions``, click on the menu item ``modify``. You are back to the form -to edit the blog entry you just created, except that the form now has -another section with a combobox titled ``add relation``. Chose -``entry_of`` in this menu and a second combobox appears where you pick -``MyLife``. - -You could also have, at the time you started to fill the form for a -new entity BlogEntry, hit ``Apply`` instead of ``Validate`` and the -combobox titled ``add relation`` would have showed up. - - -.. image:: images/cbw-add-relation-entryof.en.png - :alt: editing a blog entry to add a relation to a blog - -Validate the changes by clicking ``Validate``. The entity BlogEntry -that is displayed now includes a link to the entity Blog named -``MyLife``. - -.. image:: images/cbw-detail-one-blogentry.en.png - :alt: displaying the detailed view of a blogentry - -Note that all of this was handled by the framework and that the only input -that was provided so far is the schema. To get a graphical view of the schema, -point your browser to the URL http://localhost:8080/schema - -.. image:: images/cbw-schema.en.png - :alt: graphical view of the schema (aka data-model) - - -Define your entities views --------------------------- - -The views selection principle -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A view is defined by a Python class which includes: - - - an identifier (all objects in `CubicWeb` are entered in a registry - and this identifier will be used as a key) - - - a filter to select the resulsets it can be applied to - - -`CubicWeb` provides a lot of standard views for the type -`EntityView`, for a complete list, you -will have to read the code in directory ``cubicweb/web/views/`` - -A view is applied on a `result set` which contains a set of -entities we are trying to display. `CubicWeb` uses a selector -mecanism which computes a score used to identify which view -is the best to apply for the `result set` we are trying to -display. The standard library of selectors is in -``cubicweb.common.selector`` and a library of methods used to -compute scores is available in ``cubicweb.vregistry.vreq``. - -It is possible to define multiple views for the same identifier -and to associate selectors and filters to allow the application -to find the best way to render the data. We will see more details -on this in :ref:`DefinitionVues`. - -For example, the view named ``primary`` is the one used to display -a single entity. We will now show you hos to customize this view. - - -View customization -~~~~~~~~~~~~~~~~~~ - -If you wish to modify the way a `BlogEntry` is rendered, you will have to -overwrite the `primary` view defined in the module ``views`` of the cube -``cubes/blog/views.py``. - -We can by example add in front of the pulication date a prefix specifying -the date we see is the publication date. - -To do so, please apply the following changes: - -:: - - from cubicweb.web.views import baseviews - - - class BlogEntryPrimaryView(baseviews.PrimaryView): - - accepts = ('BlogEntry',) - - def render_entity_title(self, entity): - self.w(u'

%s

' % html_escape(entity.dc_title())) - - def content_format(self, entity): - return entity.view('reledit', rtype='content_format') - - def cell_call(self, row, col): - entity = self.entity(row, col) - - # display entity attributes with prefixes - self.w(u'

%s

' % entity.title) - self.w(u'

published on %s

' % entity.publish_date.strftime('%Y-%m-%d')) - self.w(u'

%s

' % entity.content) - - # display relations - siderelations = [] - if self.main_related_section: - self.render_entity_relations(entity, siderelations) - -.. note:: - When a view is modified, it is not required to restart the application - server. Save the Python file and reload the page in your web browser - to view the changes. - -You can now see that the publication date has a prefix. - -.. image:: images/cbw-update-primary-view.en.png - :alt: modified primary view - - -The above source code defines a new primary view for -``BlogEntry``. - -Since views are applied to resultsets and resulsets can be tables of -data, it is needed to recover the entity from its (row,col) -coordinates. We will get to this in more detail later. - -The view has a ``self.w()`` method that is used to output data. In our -example we use it to output HTML tags and values of the entity's attributes. diff -r 3159772915c4 -r d5acef862c58 doc/book/en/01-05-components.en.txt --- a/doc/book/en/01-05-components.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -.. -*- coding: utf-8 -*- - -.. _components: - -Components ----------- - -What is a component -~~~~~~~~~~~~~~~~~~~ - -A component is a model grouping one or more entity types and/or views associated -in order to provide a specific feature or even a complete application using -others components. -You can decide to write your own set of components if you wish to re-use the -entity types you develop. By default, LAX comes with its owns set of components -that you can start using right away. - - -Standard library -~~~~~~~~~~~~~~~~ - -A library of standard components is part of the `LAX` release (look at -``lax/skel/ginco-apps``). Components provide entities and views. With -``lax-0.4``, you should get a set of application entities and system -entities you can re-use. - -The available application entities are: - -* addressbook: PhoneNumber and PostalAddress - -* ebasket: Basket (like a shopping cart) - -* eblog: Blog (a *very* basic blog) - -* eclassfolder: Folder (to organize things but grouping them in folders) - -* eclasstags: Tag (to tag anything) - - -* efile: File (to allow users to upload and store binary or text files) - -* elink: Link (to collect links to web resources) - -* emailinglist: MailingList (to reference a mailing-list and the URLs - for its archives and its admin interface) - -* eperson: Person (easily mixed with addressbook) - -* etask: Task (something to be done between start and stop date) - -* ezone: Zone (to define places within larger places, for example a - city in a state in a country) - -The available system entities are: - -* ecomment: Comment (to attach comment threads to entities) - - - -Adding comments to BlogDemo -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To import a component in your application just change the line in the -``app.conf`` file. For example:: - - included-yams-components=ecomment - -will make the ``Comment`` entity available in your ``BlogDemo`` -application. - -Change the schema to add a relationship between ``BlogEntry`` and -``Comment`` and you are done. Since the ecomment component defines the -``comments`` relationship, adding the line:: - - comments = ObjectRelation('Comment', cardinality='1*', composite='object') - -to the definition of a ``BlogEntry`` will be enough. - -Clear the datastore and restart. - -Component structure -~~~~~~~~~~~~~~~~~~~ - -A complex component is structured as follows: -:: - - mycomponent/ - | - |-- schema.py - | - |-- entities/ - | - |-- sobjects/ - | - |-- views/ - | - |-- test/ - | - |-- i18n/ - | - |-- data/ - | - |-- migration/ - | |- postcreate.py - | \- depends.map - | - |-- debian/ - | - \-- __pkginfo__.py - -We can also define simple Python module instead of directories (packages), for example: -:: - - mycomponent/ - | - |-- entities.py - |-- hooks.py - \-- views.py - - -where: - -* ``schema`` contains the definition of the schema (server side only) -* ``entities`` contains entities definition (server side and web interface) -* ``sobjects`` contains hooks and/or notification views (server side only) -* ``views`` contains the web interface components (web interface only) -* ``test`` contains tests related to the application (not installed) -* ``i18n`` contains messages catalogs for supported languages (server side and - web interface) -* ``data`` contains data files for static content (images, css, javascripts) - ...(web interface only) -* ``migration`` contains initialization file for new instances (``postcreate.py``) - and a file containing dependencies of the component depending on the version - (``depends.map``) -* ``debian`` contains all the files managing debian packaging (you will find - the usual files ``control``, ``rules``, ``changelog``... not installed) -* file ``__pkginfo__.py`` provides component meta-data, especially the distribution - and the current version(server side and web interface) or sub-components used by - the component. - -At least you should have: - -* the file ``__pkginfo__.py`` -* schema definition - -[WRITE ME] - -* explain the component architecture - -* add comments to the blog by importing the comments component diff -r 3159772915c4 -r d5acef862c58 doc/book/en/01-06-maintemplate.en.txt --- a/doc/book/en/01-06-maintemplate.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +0,0 @@ -.. -*- coding: utf-8 -*- - -Views & Templates ------------------ - -Look at ``lax/skel/ginco/web/views/basetemplates.py`` and you will -find the base templates used to generate HTML for your application. - -A page is composed as indicated on the schema below: - -.. image:: images/lax-book.06-main-template-layout.en.png - -In this section we will go through a couple of the primary templates -you must be interested in, that is to say, the HTMLPageHeader, -the HTMLPageFooter and the TheMainTemplate. - - -HTMLPageHeader -~~~~~~~~~~~~~~~ - -Let's use a different logo than the default one provided with LAX -and customize our header. - -Change logo -``````````` - -The easiest way to use a different logo is to replace the existing -``logo.png`` in ``myapp/data`` by your prefered icon and refresh. -By default all application will look for a ``logo.png`` to be -rendered in the logo section. - -.. image:: images/lax-book.06-main-template-logo.en.png - -[ADD] -customized external_resources in myapp/data cd crih for reference - -[WRITE ME] -ADD how to use external_resources variables used in ginco/web/webconfig.py - -Customize header -````````````````` - -Let's now move the search box in the header and remove the login form -from the header. We'll show how to move it to the left column of the application. - -Let's sat we do not want anymore the login menu to be in the header, but we -prefer it to be in the left column just below the logo. As the left column is -rendered by ``TheMainTemplate``, we will show how to do it in TheMainTemplate_. - -First, to remove the login menu, we just need to comment out the display of the -login component such as follows: :: - - class MyHTMLPageHeader(HTMLPageHeader): - - def main_header(self, view): - """build the top menu with authentification info and the rql box""" - self.w(u'\n') - self.w(u'\n') - # appliname and breadcrumbs - self.w(u'') - # logged user and help - #self.w(u'') - # lastcolumn - self.w(u'\n') - self.w(u'\n') - self.template('logform', rset=self.rset, id='popupLoginBox', klass='hidden', - title=False, message=False) - - - -.. image:: images/lax-book.06-header-no-login.en.png - -Let's now move the search box in the top-right header area. To do so, we will -first create a method to get the search box display and insert it in the header -table. - -:: - - from ginco.web.views.basetemplates import HTMLPageHeader - class MyHTMLPageHeader(HTMLPageHeader): - def main_header(self, view): - """build the top menu with authentification info and the rql box""" - self.w(u'\n') - self.w(u'\n') - # appliname and breadcrumbs - self.w(u'') - - # logged user and help - #self.w(u'') - - self.w(u'') - # lastcolumn - self.w(u'\n') - self.w(u'\n') - self.template('logform', rset=self.rset, id='popupLoginBox', klass='hidden', - title=False, message=False) - - def get_searchbox(self, view, context): - boxes = list(self.vreg.possible_vobjects('boxes', self.req, self.rset, - view=view, context=context)) - if boxes: - for box in boxes: - if box.id == 'search_box': - box.dispatch(w=self.w, view=view) - - - - -HTMLPageFooter -~~~~~~~~~~~~~~ - -If you want to change the footer for example, look -for HTMLPageFooter and override it in your views file as in: -:: - - form ginco.web.views.basetemplates import HTMLPageFooter - class MyHTMLPageFooter(HTMLPageFooter): - def call(self, **kwargs): - self.w(u'') - -Updating a view does not require any restart of the server. By reloading -the page you can see your new page footer. - - -TheMainTemplate -~~~~~~~~~~~~~~~ - -.. _TheMainTemplate: - -The MainTemplate is a bit complex as it tries to accomodate many -different cases. We are now about to go through it and cutomize entirely -our application. - -TheMainTemplate is responsible for the general layout of the entire application. -It defines the template of ``id = main`` that is used by the application. Is -also defined in ``ginco/web/views/basetemplates.py`` another template that can -be used based on TheMainTemplate called SimpleMainTemplate which does not have -a top section. - -.. image:: images/lax-book.06-simple-main-template.en.png - -CSS changes -~~~~~~~~~~~ - -We cannot modify the order in which the application is reading the CSS. In -the case we want to create new CSS style, the best is to define it a in a new -CSS located under ``myapp/data/``. - -If you want to modify an existing CSS styling property, you will have to use -``!important`` declaration to override the existing property. The application -apply a higher priority on the default CSS and you can not change that. -Customized CSS will not be read first. - -[TODO] -Add login menu in left column - - -[WRITE ME] - -* customize MainTemplate and show that everything in the user - interface can be changed - -[TODO] -Rajouter une section pour definir la terminologie utilisee. -Dans ginco-doc rajouter une section pour erudi-ctl shell ou -on liste les commandes dispos. diff -r 3159772915c4 -r d5acef862c58 doc/book/en/01-07-rss-xml.en.txt --- a/doc/book/en/01-07-rss-xml.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -.. -*- coding: utf-8 -*- - -RSS Channel ------------ - -Assuming you have several blog entries, click on the title of the -search box in the left column. A larger search box should appear. Enter:: - - Any X ORDERBY D WHERE X is BlogEntry, X creation_date D - -and you get a list of blog entries. - -Click on your login at the top right corner. Chose "user preferences", -then "boxes", then "possible views box" and check "visible = yes" -before validating your changes. - -Enter the same query in the search box and you will see the same list, -plus a box titled "possible views" in the left column. Click on -"entityview", then "RSS". - -You just applied the "RSS" view to the RQL selection you requested. - -That's it, you have a RSS channel for your blog. - -Try again with:: - - Any X ORDERBY D WHERE X is BlogEntry, X creation_date D, - X entry_of B, B title "MyLife" - -Another RSS channel, but a bit more focused. - -A last one for the road:: - - Any C ORDERBY D WHERE C is Comment, C creation_date D LIMIT 15 - -displayed with the RSS view, that's a channel for the last fifteen -comments posted. - -[WRITE ME] - -* show that the RSS view can be used to display an ordered selection - of blog entries, thus providing a RSS channel - -* show that a different selection (by category) means a different channel - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/01-08-book-map.en.txt --- a/doc/book/en/01-08-book-map.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -.. -*- coding: utf-8 -*- - -Book map -========= - -[WRITE ME] - -* explain how to use this book and what chapters to read in what order depending on the - objectives of the reader - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/02-00-foundation.en.txt --- a/doc/book/en/02-00-foundation.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -.. -*- coding: utf-8 -*- - -`CubicWeb` Foundations -====================== - -A little history... -------------------- - -`CubicWeb` is a web application framework developped by Logilab_ since 2001. - -Entirely written in Python, `CubicWeb` publishes data from all sorts -of sources such as SQL database, LDAP directory and versioning system such -as subversion. - -`CubicWeb` user interface was designed to let the final user a huge flexibility -on how to select and how to display content. It allows to browse the knowledge -database and to display the results with the best rendering according to -the context. -This interface flexibility gives back the user the control of the -rendering parameters that are usually reserved for developpers. - - -We can list a couple of web applications developped with `CubicWeb`, an online -public phone directory (see http://www.118000.fr/), a system for managing -digital studies and simulations for a research lab, a tool for shared children -babysitting (see http://garde-partagee.atoukontact.fr/), a tool to manage -software developpment (see http://www.logilab.org), etc. - -In 2008, `CubicWeb` was ported for a new type of source : the datastore -from GoogleAppEngine_. - -.. include:: 02-01-concepts.en.txt -.. include:: 02-02-registry.en.txt -.. include:: 02-03-configuration.en.txt diff -r 3159772915c4 -r d5acef862c58 doc/book/en/02-01-concepts.en.txt --- a/doc/book/en/02-01-concepts.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,411 +0,0 @@ -.. -*- coding: utf-8 -*- - -Concepts --------- - -Global architecture -~~~~~~~~~~~~~~~~~~~ -.. image:: images/archi_globale.png - -.. note:: - For real, the client and server sides are integrated in the same - process and interact directly, without the needs for distants - calls using Pyro. It is important to note down that those two - sides, client/server, are disjointed and it is possible to execute - a couple of calls in distincts processes to balance the load of - your web site on one or more machines. - -.. _TermsVocabulary: - -Terms and vocabulary -~~~~~~~~~~~~~~~~~~~~~ - -*schema* - The schema defines the data model of an application based on entities - and relations, modeled with a comprehensive language made of Python - classes based on `yams`_ library. This is the core piece - of an application. It is initially defined in the file system and is - stored in the database at the time an instance is created. `CubicWeb` - provides a certain number of system entities included automatically as - it is necessarry for the core of `CubicWeb` and a library of - cubes that can be explicitely included if necessary. - - -*entity type* - An entity is a set of attributes; the essential attribute of - an entity is its key, named eid - -*relation type* - Entities are linked to each others by relations. In `CubicWeb` - relations are binary: by convention we name the first item of - a relation the `subject` and the second the `object`. - -*final entity type* - Final types corresponds to the basic types such as string of characters, - integers... Those types have a main property which is that they can - only be used as `object` of a relation. The attributes of an entity - (non final) are entities (finals). - -*final relation type* - A relation is said final if its `object` is a final type. This is equivalent - to an entity attribute. - -*relation definition* - a relation definition is a 3-uple (subject entity type, relation type, object entity type), - with an associated set of property such as cardinality, constraints... - -*repository* - This is the RQL server side of `CubicWeb`. Be carefull not to get - confused with a Mercurial repository or a debian repository. - -*source* - A data source is a container of data (SGBD, LDAP directory, `Google - App Engine`'s datastore ...) integrated in the - `CubicWeb` repository. This repository has at least one source, `system` which - contains the schema of the application, plain-text index and others - vital informations for the system. - -*configuration* - It is possible to create differents configurations for an instance: - - - ``repository`` : repository only, accessible for clients using Pyro - - ``twisted`` : web interface only, access the repository using Pyro - - ``all-in-one`` : web interface and repository in a single process. - The repository could be or not accessible using Pyro. - -*cube* - A cube is a model grouping one or multiple data types and/or views - to provide a specific functionnality or a complete `CubicWeb` application - potentially using other cubes. The available subes are located in the file - system at `/path/to/forest/cubicweb/cubes`. - Larger applications can be built faster by importing cubes, - adding entities and relationships and overriding the - views that need to display or edit informations not provided by - cubes. - -*instance* - An instance is a specific installation of a cube. All the required - configuration files necessarry for the well being of your web application - are grouped in an instance. This will refer to the cube(s) your application - is based on. - By example logilab.org and our intranet are two instances of a single - cube jpl, developped internally. - The instances are defined in the directory `~/etc/cubicweb.d`. - -*application* - The term application is sometime used to talk about an instance - and sometimes to talk of a cube depending on the context. - So we would like to avoid using this term and try to use *cube* and - *instance* instead. - -*result set* - This object contains the results of an RQL query sent to the source - and information on the query. - -*Pyro* - `Python Remote Object`_, distributed objects system similar to Java's RMI - (Remote Method Invocation), which can be used for the dialog between the web - side of the framework and the RQL repository. - -*query language* - A full-blown query language named RQL is used to formulate requests - to the database or any sources such as LDAP or `Google App Engine`'s - datastore. - -*views* - A view is applied to a `result set` to present it as HTML, XML, - JSON, CSV, etc. Views are implemented as Python classes. There is no - templating language. - -*generated user interface* - A user interface is generated on-the-fly from the schema definition: - entities can be created, displayed, updated and deleted. As display - views are not very fancy, it is usually necessary to develop your - own. Any generated view can be overridden by defining a new one with - the same identifier. - -*rql* - XXX - -.. _`Python Remote Object`: http://pyro.sourceforge.net/ -.. _`yams`: http://www.logilab.org/project/yams/ - - -`CubicWeb` engine -~~~~~~~~~~~~~~~~~ - -The engine in `CubicWeb` is a set of classes managing a set of objects loaded -dynamically at the startup of `CubicWeb` (*appobjects*). Those dynamics objects, based on the schema -or the library, are building the final application. The differents dymanic components are -by example: - -* client and server side - - - entities definition, containing the logic which enables application data manipulation - -* client side - - - *views*, or more specifically - - - boxes - - header and footer - - forms - - page templates - - - *actions* - - *controllers* - -* server side - - - notification hooks - - notification views - -The components of the engine are: - -* a frontal web (only twisted is available so far), transparent for dynamic objects -* an object that encapsulates the configuration -* a `registry` (`cubicweb.cwvreg`) containing the dynamic objects loaded automatically - -Every *appobject* may access to the instance configuration using its *config* attribute -and to the registry using its *vreg* attribute. - -API Python/RQL -~~~~~~~~~~~~~~ - -Inspired from the standard db-api, with a Connection object having the methods -cursor, rollback and commit essentially. The most important method is -the `execute` method of a cursor : - -`execute(rqlstring, args=None, eid_key=None, build_descr=True)` - -:rqlstring: the RQL query to execute (unicode) -:args: if the query contains substitutions, a dictionnary containing the values to use -:eid_key: - an implementation detail of the RQL queries cache implies that if a substitution - is used to introduce an eid *susceptible to raise the ambiguities in the query - type resolution*, then we have to specify the correponding key in the dictionnary - through this argument - - -The `Connection` object owns the methods `commit` and `rollback`. You *should -never need to use them* during the development of the web interface based on -the `CubicWeb` framework as it determines the end of the transaction depending -on the query execution success. - -.. note:: - While executing updates queries (SET, INSERT, DELETE), if a query generates - an error related to security, a rollback is automatically done on the current - transaction. - - -The `Request` class (`cubicweb.web`) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A request instance is created when an HTPP request is sent to the web server. -It contains informations such as forms parameters, user authenticated, etc. - -**Globally, a request represents a user query, either through HTTP or not -(we also talk about RQL queries on the server side by example)** - -An instance of `Request` has the following attributes: - -* `user`, instance of `cubicweb.common.utils.User` corresponding to the authenticated - user -* `form`, dictionnary containing the values of a web form -* `encoding`, characters encoding to use in the response - -But also: - -:Session data handling: - * `session_data()`, returns a dictinnary containing all the session data - * `get_session_data(key, default=None)`, returns a value associated to the given - key or the value `default` if the key is not defined - * `set_session_data(key, value)`, assign a value to a key - * `del_session_data(key)`, suppress the value associated to a key - - -:Cookies handling: - * `get_cookie()`, returns a dictionnary containing the value of the header - HTTP 'Cookie' - * `set_cookie(cookie, key, maxage=300)`, adds a header HTTP `Set-Cookie`, - with a minimal 5 minutes length of duration by default (`maxage` = None - returns a *session* cookie which will expire when the user closes the browser - window - * `remove_cookie(cookie, key)`, forces a value to expire - -:URL handling: - * `url()`, returns the full URL of the HTTP request - * `base_url()`, returns the root URL of the web application - * `relative_path()`, returns the relative path of the request - -:And more...: - * `set_content_type(content_type, filename=None)`, adds the header HTTP - 'Content-Type' - * `get_header(header)`, returns the value associated to an arbitrary header - of the HTTP request - * `set_header(header, value)`, adds an arbitrary header in the response - * `cursor()` returns a RQL cursor on the session - * `execute(*args, **kwargs)`, shortcut to ``.cursor().execute()`` - * `property_value(key)`, properties management (`EProperty`) - * dictionnary `data` to store data to share informations between components - *while a request is executed* - -Please note down that this class is abstract and that a concrete implementation -will be provided by the *frontend* web used (in particular *twisted* as of -today). For the views or others that are executed on the server side, -most of the interface of `Request` is defined in the session associated -to the client. - -The `AppObject` class -~~~~~~~~~~~~~~~~~~~~~ - -In general: - -* we do not inherit directly from this class but from a more specific - class such as `AnyEntity`, `EntityView`, `AnyRsetView`, - `Action`... - -* to be recordable, a subclass has to define its own register (attribute - `__registry__`) and its identifier (attribute `id`). Usually we do not have - to take care of the register, only the identifier `id`. - -We can find a certain number of attributes and methods defined in this class -and so common to all the application objects: - -At the recording, the following attributes are dynamically added to -the *subclasses*: - -* `vreg`, the `vregistry` of the application -* `schema`, the application schema -* `config`, the application configuration - -We also find on instances, the following attributes: - -* `req`, `Request` instance -* `rset`, the *result set* associated to the object if necessarry -* `cursor`, rql cursor on the session - - -:URL handling: - * `build_url(method=None, **kwargs)`, returns an absolute URL based on - the given arguments. The *controller* supposed to handle the response - can be specified through the special parameter `method` (the connection - is theoretically done automatically :). - - * `datadir_url()`, returns the directory of the application data - (contains static files such as images, css, js...) - - * `base_url()`, shortcut to `req.base_url()` - - * `url_quote(value)`, version *unicode safe* of the function `urllib.quote` - -:Data manipulation: - - * `etype_rset(etype, size=1)`, shortcut to `vreg.etype_rset()` - - * `eid_rset(eid, rql=None, descr=True)`, returns a *result set* object for - the given eid - * `entity(row, col=0)`, returns the entity corresponding to the data position - in the *result set* associated to the object - - * `complete_entity(row, col=0, skip_bytes=True)`, is equivalent to `entity` but - also call the method `complete()` on the entity before returning it - -:Data formatting: - * `format_date(date, date_format=None, time=False)` - * `format_time(time)` - -:And more...: - - * `external_resource(rid, default=_MARKER)`, access to a value defined in the - configuration file `external_resource` - - * `tal_render(template, variables)`, - - -.. note:: - When we inherit from `AppObject` (even not directly), you *always* have to use - **super()** to get the methods and attributes of the superclasses, and not - use the class identifier. - By example, instead of writting: :: - - class Truc(PrimaryView): - def f(self, arg1): - PrimaryView.f(self, arg1) - - You'd better write: :: - - class Truc(PrimaryView): - def f(self, arg1): - super(Truc, self).f(arg1) - - -Standard structure for a cube -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A complex cube is structured as follows: - -:: - - mycube/ - | - |-- schema.py - | - |-- entities/ - | - |-- sobjects/ - | - |-- views/ - | - |-- test/ - | - |-- i18n/ - | - |-- data/ - | - |-- migration/ - | |- postcreate.py - | \- depends.map - | - |-- debian/ - | - \-- __pkginfo__.py - -We can use simple Python module instead of packages, by example: - -:: - - mycube/ - | - |-- entities.py - |-- hooks.py - \-- views.py - - -where : - -* ``schema`` contains the schema definition (server side only) -* ``entities`` contains the entities definition (server side and web interface) -* ``sobjects`` contains hooks and/or views notifications (server side only) -* ``views`` contains the different components of the web interface (web interface only) -* ``test`` contains tests specifics to the application (not installed) -* ``i18n`` contains the messages catalog for supported languages (server side and - web interface) -* ``data`` contains arbitrary data files served statically - (images, css, javascripts files)... (web interface only) -* ``migration`` contains the initialization file for new instances - (``postcreate.py``) and in general a file containing the `CubicWeb` dependancies - of the cube depending on its version (``depends.map``) -* ``debian`` contains all the files that manages the debian packaging - (you would find there the classical structure with ``control``, ``rules``, - ``changelog``... (not installed) -* the file ``__pkginfo__.py`` provides meta-data on the cube, especially the - distribution name and the current version (server side and web interface) or - also the sub-cubes used by this cube - -The only required files are: - -* the file ``__pkginfo__.py`` -* the schema definition - XXX false, we may want to have cubes which are only adding a service, no persistent data (eg embeding for instance) - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/02-02-registry.en.txt --- a/doc/book/en/02-02-registry.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -.. -*- coding: utf-8 -*- - -The Registry ------------- - -[WRITE ME] - -* talk about the vreg singleton, appobjects, registration and selection - - -Details of the recording process -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -At startup, the `registry` or registers base, inspects a number of directories -looking for compatible classes definition. After a recording process, the objects -are assigned to registers so that they can be selected dynamically while the -application is running. - -The base class of those objects is `AppRsetObject` (module `cubicweb.common.appobject`). - -XXX registers example -XXX actual details of the recording process! - -Runtime objects selection -~~~~~~~~~~~~~~~~~~~~~~~~~ - -XXX tell why it's a cw foundation! - -Application objects are stored in the registry using a two level hierarchy : - - object's `__registry__` : object's `id` : [list of app objects] - -The following rules are applied to select an object given a register and an id and an input context: -* each object has a selector - - its selector may be derivated from a set of basic (or not :) - selectors using `chainall` or `chainfirst` combinators -* a selector return a score >= 0 -* a score of 0 means the objects can't be applied to the input context -* the object with the greatest score is selected. If multiple objects have an - identical score, one of them is selected randomly (this is usually a bug) - -The object's selector is the `__select__` class method on the object's class. - -The score is used to choose the most pertinent objects where there are more than -one selectable object. For instance, if you're selecting the primary -(eg `id = 'primary'`) view (eg `__registry__ = 'view'`) for a result set containing -a `Card` entity, 2 objects will probably be selectable: - -* the default primary view (`accepts = 'Any'`) -* the specific `Card` primary view (`accepts = 'Card'`) - -This is because primary views are using the `accept_selector` which is considering the -`accepts` class attribute of the object's class. Other primary views specific to other -entity types won't be selectable in this case. And among selectable objects, the -accept selector will return a higher score the the second view since it's more -specific, so it will be selected as expected. - -Usually, you won't define it directly but by defining the `__selectors__` tuple -on the class, with :: - - __selectors__ = (sel1, sel2) - -which is equivalent to :: - - __select__ = classmethod(chainall(sel1, sel2)) - -The former is prefered since it's shorter and it's ease overriding in -subclasses (you have access to sub-selectors instead of the wrapping function). - -:chainall(selectors...): if one selector return 0, return 0, else return the sum of scores - -:chainfirst(selectors...): return the score of the first selector which has a non zero score - -XXX describe standard selector (link to generated api doc!) - -Example -```````` - -Le but final : quand on est sur un Blog, on veut que le lien rss de celui-ci pointe -vers les entrées de ce blog, non vers l'entité blog elle-même. - -L'idée générale pour résoudre ça : on définit une méthode sur les classes d'entité -qui renvoie l'url du flux rss pour l'entité en question. Avec une implémentation -par défaut sur AnyEntity et une implémentation particulière sur Blog qui fera ce -qu'on veut. - -La limitation : on est embêté dans le cas ou par ex. on a un result set qui contient -plusieurs entités Blog (ou autre chose), car on ne sait pas sur quelle entité appeler -la méthode sus-citée. Dans ce cas, on va conserver le comportement actuel (eg appel -à limited_rql) - -Donc : on veut deux cas ici, l'un pour un rset qui contient une et une seule entité, -l'autre pour un rset qui contient plusieurs entité. - -Donc... On a déja dans web/views/boxes.py la classe RSSIconBox qui fonctionne. Son -sélecteur :: - - class RSSIconBox(ExtResourcesBoxTemplate): - """just display the RSS icon on uniform result set""" - __selectors__ = ExtResourcesBoxTemplate.__selectors__ + (nfentity_selector,) - - -indique qu'il prend en compte : - -* les conditions d'apparition de la boite (faut remonter dans les classes parentes - pour voir le détail) -* nfentity_selector, qui filtre sur des rset contenant une liste d'entité non finale - -ça correspond donc à notre 2eme cas. Reste à fournir un composant plus spécifique -pour le 1er cas :: - - class EntityRSSIconBox(RSSIconBox): - """just display the RSS icon on uniform result set for a single entity""" - __selectors__ = RSSIconBox.__selectors__ + (onelinerset_selector,) - - -Ici, on ajoute onelinerset_selector, qui filtre sur des rset de taille 1. Il faut -savoir que quand on chaine des selecteurs, le score final est la somme des scores -renvoyés par chaque sélecteur (sauf si l'un renvoie zéro, auquel cas l'objet est -non sélectionnable). Donc ici, sur un rset avec plusieurs entités, onelinerset_selector -rendra la classe EntityRSSIconBox non sélectionnable, et on obtiendra bien la -classe RSSIconBox. Pour un rset avec une entité, la classe EntityRSSIconBox aura un -score supérieur à RSSIconBox et c'est donc bien elle qui sera sélectionnée. - -Voili voilou, il reste donc pour finir tout ça : - -* à définir le contenu de la méthode call de EntityRSSIconBox -* fournir l'implémentation par défaut de la méthode renvoyant l'url du flux rss sur - AnyEntity -* surcharger cette methode dans blog.Blog - - -When to use selectors? -``````````````````````` - -Il faut utiliser les sélecteurs pour faire des choses différentes en -fonction de ce qu'on a en entrée. Dès qu'on a un "if" qui teste la -nature de `self.rset` dans un objet, il faut très sérieusement se -poser la question s'il ne vaut pas mieux avoir deux objets différent -avec des sélecteurs approprié. - -If this is so fundamental, why don't I see them more often? -``````````````````````````````````````````````````````````` - -Because you're usually using base classes which are hiding the plumbing -of __registry__ (almost always), id (often when using "standard" object), -register and selector. diff -r 3159772915c4 -r d5acef862c58 doc/book/en/02-03-configuration.en.txt --- a/doc/book/en/02-03-configuration.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -.. -*- coding: utf-8 -*- - -Configuration -------------- - -[WRITE ME] - -* the config object. adding configuration option - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/03-00-definition-schema.en.txt --- a/doc/book/en/03-00-definition-schema.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -.. -*- coding: utf-8 -*- - -Data Model definition (*schema*) -================================ - -The schema is the main concept of `LAX` applications as it defines the -data model we will handle. It is based on entities types already defined -in the library and others, more specific, we would expect to find in one or -more Python files under the `schema` directory. - -It is important to make clear the difference between relation type and relation -definition: a relation type is only a relation name with potentially other -additionnal properties (see XXXX), whereas a relation definition is a complete -triplet " ". A relation -type could have been implied if none is related to a relation definition of the -schema. - - -.. include:: 03-10-stdlib-schemas.en.txt -.. include:: 03-11-definition-schema.en.txt diff -r 3159772915c4 -r d5acef862c58 doc/book/en/03-00-setup.en.txt --- a/doc/book/en/03-00-setup.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -.. -*- coding: utf-8 -*- - -.. _MiseEnPlaceEnv: - -=================================================== -Installation and set-up of a `CubicWeb` environment -=================================================== -.. contents:: - -.. include:: 03-01-installation.en.txt -.. include:: 03-02-create-instance.en.txt -.. include:: 03-03-cubicweb-ctl.en.txt - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/03-01-bis-installation.en.txt --- a/doc/book/en/03-01-bis-installation.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -.. -*- coding: utf-8 -*- - -.. _installationGAE: - -Installation de `CubicWeb` pour GoogleAppEngine -=============================================== - -Qu'est-ce que `LAX` ? -======================= - -`LAX` (Logilab Appengine eXtension) est un framework d'application -web basé sur `Google AppEngine`. - -`LAX` est un portage de la partie web de la plate-forme applicative -développée par Logilab depuis 2001. Cette plate-forme publie des -données tirées de bases SQL, d'annuaires LDAP et de systèmes de -gestion de version. En avril 2008, elle a été portée pour fonctionner -sur le "datastore" de `Google AppEngine`. - -XXX: faire un parallèle entre Django/GAE et LAX/GAE - - -Téléchargement des sources -========================== - -- Les sources de `Google AppEngine` peuvent être récupérées à l'adresse - suivante : http://code.google.com/appengine/downloads.html - -- Les sources de `LAX` se trouvent à l'adresse suivante : - http://lax.logilab.org/ - - -Installation -============ - -Une fois décompactée, l'archive `lax-0.1.0-alpha.tar.gz`, on obtient -l'arborescence suivante:: - - . - |-- app.yaml - |-- custom.py - |-- data - |-- ginco/ - |-- i18n/ - |-- logilab/ - |-- main.py - |-- mx/ - |-- rql/ - |-- schema.py - |-- simplejson/ - |-- tools/ - | |-- generate_schema_img.py - | `-- i18ncompile.py - |-- views.py - |-- yams/ - `-- yapps/ - - -On retrouve le squelette d'une application web de `Google AppEngine` -(fichiers ``app.yaml``, ``main.py`` en particulier) avec les dépendances -supplémentaires nécessaires à l'utilisation du framework `LAX` - - -Lancement de l'application de base -================================== - -Plusieurs répertoires doivent être accessibles via la variable -d'environnement ``PYTHONPATH`` :: - - $ export PYTHONPATH=/path/to/google_appengine:/path/to/google_appengine/lib/yaml/lib:/path/to/myapp/ - -Le répertoire yaml n'est nécessaire que pour le lancement des scripts -qui se trouvent dans lax/tools et pour l'exécution des tests unitaires. - -Pour démarrer:: - - $ python /path/to/google_appengine/dev_appserver.py /path/to/lax - - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/03-01-installation.en.txt --- a/doc/book/en/03-01-installation.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -.. -*- coding: utf-8 -*- - -Installation -============ - -Installation of `Cubicweb` and its dependancies ------------------------------------------------ - -`CubicWeb` is available as a debian package as well as an archive. -We will detail here the two easiest way to set-up `CubciWeb` -environment. - -Debian packages -``````````````` -You need first to make sure that you added our public repository -in the list of sources you packages manager will search in. - -Depending on the debian distribution you are using here are all the -available options: :: - - deb http://ftp.logilab.org/dists/ lenny/ - deb http://ftp.logilab.org/dists/ hardy/ - deb http://ftp.logilab.org/dists/ sid/ - -As we assume you are installing `CubciWeb` on a debian machine, please -add the appropriate line from above in ``/etc/apt/sources.list``. - -You can now install the required packages with the follwoing command: :: - - apt-get install cubicweb - -This is it! - -``tar.gz`` archive -`````````````````` - -You can download our sources at: :: - - http://ftp.logilab.org/pub/cubicweb/ - -Unpack the sources - - - - -.. note:: - `CubicWeb` is also available as a Mercurial repository using the forest - extension (see :ref:`MercurialForestInstall` for more details). - - -Postgres installation -````````````````````` - -Please refer to the project online documentation Postgres_. - -.. _Postgres: http://www.postgresql.org/ - -You need to install the three following packages: `postgres-8.3`, -`postgres-contrib-8.3` and `postgresql-plpython-8.3`. - - -Then you can install: - -* `pyro` if you wish the repository is accessible through Pyro - or if the client and the server are not running on the same machine - (in suche case the packages will have to be isntalled on both - machines) - -* `python-ldap` if you plan to use a LDAP source on the server - -.. _ConfigurationEnv: - -Environment configuration -------------------------- - -[FIXME] -Ces variables ne sont plus requises pour le bon fonctionnement de `CubicWeb`, non? -A part rajouter la foret dans le PYTHONPATH, rien de plus ne doit etre fait? - -Update the environment variable PYTHONPATH to add to it the path to -the forest ``cubicweb``. - -Add the following lines to either `.bashrc` or `.bash_profile` to configure -your development environment :: - - export PYTHONPATH=/full/path/to/cubicweb-forest - - //deprecated?? - export ERUDI_REGISTRY=~/etc/erudi.d/ - export ERUDI_TEMPLATES=~/hg/ - export ERUDI_RUNTIME=/tmp/ - -Cela suppose que le composant erudi que vous développez est dans un -sous-répertoire de *~/hg/* et que vous avez créé le répertoire *~/etc/erudi.d/* -pour que `cubicweb-ctl` y place vos instances de test. - -.. _ConfigurationPostgres: - -Postgres configuration ----------------------- - -* First you have to initialize the database Postgres with the command ``initdb``. - :: - - $ initdb -D /path/to/pgsql - - Once initialized, you can launch the database server Postgres - with the command: :: - - $ postgres -D /path/to/psql - - If you cannot execute this command due to permission issues, please - make sure that your username has write access on the database. - :: - - $ chown username /path/to/pgsql - -* Create a superuser for `CubicWeb` instance (**root**) :: - - createuser -s username - - Initialize the password of the superuser you juste created with - ``su - postgres`` and ``psql``. - - This password will be asked to you later on where you will create an - instance with `cubicweb-ctl create` - -[XXX] -Est-ce que ces etapes sont vraiment necessaires? -sand : lors de l'installation de ma bdd cela n'a pas ete fait -et il semble que tout aille bien. Doit etre verifie avec les experts. - -* installation of plain-text index extension :: - - cat /usr/share/postgresql/8.3/contrib/tsearch2.sql | psql -U username template1 - -* installation of plpythonu language by default :: - - createlang -U pgadmin plpythonu template1 - - -Pyro configuration ------------------- - -If you use Pyro, it is required to have a name server Pyro runing on your -network (by default it is identified by a broadcast request). - -To do so, you need to : - -* launch the server manually before starting cubicweb with `pyro-ns` - -* launch the server manually before starting cubicweb as a server with - `pyro-nsd start` - -* edit the file ``/etc/default/pyro-nsd`` so that the name server pyro - will be launched automatically when the macine fire up - - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/03-02-create-instance.en.txt --- a/doc/book/en/03-02-create-instance.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -.. -*- coding: utf-8 -*- - -Creation of your first instance -=============================== - -What is an instance? --------------------- - -A `CubicWeb` instance is a directory in ``~/etc/cubicweb.d`` -which enables us to run a web application. An instance is based on -one or more cubes. - -An instance is a container that refers to cubes and configuration -parameters for your web application. - -We recommand not to define schema, entities or views in the instance -file system itself but in the cube, in order to maintain re-usability of -entities and their views. We strongly recommand to develop cubes which -could be used in other instances (modular approach). - - -What is a cube? ---------------- - -A cube defines entities, their views, their schems and workflows -in an independant directory located in ``/path/to/forest/cubicweb/cubes/``. - -When an instance is created, you list one or more cubes that your instance -will use. Use a cube means having the entities defined in your cube's schema -available in your instance as well as their views and workflows. - -.. note:: - The commands used below are more detailled in the section dedicated to - :ref:`cubicweb-ctl`. - - -Create a cube -------------- - -Let's start by creating the cube environment in which we will develop :: - - cd ~/hg - - cubicweb-ctl newcube mycube - - # answer questions - hg init moncube - cd mycube - hg add . - hg ci - -If all went well, you should see the cube you just create in the list -returned by `cubicweb-ctl list` in the section *Available components*, -and if it is not the case please refer to :ref:`ConfigurationEnv`. - -To use a cube, you have to list it in the variable ``__use__`` -of the file ``__pkginfo__.py`` of the instance. -This variable is used for the instance packaging (dependencies -handled by system utility tools such as APT) and the usable cubes -at the time the base is created (import_erschema('MyCube') will -not properly work otherwise). - -Instance creation ------------------ - -Now that we created our cube, we can create an instance to view our -application in a web browser. To do so we will use a `all-in-on` -configuration to simplify things :: - - cubicweb-ctl create -c all-in-one mycube myinstance - -.. note:: - Please note that we created a new cube for a demo purpose but - you could have use an existing cube available in our standard library - such as blog or person by example. - -A serie of questions will be prompted to you, the default answer is usually -sufficient. You can anyway modify the configuration later on by editing -configuration files. When a user/psswd is requested to access the database -please use the login you create at the time you configured the database -(:ref:`ConfigurationPostgres`). - -It is important to distinguish here the user used to access the database and -the user used to login to the cubicweb application. When a `CubicWeb` application -starts, it uses the login/psswd for the database to get the schema and handle -low transaction [FIXME - bas niveau]. But, when ``cubicweb-ctl create`` asks for -a manager login/psswd of `CubicWeb`, it refers to an application user you will -use during the development to administrate your web application. It will be -possible, later on, to create others users for your final web application. - -When this command is completed, the definition of your instance is -located in *~/etc/cubicweb.d/moninstance/*. To launch it, you just type :: - - cubicweb-ctl start -D myinstance - -The option `-D` specify the *debug mode* : the instance is not running in -server mode and does not disconnect from the termnial, which simplifies debugging -in case the instance is not properly launched. You can see how it looks by -visiting the URL `http://localhost:8080` (the port number depends of your -configuration). To login, please use the cubicweb administrator login/psswd you -defined when you created the instance. - -To shutdown the instance, Crtl-C in the terminal window is enough. -If you did not use the option `-D`, then type :: - - cubicweb-ctl stop myinstance - -This is it! All is settled down to start developping your data model... - - -Usage of `cubicweb-liveserver` -`````````````````````````````` - -To quickly test a new cube, you can also use the script `cubicweb-liveserver` -which allows to create an application in memory (use of SQLite database by -default) and make it accessible through a web server :: - - cubicweb-ctl live-server mycube - -or by using an existing database (SQLite or Postgres):: - - cubicweb-ctl live-server -s myfile_sources mycube - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/03-03-cubicweb-ctl.en.txt --- a/doc/book/en/03-03-cubicweb-ctl.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -.. -*- coding: utf-8 -*- - -.. _cubicweb-ctl: - -``cubicweb-ctl`` tool -===================== - -`cubicweb-ctl` is the swiss knife to manage `CubicWeb` instances. -The general syntax is :: - - cubicweb-ctl [options command] - -To view available commands :: - - cubicweb-ctl - cubicweb-ctl --help - -Please note that the commands available depends on the `CubicWeb` packages -and cubes that have been installed. - -To view the help menu on specific command :: - - cubicweb-ctl --help - -Command to create a cube ------------------------- - -* ``newcube``, create a new cube on the file system based on the name - given in the parameters. This command create a cube from an application - skeleton that includes default files required for debian packaging. - - -Command to create an instance ------------------------------ -* ``create``, creates the files for the instance configuration -* ``db-create``, creates the system database of an instance (tables and - extensions only) -* ``db-init``, initializes the system database of an instance - (schema, groups, users, workflows...) - -By default, those three commandes are encapsulated in ``create`` so -that they can be executed consecutively. - -Command to create an instance for Google AppEngine datastore source -------------------------------------------------------------------- -* ``newgapp``, creates the configuration files for an instance - -This command needs to be followed by the commands responsible for -the database initialization. As those are specific to the `datastore`, -specific Google AppEgine database, they are not available for now -in cubicweb-ctl, but they are available in the instance created. - -[FIXME] - add link to gae install -For more details, please see :ref:`` . - -Commands to launch instance ---------------------------- -* ``start``, starts one or more or all instances -* ``stop``, stops one or more or all instances -* ``restart``, restarts one or more or all instances -* ``status``, returns the status of the instance - -Commands to maintain instances ------------------------------- -* ``upgrade``, launches the existing instances migration when a new version - of `CubicWeb` or the cubes installed is available -* ``shell``, opens a migration shell for manual maintenance of the instance -* ``db-dump``, creates a dump of the system database -* ``db-restore``, restores a dump of the system database -* ``db-check``, checks data integrity of an instance. If the automatic correction - is activated, it is recommanded to create a dump before this operation. -* ``schema-sync``, synchronizes the persistent schema of an instance with - the application schema. It is recommanded to create a dump before this operation. - -Commands to maintain i18n catalogs ----------------------------------- -* ``i18nlibupdate``, regenerates messages catalogs of the `CubicWeb` library -* ``i18nupdate``, regenerates the messages catalogs of a cube -* ``i18ncompile``, recompiles the messages catalogs of an instance. - This is automatically done while upgrading. - -Cf :ref:`Internationalisation`. - -Other commands --------------- -* ``list``, provides a list of the available configuration, cubes - and instances. -* ``delete``, deletes an instance (configuration files and database) - -Examples --------- - -Create an instance from an existing cube -```````````````````````````````````````` - -To create an instance from an existing cube, execute the following -command :: - - cubicweb-ctl create - -This command will create the configuration files of an instance in -``~/etc/cubicweb.d/``. -The tool ``cubicweb-ctl`` allows you to execute the command ``db-create`` -and ``db-init`` when you run ``create`` so that you can complete an -instance creation in a single command. - -If you decide not to execut those commands while ``cubicweb-ctl create``, -then you will have to execute them seperately(``cubicweb-ctl db-create``, -``cubicweb-ctl db-init`` ) otherwise your installation will not be complete -and you will not be able to launch your instance. - - -Creation of an instance from a new cube -``````````````````````````````````````` - -Create first your new cube cube :: - - cubicweb-ctl newcube - -This will create a new cube in ``/path/to/forest/cubicweb/cubes/`` -and then create an instance as explained just above. - - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/03-10-stdlib-schemas.en.txt --- a/doc/book/en/03-10-stdlib-schemas.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -.. -*- coding: utf-8 -*- - -Pre-defined schemas in the library ----------------------------------- - -The library defines a set of entities schemas that are required by the system -or commonly used in `LAX` applications. -Of course, you can extend those schemas if necessarry. - -System schemas -`````````````` -Those are defined in:: - - ./myapp/ginco/schemas/ - ./myapp/ginco/entities/ - -``schemas/`` defines the data model you will use in your application. -It allows you to describre the entities and the relations you will need. - -``entities/`` deifnes the methods you might need on the entities you -defined in your schema. - -The system entities available are: - -* `EUser`, system users -* `EGroup`, users groups -* `EEType`, entity type -* `ERType`, relation type - -* `State`, workflow state -* `Transition`, workflow transition -* `TrInfo`, record of a transition trafic for an entity - -* `EmailAddress`, email address, used by the system to send notifications - to the users and also used by others optionnals schemas - -* `EProperty`, used to configure the application -* `EPermission`, used to configure the security of the application - -* `Card`, generic documenting card -* `Bookmark`, an entity type used to allow a user to customize his links within - the application - - -Components in the library -````````````````````````` - -Those are defined in:: - - ./myapp/ginco-apps/ - -An application is based on several basic components. In the set of available -basic components we can find by example: - -* `ecomment`, provides an entity type for `Comment` allowing us to comment others - site's entities - -* `emailinglist`, provides an entity type for `Mailinglist` which groups informations - in a discussion list - -* `efile`, provides entity types for `File` et `Image` used to represent - files (text or binary) with additionnal informations such as MIME type or - encoding. - -* `elink`, provides an entity type for hypertext link (`Link`) - -* `eblog`, provides an entity type weblog (`Blog`) - -* `eperson`, provides an entity type for a person (`Person`) - -* `eaddressbook`, provides an entity type used to represent phone - numbers (`PhoneNumber`) and mailing address (`PostalAddress`) - -* `eclasstags`, categorization system based on tags (`Tag`) - -* `eclassfolders`, categorization system based on folders hierarchy in order - to create navigation sections (`Folder`) - -* `eemail`, archiving management for emails (`Email`, `Emailpart`, - `Emailthread`) - -* `ebasket`, basket management (`Basket`) allowing to group entities - -To declare the use of a component, once installed, add the name of the component -to the variable `__use__` in the file `__pkginfo__.py` of your own component. - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/03-11-definition-schema.en.txt --- a/doc/book/en/03-11-definition-schema.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,344 +0,0 @@ -.. -*- coding: utf-8 -*- - -Entity type definition ----------------------- - -An entity type is defined by a Python class which inherits `EntityType`. The -class name correponds to the type name. Then the content of the class contains -the description of attributes and relations for the defined entity type, -by example :: - - class Personne(EntityType): - """A person with the properties and the relations necessarry for my - application""" - - last_name = String(required=True, fulltextindexed=True) - first_name = String(required=True, fulltextindexed=True) - title = String(vocabulary=('M', 'Mme', 'Mlle')) - date_of_birth = Date() - works_for = SubjectRelation('Company', cardinality='?*') - -* the name of the Python attribute corresponds to the name of the attribute - or the relation in `LAX` application. - -* all built-in types are available: `String`, `Int`, `Float`, - `Boolean`, `Date`, `Datetime`, `Time`, `Byte`. - -* each entity has at least the following meta-relations: - - - `eid` (`Int`) - - - `creation_date` (`Datetime`) - - - `modification_date` (`Datetime`) - - - `created_by` (`EUser`) (which user created the entity) - - - `owned_by` (`EUser`) (who does the entity belongs to, by default the - creator but not necessarry and it could have multiple owners) - - - `is` (`EEType`) - - -* it is also possible to define relations of type object by using `ObjectRelation` - instead of `SubjectRelation` - -* the first argument of `SubjectRelation` and `ObjectRelation` gives respectively - the object/subject entity type of the relation. This could be: - - * a string corresponding to an entity type - - * a tuple of string correponding to multiple entities types - - * special string such as follows: - - - "**" : all types of entities - - "*" : all types of entities non meta - - "@" : all types of meta entities but not system entities (e.g. used for - the basis schema description) - -* it is possible to use the attribute `meta` to flag an entity type as a `meta` - (e.g. used to describe/categorize other entities) - -* optional properties for attributes and relations: - - - `description` : string describing an attribute or a relation. By default - this string will be used in the editing form of the entity, which means - that it is supposed to help the end-user and should be flagged by the - function `_` to be properly internationalized. - - - `constraints` : list of conditions/constraints that the relation needs to - satisfy (c.f. `Contraints`_) - - - `cardinality` : two characters string which specify the cardinality of the - relation. The first character defines the cardinality of the relation on - the subject, the second on the object of the relation. When a relation - has multiple possible subjects or objects, the cardinality applies to all - and not on a one to one basis (so it must be consistent...). The possible - values are inspired from regular expressions syntax: - - * `1`: 1..1 - * `?`: 0..1 - * `+`: 1..n - * `*`: 0..n - - - `meta` : boolean indicating that the relation is a meta-relation (false by - default) - -* optionnal properties for attributes: - - - `required` : boolean indicating if the attribute is required (false by default) - - - `unique` : boolean indicating if the value of the attribute has to be unique - or not within all entities of the same type (false by default) - - - `indexed` : boolean indicating if an index needs to be created for this - attribute in the database (false by default). This is usefull only if - you know that you will have to run numerous searches on the value of this - attribute. - - - `default` : default value of the attribute. In case of date types, the values - which could be used correpond to the RQL keywords `TODAY` and `NOW`. - - - `vocabulary` : specify static possible values of an attribute - -* optionnal properties of type `String`: - - - `fulltextindexed` : boolean indicating if the attribute is part of - the full text index (false by default) (*applicable on the type `Byte` - as well*) - - - `internationalizable` : boolean indicating if the value of the attribute - is internationalizable (false by default) - - - `maxsize` : integer providing the maximum size of the string (no limit by default) - -* optionnal properties for relations: - - - `composite` : string indicating that the subject (composite == 'subject') - is composed of the objects of the relations. For the opposite case (when - the object is composed of the subjects of the relation), we just need - to set 'object' as the value. The composition implies that when the relation - is deleted (so when the composite is deleted), the composed are also deleted. - [PAS CLAIR] - -Contraints -`````````` -By default, the available constraints types are: - -* `SizeConstraint` : allows to specify a minimum and/or maximum size on - string (generic case of `maxsize`) - -* `BoundConstraint` : allows to specify a minimum and/or maximum value on - numeric types - -* `UniqueConstraint` : identical to "unique=True" - -* `StaticVocabularyConstraint` : identical to "vocabulary=(...)" - -* `RQLConstraint` : allows to specify a RQL query that needs to be satisfied - by the subject and/or the object of the relation. In this query the variables - `S` and `O` are reserved for the entities subject and object of the - relation. - -* `RQLVocabularyConstraint` : similar to the previous type of constraint except - that it does not express a "strong" constraint, which means it is only used to - restrict the values listed in the drop-down menu of editing form, but it does - not prevent another entity to be selected - [PAS CLAIR] - - -Relation type definition ------------------------- - -A relation is defined by a Python class heriting `RelationType`. The name -of the class corresponds to the name of the type. The class then contains -a description of the properties of this type of relation, as well as a -string for the subject and a string for the object. This allows to create -new definition of associated relations, (so that the class can have the -definition properties from the relation)[PAS CLAIR] by example :: - - class locked_by(RelationType): - """relation on all entities indicating that they are locked""" - inlined = True - cardinality = '?*' - subject = '*' - object = 'EUser' - -In addition to the permissions, the own properties of the relation types -(shared also by all definition of relation of this type) are: - - -* `inlined` : boolean handling the physical optimization for archiving - the relation in the subject entity table, instead of creating a specific - table for the relation. This applies to the relation when the cardinality - of subject->relation->object is 0..1 ('?') or 1..1 ('1') - -* `symetric` : boolean indication that the relation is symetrical, which - means `X relation Y` implies `Y relation X` - -In the case of simultaneous relations definitions, `subject` and `object` -can both be equal to the value of the first argument of `SubjectRelation` -and `ObjectRelation`. - -When a relation is not inlined and not symetrical, and it does not require -specific permissions, its definition (by using `SubjectRelation` and -`ObjectRelation`) is all we need. - -Permissions definition ----------------------- - -Define permissions is set through to the attribute `permissions` of entities and -relations types. It defines a dictionnary where the keys are the access types -(action), and the values are the authorized groups or expressions. - -For an entity type, the possible actions are `read`, `add`, `update` and -`delete`. - -For a relation type, the possible actions are `read`, `add`, and `delete`. - -For each access type, a tuple indicates the name of the authorized groups and/or -one or multiple RQL expressions to satisfy to grant access. The access is -provided once the user is in the listed groups or one of the RQL condition is -satisfied. - -The standard groups are: - -* `guests` - -* `users` - -* `managers` - -* `owners` : virtual group corresponding to the entity's owner. - This can only be used for the actions `update` and `delete` of an entity - type. - -It is also possible to use specific groups if they are define in the precreate -of the application (``migration/precreate.py``). - -Use of RQL expression for writing rights -```````````````````````````````````````` -It is possible to define RQL expression to provide update permission -(`add`, `delete` and `update`) on relation and entity types. - -RQL expression for entity type permission: - -* you have to use the class `ERQLExpression` - -* the used expression corresponds to the WHERE statement of an RQL query - -* in this expression, the variables X and U are pre-defined references - respectively on the current entity (on which the action is verified) and - on the user who send the request - -* it is possible to use, in this expression, a special relation - "has__permission" where the subject is the user and the - object is a any variable, meaning that the user needs to have - permission to execute the action on the entities related - to this variable - -For RQL expressions on a relation type, the principles are the same except -for the following: - -* you have to use the class `RQLExpression` in the case of a non-final relation - [WHAT IS A NON FINALE RELATION] - -* in the expression, the variables S, O and U are pre-defined references - to respectively the subject and the object of the current relation (on - which the action is being verified) and the user who executed the query - -* we can also defined rights on attributes of an entity (non-final relation), - knowing that: - - - to defines RQL expression, we have to use the class `ERQLExpression` - in which X represents the entity the attribute belongs to - - - the permissions `add` and `delete` are equivalent. Only `add`/`read` - are actually taken in consideration. - - - -In addition to thatm the entity type `EPermission` from the standard library -allow to build very complex and dynamic security architecture. The schema of -this entity type is as follow: :: - - class EPermission(MetaEntityType): - """entity type that may be used to construct some advanced security configuration - """ - name = String(required=True, indexed=True, internationalizable=True, maxsize=100) - require_group = SubjectRelation('EGroup', cardinality='+*', - description=_('groups to which the permission is granted')) - require_state = SubjectRelation('State', - description=_("entity'state in which the permission is applyable")) - # can be used on any entity - require_permission = ObjectRelation('**', cardinality='*1', composite='subject', - description=_("link a permission to the entity. This " - "permission should be used in the security " - "definition of the entity's type to be useful.")) - - -Example of configuration :: - - ... - - class Version(EntityType): - """a version is defining the content of a particular project's release""" - - permissions = {'read': ('managers', 'users', 'guests',), - 'update': ('managers', 'logilab', 'owners',), - 'delete': ('managers', ), - 'add': ('managers', 'logilab', - ERQLExpression('X version_of PROJ, U in_group G,' - 'PROJ require_permission P, P name "add_version",' - 'P require_group G'),)} - - ... - - class version_of(RelationType): - """link a version to its project. A version is necessarily linked to one and only one project. - """ - permissions = {'read': ('managers', 'users', 'guests',), - 'delete': ('managers', ), - 'add': ('managers', 'logilab', - RRQLExpression('O require_permission P, P name "add_version",' - 'U in_group G, P require_group G'),) - } - inlined = True - -This configuration assumes/indicates [???] that an entity `EPermission` named -"add_version" can be associated to a project and provides rights to create -new versions on this project to specific groups. It is important to notice that: - -* in such case, we have to protect both the entity type "Version" and the relation - associating a version to a project ("version_of") - -* because of the genricity of the entity type `EPermission`, we have to execute - a unification with the groups and/or the states if necessary in the expression - ("U in_group G, P require_group G" in the above example) - - -Use of RQL expression for reading rights -```````````````````````````````````````` - -The principles are the same but with the following restrictions: - -* we can not [??] `RRQLExpression` on relation types for reading - -* special relations "has__permission" can not be used - - -Note on the use of RQL expression for `add` permission -`````````````````````````````````````````````````````` -Potentially, the use of an RQL expression to add an entity or a relation -can cause problems for the user interface, because if the expression uses -the entity or the relation to create, then we are not able to verify the -permissions before we actually add the entity (please note that this is -not a problem for the RQL server at all, because the permissions checks are -done after the creation). In such case, the permission checks methods -(check_perm, has_perm) can indicate that the user is not allowed to create -this entity but can obtain the permission. -To compensate this problem, it is usually necessary, for such case, -to use an action that reflects the schema permissions but which enables -to check properly the permissions so that it would show up if necessary. -[PAS CLAIR] diff -r 3159772915c4 -r d5acef862c58 doc/book/en/04-00-define-schema.en.txt --- a/doc/book/en/04-00-define-schema.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -.. -*- coding: utf-8 -*- - -Data model definition (*schema*) -================================ - -The schema is the core piece of a `CubicWeb` application as it defines -the data model handled. It is based on entities types already defined -in the `CubicWeb` standard library and others, more specific, we would -expect to find in one or more Python files under the `schema` directory. - -At this point, it is important to make clear the difference between -relation type and relation definition: a relation type is only a relation -name with potentially other additionnal properties (see XXXX), whereas a -relation definition is a complete triplet -" ". -A relation type could have been implied if none is related to a -relation definition of the schema. - - -.. include:: 04-01-schema-stdlib.en.txt -.. include:: 04-02-schema-definition.en.txt - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/04-01-schema-stdlib.en.txt --- a/doc/book/en/04-01-schema-stdlib.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -.. -*- coding: utf-8 -*- - -Pre-defined schemas in the library ----------------------------------- - -The library defines a set of entities schemas that are required by the system -or commonly used in `CubicWeb` applications. -Of course, you can extend those schemas if necessarry. - - -System schemas -`````````````` -The system entities available are : - -* `EUser`, system users -* `EGroup`, users groups -* `EEType`, entity type -* `ERType`, relation type - -* `State`, workflow state -* `Transition`, workflow transition -* `TrInfo`, record of a transition trafic for an entity - -* `EmailAddress`, email address, used by the system to send notifications - to the users and also used by others optionnals schemas - -* `EProperty`, used to configure the application -* `EPermission`, used to configure the security of the application - -* `Card`, generic documenting card -* `Bookmark`, an entity type used to allow a user to customize his links within - the application - -Cubes in the library -```````````````````` - -An application is based on several basic cubes. In the set of available -basic cubes we can find by example : - -* `comment`, provides an entity type for `Comment` allowing us to comment others - site's entities - -* `mailinglist`, provides an entity type for `Mailinglist` which groups informations - in a discussion list - -* `file`, provides entity types for `File` et `Image` used to represent - files (text or binary) with additionnal informations such as MIME type or - encoding. - -* `link`, provides an entity type for hypertext link (`Link`) - -* `blog`, provides an entity type weblog (`Blog`) - -* `person`, provides an entity type for a person (`Person`) - -* `addressbook`, provides an entity type used to represent phone - numbers (`PhoneNumber`) and mailing address (`PostalAddress`) - -* `classtags`, categorization system based on tags (`Tag`) - -* `classfolders`, categorization system based on folders hierarchy in order - to create navigation sections (`Folder`) - -* `email`, archiving management for emails (`Email`, `Emailpart`, - `Emailthread`) - -* `basket`, basket management (`Basket`) allowing to group entities - -To declare the use of a component, once installed, add the name of the component -to the variable `__use__` in the file `__pkginfo__.py` of your own component. - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/04-02-schema-definition.en.txt --- a/doc/book/en/04-02-schema-definition.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,379 +0,0 @@ -.. -*- coding: utf-8 -*- - -Entity type definition ----------------------- - -An entity type is defined by a Python class which inherits `EntityType`. The -class name correponds to the type name. Then the content of the class contains -the description of attributes and relations for the defined entity type, -by example :: - - class Personne(EntityType): - """A person with the properties and the relations necessarry for my - application""" - - last_name = String(required=True, fulltextindexed=True) - first_name = String(required=True, fulltextindexed=True) - title = String(vocabulary=('M', 'Mme', 'Mlle')) - date_of_birth = Date() - works_for = SubjectRelation('Company', cardinality='?*') - -* the name of the Python attribute corresponds to the name of the attribute - or the relation in `CubicWeb` application. - -* all built-in types are available : `String`, `Int`, `Float`, - `Boolean`, `Date`, `Datetime`, `Time`, `Byte`. - -* each entity type has at least the following meta-relations : - - - `eid` (`Int`) - - - `creation_date` (`Datetime`) - - - `modification_date` (`Datetime`) - - - `created_by` (`EUser`) (which user created the entity) - - - `owned_by` (`EUser`) (who does the entity belongs to, by default the - creator but not necessarry and it could have multiple owners) - - - `is` (`EEType`) - - -* it is also possible to define relations of type object by using `ObjectRelation` - instead of `SubjectRelation` - -* the first argument of `SubjectRelation` and `ObjectRelation` gives respectively - the object/subject entity type of the relation. This could be : - - * a string corresponding to an entity type - - * a tuple of string correponding to multiple entities types - - * special string such as follows : - - - "**" : all types of entities - - "*" : all types of non-meta entities - - "@" : all types of meta entities but not system entities (e.g. used for - the basic schema description) - -* it is possible to use the attribute `meta` to flag an entity type as a `meta` - (e.g. used to describe/categorize other entities) - -* optional properties for attributes and relations : - - - `description` : string describing an attribute or a relation. By default - this string will be used in the editing form of the entity, which means - that it is supposed to help the end-user and should be flagged by the - function `_` to be properly internationalized. - - - `constraints` : list of conditions/constraints that the relation needs to - satisfy (c.f. `Contraints`_) - - - `cardinality` : two characters string which specify the cardinality of the - relation. The first character defines the cardinality of the relation on - the subject, the second on the object of the relation. When a relation - has multiple possible subjects or objects, the cardinality applies to all - and not on a one to one basis (so it must be consistent...). The possible - values are inspired from regular expressions syntax : - - * `1`: 1..1 - * `?`: 0..1 - * `+`: 1..n - * `*`: 0..n - - - `meta` : boolean indicating that the relation is a meta-relation (false by - default) - -* optionnal properties for attributes : - - - `required` : boolean indicating if the attribute is required (false by default) - - - `unique` : boolean indicating if the value of the attribute has to be unique - or not within all entities of the same type (false by default) - - - `indexed` : boolean indicating if an index needs to be created for this - attribute in the database (false by default). This is usefull only if - you know that you will have to run numerous searches on the value of this - attribute. - - - `default` : default value of the attribute. In case of date types, the values - which could be used correpond to the RQL keywords `TODAY` and `NOW`. - - - `vocabulary` : specify static possible values of an attribute - -* optionnal properties of type `String` : - - - `fulltextindexed` : boolean indicating if the attribute is part of - the full text index (false by default) (*applicable on the type `Byte` - as well*) - - - `internationalizable` : boolean indicating if the value of the attribute - is internationalizable (false by default) - - - `maxsize` : integer providing the maximum size of the string (no limit by default) - -* optionnal properties for relations : - - - `composite` : string indicating that the subject (composite == 'subject') - is composed of the objects of the relations. For the opposite case (when - the object is composed of the subjects of the relation), we just need - to set 'object' as the value. The composition implies that when the relation - is deleted (so when the composite is deleted), the composed are also deleted. - -Contraints -`````````` -By default, the available constraints types are : - -* `SizeConstraint` : allows to specify a minimum and/or maximum size on - string (generic case of `maxsize`) - -* `BoundConstraint` : allows to specify a minimum and/or maximum value on - numeric types - -* `UniqueConstraint` : identical to "unique=True" - -* `StaticVocabularyConstraint` : identical to "vocabulary=(...)" - -* `RQLConstraint` : allows to specify a RQL query that needs to be satisfied - by the subject and/or the object of the relation. In this query the variables - `S` and `O` are reserved for the entities subject and object of the - relation. - -* `RQLVocabularyConstraint` : similar to the previous type of constraint except - that it does not express a "strong" constraint, which means it is only used to - restrict the values listed in the drop-down menu of editing form, but it does - not prevent another entity to be selected - - -Relation definition -------------------- - -XXX add note about defining relation type / definition - -A relation is defined by a Python class heriting `RelationType`. The name -of the class corresponds to the name of the type. The class then contains -a description of the properties of this type of relation, and could as well -contains a string for the subject and a string for the object. This allows to create -new definition of associated relations, (so that the class can have the -definition properties from the relation) by example :: - - class locked_by(RelationType): - """relation on all entities indicating that they are locked""" - inlined = True - cardinality = '?*' - subject = '*' - object = 'EUser' - -In addition to the permissions, the properties of the relation types -(shared also by all definition of relation of this type) are : - - -* `inlined` : boolean handling the physical optimization for archiving - the relation in the subject entity table, instead of creating a specific - table for the relation. This applies to the relation when the cardinality - of subject->relation->object is 0..1 (`?`) or 1..1 (`1`) - -* `symetric` : boolean indication that the relation is symetrical, which - means `X relation Y` implies `Y relation X` - -In the case of simultaneous relations definitions, `subject` and `object` -can both be equal to the value of the first argument of `SubjectRelation` -and `ObjectRelation`. - -When a relation is not inlined and not symetrical, and it does not require -specific permissions, its definition (by using `SubjectRelation` and -`ObjectRelation`) is all we need. - - -The security model ------------------- - -Le modèle de sécurité de CubicWeb est un modèle fondé sur des `Access -Control List`. Les notions sont les suivantes : - -* utilisateurs et groupes d'utilisateurs -* un utilisateur appartient à au moins un groupe -* droits (lire, modifier, créer, supprimer) -* les droits sont attribués aux groupes (et non aux utilisateurs) - -Pour CubicWeb plus spécifiquement : - -* on associe les droits au niveau des schemas d'entites / relations - -* pour chaque type d'entité, on distingue les droits de lecture, - ajout, modification et suppression - -* pour chaque type de relation, on distingue les droits de lecture, - ajout et suppression (on ne peut pas modifer une relation) - -* les groupes de base sont : Administrateurs, Utilisateurs, Invités - -* les utilisateurs font par défaut parti du groupe Utilisateurs - -* on a un groupe virtuel "Utilisateurs Propriétaires", auquel on peut - associer uniquement les droits de suppression et de modification - -* on ne peut pas mettre d'utilisateurs dans ce groupe, ils y sont - ajoutés implicitement dans le contexte des objets dont ils sont - propriétaires - -* les droits de ce groupe ne sont vérifiés que sur - modification / suppression si tous les autres groupes auxquels - l'utilisateur appartient se sont vu interdir l'accès - - -Permissions definition -`````````````````````` - -Define permissions is set through to the attribute `permissions` of entities and -relations types. It defines a dictionnary where the keys are the access types -(action), and the values are the authorized groups or expressions. - -For an entity type, the possible actions are `read`, `add`, `update` and -`delete`. - -For a relation type, the possible actions are `read`, `add`, and `delete`. - -For each access type, a tuple indicates the name of the authorized groups and/or -one or multiple RQL expressions to satisfy to grant access. The access is -provided once the user is in the listed groups or one of the RQL condition is -satisfied. - -The standard groups are : - -* `guests` - -* `users` - -* `managers` - -* `owners` : virtual group corresponding to the entity's owner. - This can only be used for the actions `update` and `delete` of an entity - type. - -It is also possible to use specific groups if they are defined in the precreate -of the cube (``migration/precreate.py``). - - -Use of RQL expression for writing rights -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -It is possible to define RQL expression to provide update permission -(`add`, `delete` and `update`) on relation and entity types. - -RQL expression for entity type permission : - -* you have to use the class `ERQLExpression` - -* the used expression corresponds to the WHERE statement of an RQL query - -* in this expression, the variables X and U are pre-defined references - respectively on the current entity (on which the action is verified) and - on the user who send the request - -* it is possible to use, in this expression, a special relation - "has__permission" where the subject is the user and the - object is a any variable, meaning that the user needs to have - permission to execute the action on the entities related - to this variable - -For RQL expressions on a relation type, the principles are the same except -for the following : - -* you have to use the class `RQLExpression` in the case of a non-final relation - -* in the expression, the variables S, O and U are pre-defined references - to respectively the subject and the object of the current relation (on - which the action is being verified) and the user who executed the query - -* we can also defined rights on attributes of an entity (non-final relation), - knowing that : - - - to defines RQL expression, we have to use the class `ERQLExpression` - in which X represents the entity the attribute belongs to - - - the permissions `add` and `delete` are equivalent. Only `add`/`read` - are actually taken in consideration. - -In addition to that the entity type `EPermission` from the standard library -allow to build very complex and dynamic security architecture. The schema of -this entity type is as follow : :: - - class EPermission(MetaEntityType): - """entity type that may be used to construct some advanced security configuration - """ - name = String(required=True, indexed=True, internationalizable=True, maxsize=100) - require_group = SubjectRelation('EGroup', cardinality='+*', - description=_('groups to which the permission is granted')) - require_state = SubjectRelation('State', - description=_("entity'state in which the permission is applyable")) - # can be used on any entity - require_permission = ObjectRelation('**', cardinality='*1', composite='subject', - description=_("link a permission to the entity. This " - "permission should be used in the security " - "definition of the entity's type to be useful.")) - - -Example of configuration :: - - - ... - - class Version(EntityType): - """a version is defining the content of a particular project's release""" - - permissions = {'read': ('managers', 'users', 'guests',), - 'update': ('managers', 'logilab', 'owners',), - 'delete': ('managers', ), - 'add': ('managers', 'logilab', - ERQLExpression('X version_of PROJ, U in_group G,' - 'PROJ require_permission P, P name "add_version",' - 'P require_group G'),)} - - ... - - class version_of(RelationType): - """link a version to its project. A version is necessarily linked to one and only one project. - """ - permissions = {'read': ('managers', 'users', 'guests',), - 'delete': ('managers', ), - 'add': ('managers', 'logilab', - RRQLExpression('O require_permission P, P name "add_version",' - 'U in_group G, P require_group G'),) - } - inlined = True - -This configuration indicates that an entity `EPermission` named -"add_version" can be associated to a project and provides rights to create -new versions on this project to specific groups. It is important to notice that : - -* in such case, we have to protect both the entity type "Version" and the relation - associating a version to a project ("version_of") - -* because of the genricity of the entity type `EPermission`, we have to execute - a unification with the groups and/or the states if necessary in the expression - ("U in_group G, P require_group G" in the above example) - -Use of RQL expression for reading rights -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The principles are the same but with the following restrictions : - -* we can not use `RRQLExpression` on relation types for reading - -* special relations "has__permission" can not be used - - -Note on the use of RQL expression for `add` permission -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Potentially, the use of an RQL expression to add an entity or a relation -can cause problems for the user interface, because if the expression uses -the entity or the relation to create, then we are not able to verify the -permissions before we actually add the entity (please note that this is -not a problem for the RQL server at all, because the permissions checks are -done after the creation). In such case, the permission check methods -(check_perm, has_perm) can indicate that the user is not allowed to create -this entity but can obtain the permission. -To compensate this problem, it is usually necessary, for such case, -to use an action that reflects the schema permissions but which enables -to check properly the permissions so that it would show up if necessary. diff -r 3159772915c4 -r d5acef862c58 doc/book/en/05-00-define-views.en.txt --- a/doc/book/en/05-00-define-views.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,238 +0,0 @@ -.. -*- coding: utf-8 -*- - -.. _DefinitionVues: - -Views definition -================ - -Basic class for views ---------------------- - -Class `View` (`cubicweb.common.view`) -````````````````````````````````````` - -A view writes in its output exit thanks to its attribute `w` (`UStreamIO`). - -The basic interface for views is as follows: - -* `dispatch(**context)`, render the view by calling `call` or - `cell_call` depending on the given parameters -* `call(**kwargs)`, call the view for a complete result set or null -* `cell_call(row, col, **kwargs)`, call the view for a given cell of a result set -* `url()`, returns the URL enabling us to get the view with the current - result set -* `view(__vid, rset, __fallback_vid=None, **kwargs)`, call the view of identifier - `__vid` on the given result set. It is possible to give a view identifier - of fallback that will be used if the view requested is not applicable to the - result set - -* `wview(__vid, rset, __fallback_vid=None, **kwargs)`, similar to `view` except - the flow is automatically passed in the parameters - -* `html_headers()`, returns a list of HTML headers to set by the main template - -* `page_title()`, returns the title to use in the HTML header `title` - -* `creator(eid)`, returns the eid and the login of the entity creator of the entity - having the eid given in the parameter - -Other basic classes: - -* `EntityView`, view applying to lines or cell containing an entity (e.g. an eid) -* `StartupView`, start view that does not require a result set to apply to -* `AnyRsetView`, view applied to any result set - - -The selection view principle ----------------------------- - -A view includes : - -- an identifier (all objects in `LAX` are entered in a registry - and this identifier will be used as a key) - -- a filter to select the resulsets it can be applied to - - -For a given identifier, multiple views can be defined. `CubicWeb` uses -a selector which computes scores so that it can identify and select the -best view to apply in context. The selector library is in -``cubicweb.common.selector`` and a library of the methods used to -compute scores is in ``cubicweb.vregistry.vreq``. - - -`CubicWeb` provides a lot of standard views, for a complete list, you -will have to read the code in directory ``cubicweb/web/views/`` (XXX -improve doc). - -For example, the view named ``primary`` is the one used to display -a single entity. - -If you want to change the way a ``BlogEntry`` is displayed, just -override the view ``primary`` in ``BlogDemo/views.py`` :: - - 01. from ginco.web.views import baseviews - 02. - 03. class BlogEntryPrimaryView(baseviews.PrimaryView): - 04. - 05. accepts = ('BlogEntry',) - 06. - 07. def cell_call(self, row, col): - 08. entity = self.entity(row, col) - 09. self.w(u'

%s

' % entity.title) - 10. self.w(u'

published on %s in category %s

' % \ - 11. (entity.publish_date.strftime('%Y-%m-%d'), entity.category)) - 12. self.w(u'

%s

' % entity.text) - -The above source code defines a new primary view (`line 03`) for -``BlogEntry`` (`line 05`). - -Since views are applied to resultsets and resulsets can be tables of -data, it is needed to recover the entity from its (row,col) -coordinates (`line 08`). We will get to this in more detail later. - -The view has a ``self.w()`` method that is used to output data. Here `lines -09-12` output HTML tags and values of the entity's attributes. - -When displaying same blog entry as before, you will notice that the -page is now looking much nicer. - -.. image:: images/lax-book.09-new-view-blogentry.en.png - :alt: blog entries now look much nicer - -Let us now improve the primary view of a blog :: - - 01. class BlogPrimaryView(baseviews.PrimaryView): - 02. - 03. accepts = ('Blog',) - 04. - 05. def cell_call(self, row, col): - 06. entity = self.entity(row, col) - 07. self.w(u'

%s

' % entity.title) - 08. self.w(u'

%s

' % entity.description) - 09. rset = self.req.execute('Any E WHERE E entry_of B, B eid "%s"' % entity.eid) - 10. self.wview('primary', rset) - -In the above source code, `lines 01-08` are similar to the previous -view we defined. - -At `line 09`, a simple request in made to build a resultset with all -the entities linked to the current ``Blog`` entity by the relationship -``entry_of``. The part of the framework handling the request knows -about the schema and infer that such entities have to be of the -``BlogEntry`` kind and retrieves them. - -The request returns a selection of data called a resultset. At -`line 10` the view 'primary' is applied to this resultset to output -HTML. - -**This is to be compared to interfaces and protocols in object-oriented -languages. Applying a given view to all the entities of a resultset only -requires the availability, for each entity of this resultset, of a -view with that name that can accepts the entity.** - -Assuming we added entries to the blog titled `MyLife`, displaying it -now allows to read its description and all its entries. - -.. image:: images/lax-book.10-blog-with-two-entries.en.png - :alt: a blog and all its entries - -**Before we move forward, remember that the selection/view principle is -at the core of `CubicWeb`. Everywhere in the engine, data is requested -using the RQL language, then HTML/XML/text/PNG is output by applying a -view to the resultset returned by the query. That is where most of the -flexibility comes from.** - -[WRITE ME] - -* implementing interfaces, calendar for blog entries -* show that a calendar view can export data to ical - -We will implement the cubicwweb.interfaces.ICalendarable interfaces on -entities.BloEntry and apply the OneMonthCalendar and iCalendar views -to resultsets like "Any E WHERE E is BlogEntry" - -* create view "blogentry table" with title, publish_date, category - -We will show that by default the view that displays -"Any E,D,C WHERE E publish_date D, E category C" is the table view. -Of course, the same can be obtained by calling -self.wview('table',rset) - -* in view blog, select blogentries and apply view "blogentry table" -* demo ajax by filtering blogentry table on category - -we did the same with 'primary', but with tables we can turn on filters -and show that ajax comes for free. -[FILLME] - - -Templates ---------- - -*Templates* are specific view that does not depend on a result set. The basic -class `Template` (`cubicweb.common.view`) is derived from the class `View`. - -To build a HTML page, a *main template* is used. In general, the template of -identifier `main` is the one (it is not used in case an error is raised or for -the login form by example). This template uses other templates in addition -to the views which depends on the content to generate the HTML page to return. - -A *template* is responsible for: - -1. executing RQL query of data to render if necessarry -2. identifying the view to use to render data if it is not specified -3. composing the HTML page to return - - -The default main template (`cubicweb.web.views.basetemplates.TheMainTemplate`) ------------------------------------------------------------------------------- - -The default main template build the page based on the following pattern: - -.. image:: images/main_template_layout.png - -The rectangle containing `view.dispathc()` represents the area where the content -view has to be displayed. The others represents sub-templates called to complete -the page. A default implementation of those is provided in -`cubicweb.views.basetemplates`. You can, of course, overload those sub-templates -to implement your own customization of the HTML page. - -We can also control certain aspects of the main template thanks to the following -forms parameters: - -* `__notemplate`, if present (whatever the value assigned), only the content view - is returned -* `__force_display`, if present and its value is not null, no navigation - whatever the number of entities to display -* `__method`, if the result set to render contains only one entity and this - parameter is set, it refers to a method to call on the entity by passing it - the dictionnary of the forms parameters, before going the classic way (through - step 1 and 2 described juste above) - -.. include:: 05-01-views-stdlib.en.txt - - -XML views, binaries... ----------------------- -For the views generating other formats that HTML (an image generated dynamically -by example), and which can not usually be included in the HTML page generated -by the main template (see above), you have to: - -* set the atribute `templatable` of the class to `False` -* set, through the attribute `content_type` of the class, the MIME type generated - by the view to `application/octet-stream` - -For the views dedicated to binary content creation (an image dynamically generated -by example), we have to set the attribute `binary` of the class to `True` (which -implies that `templateable == False`, so that the attribute `w` of the view could be -replaced by a binary flow instead of unicode). - -(X)HTML tricks to apply ------------------------ - -Some web browser (Firefox by example) are not happy with empty `
` -(by empty we mean that there is no content in the tag, but there -could be attributes), so we should always use `
` even if -it is empty and not use `
`. - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/05-01-views-stdlib.en.txt --- a/doc/book/en/05-01-views-stdlib.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -.. -*- coding: utf-8 -*- - -Predefined views in the library -------------------------------- - -A certain number of views are used to build the web interface, which apply -to one or more entities. Their identifier is what distinguish them from -each others and the main ones are: - -:primary: - primary view of an entity, this is the view called by default when a single - entity is in the result set and needs to be displayed. This view is supposed - to render a maximum of informations about the entity. -:secondary: - secondary view of an entity. By default it renders the two first attributes - of the entity as a clickable link redirecting to the primary view. -:oneline: - similar to the `secondary` view, but called when we want the view to stand - on a single line, or just get a brief view. By default this view uses the - parameter `MAX_LINE_CHAR` to control the result size. -:text: - similar to the `oneline` view, but should not contain HTML. -:incontext, outofcontext: - similar to the `secondary` view, but called when an entity is considered - as in or out of context. By default it respectively returns the result of - `textincontext` and `textoutofcontext` wrapped in a link leading to - the primary view of the entity. -:textincontext, textoutofcontext: - similar to the `text` view, but called is an entity is considered out or - in context. By default it returns respectively the result of the - methods `.dc_title` and `.dc_long_title` of the entity. -:list: - creates a HTML list (`
    `) and call the view `listitem` for each entity - of the result set -:listitem: - redirects by default to the `outofcontext` view -:rss: - creates a RSS/XML view and call the view `rssitem` for each entity of - the result set -:rssitem: - create a RSS/XML view for each entity based on the results of the dunblin core - methods of the entity (`dc_*`) - -Start view: - -:index: - home page -:schema: - display the schema of the application - -Special views: - -:noresult: - called if the result set is empty -:finall: - display the value of a cell without trasnformation (in case of a non final - entity, we see the eid). Applicable on any result set. -:table: - creates a HTML table (``) and call the view `cell` for each cell of - the result set. Applicable on any result set. -:cell: - by default redirects to the `final` view if this is a final entity or - `outofcontext` view otherwise -:null: - view always applicable and which does not return anything diff -r 3159772915c4 -r d5acef862c58 doc/book/en/06-00-define-workflows.en.txt --- a/doc/book/en/06-00-define-workflows.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -.. -*- coding: utf-8 -*- - -Workflow definition -====================== - -On peut mettre une condition rql ou/et un groupe auquel doit appartenir l'utilisateur. - -Si on met à la fois un(ou plusieurs) groupe et une condition RQL, il faut que les deux soient respectés. - -Si on met plusieurs groupes, il faut que l'utilisateur soit dans un des groupes. - -Pour la condition RQL sur une transition, on peut y mettre les substitutions suivantes : - -* `%(eid)s`, eid de l'objet -* `%(ueid)s`, eid de l'utilisateur qui fait la requête -* `%(seid)s`, eid de l'état courant de l'objet - -Dans le script de création d'un workflow, penser à mettre `_()` autour des noms d'états et de transitions -pour que ceux si soient pris en compte par les scripts de gestion des catalogues i18n. - -General -------- - -A workflow can be defined in a `LAX` application thanks to the system -entities ``State`` and ``Transition``. Those are defined within all -LAX application and can be set-up through the main administrator interface. - -Once your schema is defined, you can start creating the set of states and -the required transitions for your applications entities. - -You first need to define the states and then the transitions between those -to complete your workflow. - -A ``State`` defines the status of an entity. While creating a new state, -you will be first given the option to select the entity type the state -can be applied to. By choosing ``Apply``, a new section will be displayed -in the editing screen to enable you to add relation to the state you are -creating. - -A ``Transition`` is also based on an entity type it can be applied to. -By choosing ``Apply``, a new section will be displayed in the editing -screen to enable you to add relation to the transition you are -creating. - -At the transition level you will also define the group of user which can -aplly this transition to an object. - - -Example of a simple workflow ----------------------------- - -Please see the tutorial to view and example of a simple workflow. - - -[Create a simple workflow for BlogDemo, to have a moderator approve new blog -entry to be published. This implies, specify a dedicated group of blog -moderator as well as hide the view of a blog entry to the user until -it reaches the state published] - -Set-up a workflow ------------------ - -Before starting, make sure you refresh your mind by reading [link to -definition_workflow chapter]. - -We want to create a workflow to control the quality of the BlogEntry -submitted on your application. When a BlogEntry is created by a user -its state should be `submitted`. To be visible to all, it needs to -be in the state `published`. To move from `submitted` to `published` -we need a transition that we can name `approve_blogentry`. - -We do not want every user to be allowed to change the state of a -BlogEntry. We need to define a group of user, `moderators`, and -this group will have appropriate permissions to approve BlogEntry -to be published and visible to all. - -There are two ways to create a workflow, form the user interface, -and also by defining it in ``migration/postcreate.py``. This script -is executed each time a new ``./bin/laxctl db-init`` is done. -If you create the states and transitions through the user interface -this means that next time you will need to initialize the database -you will have to re-create all the entities. -We strongly recommand you create the workflow in ``migration\postcreate.py`` -and we will now show you how. -The user interface would only be a reference for you to view the states -and transitions but is not the appropriate interface to define your -application workflow. - -Update the schema -~~~~~~~~~~~~~~~~~ -To enable a BlogEntry to have a State, we have to define a relation -``in_state`` in the schema of BlogEntry. Please do as follows, add -the line ``in_state (...)``:: - - class BlogEntry(EntityType): - title = String(maxsize=100, required=True) - publish_date = Date(default='TODAY') - text_format = String(meta=True, internationalizable=True, maxsize=50, - default='text/rest', constraints=[format_constraint]) - text = String(fulltextindexed=True) - category = String(vocabulary=('important','business')) - entry_of = SubjectRelation('Blog', cardinality='?*') - in_state = SubjectRelation('State', cardinality='1*') - -As you updated the schema, you will have re-execute ``./bin/laxctl db-init`` -to initialize the database and migrate your existing entities. -[WRITE ABOUT MIGRATION] - -Create states, transitions and group permissions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -At the time the ``postcreate.py`` script is executed, several methods -can be used. They are all defined in the ``class ServerMigrationHelper``. -We will only discuss the method we use to create a wrokflow here. - -To define our workflow for BlogDemo, please add the following lines -to ``migration/postcreate.py``:: - - _ = unicode - - moderators = add_entity('EGroup', name=u"moderators") - - submitted = add_state(_('submitted'), 'BlogEntry', initial=True) - published = add_state(_('published'), 'BlogEntry') - - add_transition(_('approve_blogentry'), 'BlogEntry', (submitted,), published, ('moderators', 'managers'),) - - checkpoint() - -``add_entity`` is used here to define the new group of users that we -need to define the transitions, `moderators`. -If this group required by the transition is not defined before the -transition is created, it will not create the relation `transition -require the group moderator`. - -``add_state`` expects as the first argument the name of the state you are -willing to create, then the entity type on which the state can be applied, -and an optionnal argument to set if the state is the initial state -of the entity type or not. - -``add_transition`` expects as the first argument the name of the -transition, then the entity type on which we can apply the transition, -then the list of possible initial states from which the transition -can be applied, the target state of the transition, and the permissions -(e.g. list of the groups of users who can apply the transition). - -.. image:: images/lax-book.03-transitions-view.en.png - -You can now notice that in the actions box of a BlogEntry, the state -is now listed as well as the possible transitions from this state -defined by the workflow. This transition, as defined in the workflow, -will only being displayed for the users belonging to the group -moderators of managers. - - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/07-00-data-as-objects.en.txt --- a/doc/book/en/07-00-data-as-objects.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -.. -*- coding: utf-8 -*- - - -Manipulation des données stockées -================================= - -Les classes `Entity` et `AnyEntity` ------------------------------------ -Pour fournir un comportement spécifique à un type d'entité, il suffit de définir -une classe héritant de la class `ginco.entities.AnyEntity`. En général il faut -définir ces classes dans un module du package `entities` d'une application pour -qu'elle soit disponible à la fois coté serveur et coté client. - -La classe `AnyEntity` est une classe chargée dynamiquement héritant de la classe -de base `Entity` (`ginco.common.entity`). On définit une sous-classe pour -ajouter des méthodes ou spécialiser les comportements d'un type d'entité donné. - -Des descripteurs sont ajoutés à l'enregistrement pour initialiser la classe en -fonction du schéma : - -* on peut accéder aux attributs définis dans le schéma via les attributs de même - nom sur les instances (valeur typée) - -* on peut accéder aux relations définies dans le schéma via les attributs de même - nom sur les instances (liste d'instances d'entité) - -Les méthodes définies sur la classe `AnyEntity` ou `Entity` sont les suivantes : - -* `has_eid()`, retourne vrai si l'entité à un eid affecté (i.e. pas en cours de - création) - -* `check_perm(action)`, vérifie que l'utilisateur à le droit d'effectuer - l'action demandée sur l'entité - -:Formattage et génération de la sortie: - - * `view(vid, **kwargs)`, applique la vue donnée à l'entité - - * `absolute_url(**kwargs)`, retourne une URL absolue permettant d'accéder à la - vue primaire d'une entité - - * `rest_path()`, renvoie une l'URL REST relative permettant d'obtenir l'entité - - * `format(attr)`, retourne le format (type MIME) du champ passé en argument - - * `printable_value(attr, value=_marker, attrtype=None, format='text/html')`, - retourne une chaine permettant l'affichage dans un format donné de la valeur - d'un attribut (la valeur est automatiquement récupérée au besoin) - - * `display_name(form='')`, retourne une chaîne pour afficher le type de - l'entité, en spécifiant éventuellement la forme désirée ('plural' pour la - forme plurielle) - -:Gestion de données: - - * `as_rset()`, transforme l'entité en un resultset équivalent simulant - le résultat de la requête `Any X WHERE X eid _eid_` - - * `complete(skip_bytes=True)`, effectue une requête permettant de récupérer d'un - coup toutes les valeurs d'attributs manquant sur l'entité - - * `get_value(name)`, récupere la valeur associée à l'attribut passé en argument - - * `related(rtype, x='subject', limit=None, entities=False)`, retourne une liste - des entités liées à l'entité courant par la relation donnée en argument - - * `unrelated(rtype, targettype, x='subject', limit=None)`, retourne un result set - des entités not liées à l'entité courante par la relation donnée en argument - et satisfaisants les contraintes de celle-ci - - * `set_attributes(**kwargs)`, met à jour la liste des attributs avec - les valeurs correspondantes passées sous forme d'arguments nommés - - * `copy_relations(ceid)`, copie les relations de l'entité ayant l'eid passé en - argument sur l'entité courante - - * `last_modified(view)`, retourne la date à laquelle on doit considérer - l'objet comme modifié (utiliser par la gestion de cache HTTP) - - * `delete()` permet de supprimer l'entité représentée - -:Meta-données standard (Dublin Core): - - * `dc_title()`, retourne une chaine unicode correspondant à la méta-donnée - 'Title' (utilise par défaut le premier attribut non 'meta' du schéma de - l'entité) - - * `dc_long_title()`, comme dc_title mais peut retourner un titre plus détaillé - - * `dc_description(format='text/plain')`, retourne une chaine unicode - correspondant à la méta-donnée 'Description' (cherche un attribut - 'description' par défaut) - - * `dc_authors()`, retourne une chaine unicode correspondant à la méta-donnée - 'Authors' (propriétaires par défaut) - - * `dc_date(date_format=None)`, retourne une chaine unicode - correspondant à la méta-donnée 'Date' (date de modification par défaut) - -:Contrôle du vocabulaire pour les relations: - - * `vocabulary(rtype, x='subject', limit=None)`, appelée notamment - par les vues d'édition d'erudi, elle renvoie une liste de couple - (label, eid) des entités qui pourraient être liées à l'entité - via la relation `rtype` - * `subject_relation_vocabulary(rtype, limit=None)`, appelée - en interne par `vocabulary` dans le cas d'une relation sujet - * `object_relation_vocabulary(rtype, limit=None)`, appelée - en interne par `vocabulary` dans le cas d'une relation objet - * `relation_vocabulary(rtype, targettype, x, limit=None)`, appelé - en interne par `subject_relation_vocabulary` et `object_relation_vocabulary` - - -Les *rtags* ------------ -Les *rtags* permettent de spécifier certains comportements propres aux relations -d'un type d'entité donné (voir plus loin). Ils sont définis sur la classe -d'entité via l'attribut `rtags` qui est un dictionnaire dont les clés sont un -triplet :: - - , , ` pour -un attribut donnée. - - -Contrôle des attributs chargés et du tri par défaut -``````````````````````````````````````````````````` -* l'attribut de classe `fetch_attrs` permet de définir sur une classe d'entité - la liste des noms des attributs ou relations devant être chargés - automatiquement lors de la récupération d'entité(s) de ce type. Dans le cas - des relations, on est limité aux relations *sujets de cardinalité `?` ou `1`*. - -* la méthode de classe `fetch_order(attr, var)` prend en argument un nom - d'attribut (ou de relation) et un nom de variable et doit retourner une chaine - à utiliser dans la close "ORDERBY" d'une requête RQL pour trier - automatiquement les listes d'entités de ce type selon cet attribut, ou `None` - si l'on ne veut pas de tri sur l'attribut passé en argument. Par défaut les - entités sont triées selon leur date de création - -* la méthode de classe `fetch_unrelated_order(attr, var)` est similaire à la - méthode `fetch_order` mais est utilisée essentiellement pour contrôler le tri - des listes déroulantes permettant de créer des relations dans la vue d'édition - d'une entité - -La fonction `fetch_config(fetchattrs, mainattr=None)` permet de simplifier la -définition des attributs à précharger et du tri en retournant une liste des -attributs à précharger (en considérant ceux de la classe `AnyEntity` -automatiquement) et une fonction de tri sur l'attribut "principal" (le 2eme -argument si spécifié ou sinon le premier attribut de la liste `fetchattrs`). -Cette fonction est définie dans le package `ginco.entities`. - -Par exemple : :: - - class Transition(AnyEntity): - """...""" - id = 'Transition' - fetch_attrs, fetch_order = fetch_config(['name']) - -Indique que pour le type d'entité "Transition" il faut précharger l'attribut -"name" et trier par défaut selon cet attribut. - - -Contrôle des formulaires d'édition -`````````````````````````````````` -Il est possible de contrôler les attributs/relations dans la vue d'édition -simple ou multiple à l'aide des *rtags* suivants : - -* `primary`, indique qu'un attribut ou une relation doit être incorporé dans - les formulaires d'édition simple et multiple. Dans le cas d'une relation, - le formulaire d'édition de l'entité liée sera inclus dans le formulaire - -* `secondary`, indique qu'un attribut ou une relation doit être incorporé dans - le formulaire d'édition simple uniquement. Dans le cas d'une relation, - le formulaire d'édition de l'entité liée sera inclus dans le formulaire - -* `generic`, indique qu'une relation doit être incorporé dans le formulaire - d'édition simple dans la boite générique d'ajout de relation - -* `generated`, indique qu'un attribut est caculé dynamiquement ou autre, et - qu'il ne doit donc pas être présent dans les formulaires d'édition - -Au besoin il est possible de surcharger la méthode -`relation_category(rtype, x='subject')` pour calculer dynamiquement la catégorie -d'édition d'une relation. - - -Contrôle de la boîte "add_related" -`````````````````````````````````` -La boite `add related` est une boite automatique proposant de créer une entité -qui sera automatiquement liée à l'entité de départ (le contexte dans lequel -s'affiche la boite). Par défaut, les liens présents dans cette boite sont -calculés en fonction des propriétés du schéma de l'entité visualisée, mais il -est possible de les spécifier explicitement à l'aide des *rtags* suivants : - -* `link`, indique qu'une relation est généralement créée vers une entité - existante et qu'il ne faut donc pas faire apparaitre de lien pour cette - relation - -* `create`, indique qu'une relation est généralement créée vers de nouvelles - entités et qu'il faut donc faire apparaitre un lien pour créer une nouvelle - entité et la lier automatiquement - -Au besoin il est possible de surcharger la méthode -`relation_mode(rtype, targettype, x='subject')` pour caculer dynamiquement la -catégorie de création d'une relation. - -A noter également que si au moins une action dans la catégorie "addrelated" est -trouvée pour le contexte courant, le fonctionnement automatique est désactivé -en faveur du fonctionnement explicite (i.e. affichage des actions de la -catégorie "addrelated" uniquement). - -Contrôle des formulaires de filtrage de table -````````````````````````````````````````````` -La vue "table" par défaut gère dynamiquement un formulaire de filtrage du -contenu de celle-ci. L'algorithme est le suivant : - -1. on considère que la première colonne contient les entités à restreindre -2. on recupère la première entité de la table (ligne 0) pour "représenter" - toutes les autres -3. pour toutes les autres variables définies dans la requête originale : - - 1. si la variable est liée à la variable principale par au moins une - n'importe quelle relation - 2. on appelle la méthode `filterform_vocabulary(rtype, x)` sur l'entité - et si rien est retourné (ou plus exactement un tuple de valeur `None`, - voir ci-dessous) on passe à la variable suivante, sinon un élément de - formulaire de filtrage sera créé avec les valeurs de vocabulaire - retournées - -4. il n'y a pas d'autres limitations sur le rql, il peut comporter des clauses - de tris, de groupes... Des fonctions javascripts sont utilisées pour - regénérer une requête à partir de la requête de départ et des valeurs - séléctionnées dans les filtres de formulaire. - - -La méthode `filterform_vocabulary(rtype, x, var, rqlst, args, cachekey)` prend -en argument le nom d'une relation et la "cible", qui indique si l'entité sur -laquelle la méthode est appellée est sujet ou objet de la relation. Elle doit -retourner : - -* un 2-uple de None si elle ne sait pas gérer cette relation - -* un type et une liste contenant le vocabulaire - - * la liste doit contenir des couples (valeur, label) - * le type indique si la valeur désigne un nombre entier (`type == 'int'`), une - chaîne de caractères (`type == 'string'`) ou une entité non finale (`type - == 'eid'`) - -Par exemple dans notre application de gestion de tickets, on veut pouvoir -filtrés ceux-ci par : - -* type -* priorité -* état (in_state) -* étiquette (tags) -* version (done_in) - -On définit donc la méthode suivante : :: - - - class Ticket(AnyEntity): - - ... - - def filterform_vocabulary(self, rtype, x, var, rqlst, args, cachekey): - _ = self.req._ - if rtype == 'type': - return 'string', [(x, _(x)) for x in ('bug', 'story')] - if rtype == 'priority': - return 'string', [(x, _(x)) for x in ('minor', 'normal', 'important')] - if rtype == 'done_in': - rql = insert_attr_select_relation(rqlst, var, rtype, 'num') - return 'eid', self.req.execute(rql, args, cachekey) - return super(Ticket, self).filterform_vocabulary(rtype, x, var, rqlst, - args, cachekey) - - -NOTE: Le support du filtrage sur les étiquettes et l'état est installé -automatiquement, pas besoin de le gérer ici. diff -r 3159772915c4 -r d5acef862c58 doc/book/en/08-00-site-config.en.txt --- a/doc/book/en/08-00-site-config.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -.. -*- coding: utf-8 -*- - -Interface de configuration du site -================================== - -.. image:: images/lax-book.03-site-config-panel.en.png - -This panel allows you to configure the appearance of your application site. -Six menus are available and we will go through each of them to explain how -to use them. - -Navigation -~~~~~~~~~~ -This menu provides you a way to adjust some navigation options depending on -your needs, such as the number of entities to display by page of results. -Follows the detailled list of available options : - -* navigation.combobox-limit : maximum number of entities to display in related - combo box (sample format: 23) -* navigation.page-size : maximum number of objects displayed by page of results - (sample format: 23) -* navigation.related-limit : maximum number of related entities to display in - the primary view (sample format: 23) -* navigation.short-line-size : maximum number of characters in short description - (sample format: 23) - -UI -~~ -This menu provides you a way to customize the user interface settings such as -date format or encoding in the produced html. -Follows the detailled list of available options : - -* ui.date-format : how to format date in the ui ("man strftime" for format description) -* ui.datetime-format : how to format date and time in the ui ("man strftime" for format - description) -* ui.default-text-format : default text format for rich text fields. -* ui.encoding : user interface encoding -* ui.fckeditor :should html fields being edited using fckeditor (a HTML WYSIWYG editor). - You should also select text/html as default text format to actually get fckeditor. -* ui.float-format : how to format float numbers in the ui -* ui.language : language of the user interface -* ui.main-template : id of main template used to render pages -* ui.site-title : site title, which is displayed right next to the logo in the header -* ui.time-format : how to format time in the ui ("man strftime" for format description) - - -Actions -~~~~~~~ -This menu provides a way to configure the context in which you expect the actions -to be displayed to the user and if you want the action to be visible or not. -You must have notice that when you view a list of entities, an action box is -available on the left column which display some actions as well as a drop-down -menu for more actions. - -The context available are : - -* mainactions : actions listed in the left box -* moreactions : actions listed in the `more` menu of the left box -* addrelated : add actions listed in the left box -* useractions : actions listed in the first section of drop-down menu - accessible from the right corner user login link -* siteactions : actions listed in the second section of drop-down menu - accessible from the right corner user login link -* hidden : select this to hide the specific action - -Boxes -~~~~~ -The application has already a pre-defined set of boxes you can use right away. -This configuration section allows you to place those boxes where you want in the -application interface to customize it. - -The available boxes are : - -* actions box : box listing the applicable actions on the displayed data - -* boxes_blog_archives_box : box listing the blog archives - -* possible views box : box listing the possible views for the displayed data - -* rss box : RSS icon to get displayed data as a RSS thread - -* search box : search box - -* startup views box : box listing the configuration options available for - the application site, such as `Preferences` and `Site Configuration` - -Components -~~~~~~~~~~ -[WRITE ME] - -Contextual components -~~~~~~~~~~~~~~~~~~~~~ -[WRITE ME] - diff -r 3159772915c4 -r d5acef862c58 doc/book/en/09-00-instance-config.en.txt --- a/doc/book/en/09-00-instance-config.en.txt Tue Nov 25 17:44:54 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +0,0 @@ -.. -*- coding: utf-8 -*- - -Configuration d'une instance -============================ - -À la création d'une instance, un fichier de configuration est généré dans :: - - $(CW_REGISTRY)//.conf - -par exemple :: - - /etc/cubicweb.d/jpl/all-in-one.conf - -C'est un simple fichier texte au format INI. Dans la description suivante, -chaque nom d'option est préfixé de sa section et suivi de sa valeur par défaut -le cas échéant, e.g. "`
    .
    \n') + self.w(u'\n') + # appliname and breadcrumbs + self.w(u'') + # logged user and help + #self.w(u'') + # lastcolumn + self.w(u'\n') + self.w(u'\n') + self.template('logform', rset=self.rset, id='popupLoginBox', klass='hidden', + title=False, message=False) + + + +.. image:: images/lax-book.06-header-no-login.en.png + +Let's now move the search box in the top-right header area. To do so, we will +first create a method to get the search box display and insert it in the header +table. + +:: + + from ginco.web.views.basetemplates import HTMLPageHeader + class MyHTMLPageHeader(HTMLPageHeader): + def main_header(self, view): + """build the top menu with authentification info and the rql box""" + self.w(u'\n') + self.w(u'\n') + # appliname and breadcrumbs + self.w(u'') + + # logged user and help + #self.w(u'') + + self.w(u'') + # lastcolumn + self.w(u'\n') + self.w(u'\n') + self.template('logform', rset=self.rset, id='popupLoginBox', klass='hidden', + title=False, message=False) + + def get_searchbox(self, view, context): + boxes = list(self.vreg.possible_vobjects('boxes', self.req, self.rset, + view=view, context=context)) + if boxes: + for box in boxes: + if box.id == 'search_box': + box.dispatch(w=self.w, view=view) + + + + +HTMLPageFooter +~~~~~~~~~~~~~~ + +If you want to change the footer for example, look +for HTMLPageFooter and override it in your views file as in: +:: + + form ginco.web.views.basetemplates import HTMLPageFooter + class MyHTMLPageFooter(HTMLPageFooter): + def call(self, **kwargs): + self.w(u'') + +Updating a view does not require any restart of the server. By reloading +the page you can see your new page footer. + + +TheMainTemplate +~~~~~~~~~~~~~~~ + +.. _TheMainTemplate: + +The MainTemplate is a bit complex as it tries to accomodate many +different cases. We are now about to go through it and cutomize entirely +our application. + +TheMainTemplate is responsible for the general layout of the entire application. +It defines the template of ``id = main`` that is used by the application. Is +also defined in ``ginco/web/views/basetemplates.py`` another template that can +be used based on TheMainTemplate called SimpleMainTemplate which does not have +a top section. + +.. image:: images/lax-book.06-simple-main-template.en.png + +CSS changes +~~~~~~~~~~~ + +We cannot modify the order in which the application is reading the CSS. In +the case we want to create new CSS style, the best is to define it a in a new +CSS located under ``myapp/data/``. + +If you want to modify an existing CSS styling property, you will have to use +``!important`` declaration to override the existing property. The application +apply a higher priority on the default CSS and you can not change that. +Customized CSS will not be read first. + +[TODO] +Add login menu in left column + + +[WRITE ME] + +* customize MainTemplate and show that everything in the user + interface can be changed + +[TODO] +Rajouter une section pour definir la terminologie utilisee. +Dans ginco-doc rajouter une section pour erudi-ctl shell ou +on liste les commandes dispos. diff -r 3159772915c4 -r d5acef862c58 doc/book/en/A02d-rss-xml.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/A02d-rss-xml.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,45 @@ +.. -*- coding: utf-8 -*- + +RSS Channel +----------- + +Assuming you have several blog entries, click on the title of the +search box in the left column. A larger search box should appear. Enter:: + + Any X ORDERBY D WHERE X is BlogEntry, X creation_date D + +and you get a list of blog entries. + +Click on your login at the top right corner. Chose "user preferences", +then "boxes", then "possible views box" and check "visible = yes" +before validating your changes. + +Enter the same query in the search box and you will see the same list, +plus a box titled "possible views" in the left column. Click on +"entityview", then "RSS". + +You just applied the "RSS" view to the RQL selection you requested. + +That's it, you have a RSS channel for your blog. + +Try again with:: + + Any X ORDERBY D WHERE X is BlogEntry, X creation_date D, + X entry_of B, B title "MyLife" + +Another RSS channel, but a bit more focused. + +A last one for the road:: + + Any C ORDERBY D WHERE C is Comment, C creation_date D LIMIT 15 + +displayed with the RSS view, that's a channel for the last fifteen +comments posted. + +[WRITE ME] + +* show that the RSS view can be used to display an ordered selection + of blog entries, thus providing a RSS channel + +* show that a different selection (by category) means a different channel + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/A030-foundation.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/A030-foundation.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,32 @@ +.. -*- coding: utf-8 -*- + +`CubicWeb` Foundations +====================== + +A little history... +------------------- + +`CubicWeb` is a web application framework developped by Logilab_ since 2001. + +Entirely written in Python, `CubicWeb` publishes data from all sorts +of sources such as SQL database, LDAP directory and versioning system such +as subversion. + +`CubicWeb` user interface was designed to let the final user a huge flexibility +on how to select and how to display content. It allows to browse the knowledge +database and to display the results with the best rendering according to +the context. +This interface flexibility gives back the user the control of the +rendering parameters that are usually reserved for developpers. + + +We can list a couple of web applications developped with `CubicWeb`, an online +public phone directory (see http://www.118000.fr/), a system for managing +digital studies and simulations for a research lab, a tool for shared children +babysitting (see http://garde-partagee.atoukontact.fr/), a tool to manage +software developpment (see http://www.logilab.org), etc. + +In 2008, `CubicWeb` was ported for a new type of source : the datastore +from GoogleAppEngine_. + +.. include:: A03a-concepts.en.txt diff -r 3159772915c4 -r d5acef862c58 doc/book/en/A03a-concepts.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/A03a-concepts.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,411 @@ +.. -*- coding: utf-8 -*- + +Concepts +-------- + +Global architecture +~~~~~~~~~~~~~~~~~~~ +.. image:: images/archi_globale.png + +.. note:: + For real, the client and server sides are integrated in the same + process and interact directly, without the needs for distants + calls using Pyro. It is important to note down that those two + sides, client/server, are disjointed and it is possible to execute + a couple of calls in distincts processes to balance the load of + your web site on one or more machines. + +.. _TermsVocabulary: + +Terms and vocabulary +~~~~~~~~~~~~~~~~~~~~~ + +*schema* + The schema defines the data model of an application based on entities + and relations, modeled with a comprehensive language made of Python + classes based on `yams`_ library. This is the core piece + of an application. It is initially defined in the file system and is + stored in the database at the time an instance is created. `CubicWeb` + provides a certain number of system entities included automatically as + it is necessarry for the core of `CubicWeb` and a library of + cubes that can be explicitely included if necessary. + + +*entity type* + An entity is a set of attributes; the essential attribute of + an entity is its key, named eid + +*relation type* + Entities are linked to each others by relations. In `CubicWeb` + relations are binary: by convention we name the first item of + a relation the `subject` and the second the `object`. + +*final entity type* + Final types corresponds to the basic types such as string of characters, + integers... Those types have a main property which is that they can + only be used as `object` of a relation. The attributes of an entity + (non final) are entities (finals). + +*final relation type* + A relation is said final if its `object` is a final type. This is equivalent + to an entity attribute. + +*relation definition* + a relation definition is a 3-uple (subject entity type, relation type, object entity type), + with an associated set of property such as cardinality, constraints... + +*repository* + This is the RQL server side of `CubicWeb`. Be carefull not to get + confused with a Mercurial repository or a debian repository. + +*source* + A data source is a container of data (SGBD, LDAP directory, `Google + App Engine`'s datastore ...) integrated in the + `CubicWeb` repository. This repository has at least one source, `system` which + contains the schema of the application, plain-text index and others + vital informations for the system. + +*configuration* + It is possible to create differents configurations for an instance: + + - ``repository`` : repository only, accessible for clients using Pyro + - ``twisted`` : web interface only, access the repository using Pyro + - ``all-in-one`` : web interface and repository in a single process. + The repository could be or not accessible using Pyro. + +*cube* + A cube is a model grouping one or multiple data types and/or views + to provide a specific functionnality or a complete `CubicWeb` application + potentially using other cubes. The available subes are located in the file + system at `/path/to/forest/cubicweb/cubes`. + Larger applications can be built faster by importing cubes, + adding entities and relationships and overriding the + views that need to display or edit informations not provided by + cubes. + +*instance* + An instance is a specific installation of a cube. All the required + configuration files necessarry for the well being of your web application + are grouped in an instance. This will refer to the cube(s) your application + is based on. + By example logilab.org and our intranet are two instances of a single + cube jpl, developped internally. + The instances are defined in the directory `~/etc/cubicweb.d`. + +*application* + The term application is sometime used to talk about an instance + and sometimes to talk of a cube depending on the context. + So we would like to avoid using this term and try to use *cube* and + *instance* instead. + +*result set* + This object contains the results of an RQL query sent to the source + and information on the query. + +*Pyro* + `Python Remote Object`_, distributed objects system similar to Java's RMI + (Remote Method Invocation), which can be used for the dialog between the web + side of the framework and the RQL repository. + +*query language* + A full-blown query language named RQL is used to formulate requests + to the database or any sources such as LDAP or `Google App Engine`'s + datastore. + +*views* + A view is applied to a `result set` to present it as HTML, XML, + JSON, CSV, etc. Views are implemented as Python classes. There is no + templating language. + +*generated user interface* + A user interface is generated on-the-fly from the schema definition: + entities can be created, displayed, updated and deleted. As display + views are not very fancy, it is usually necessary to develop your + own. Any generated view can be overridden by defining a new one with + the same identifier. + +*rql* + XXX + +.. _`Python Remote Object`: http://pyro.sourceforge.net/ +.. _`yams`: http://www.logilab.org/project/yams/ + + +`CubicWeb` engine +~~~~~~~~~~~~~~~~~ + +The engine in `CubicWeb` is a set of classes managing a set of objects loaded +dynamically at the startup of `CubicWeb` (*appobjects*). Those dynamics objects, based on the schema +or the library, are building the final application. The differents dymanic components are +by example: + +* client and server side + + - entities definition, containing the logic which enables application data manipulation + +* client side + + - *views*, or more specifically + + - boxes + - header and footer + - forms + - page templates + + - *actions* + - *controllers* + +* server side + + - notification hooks + - notification views + +The components of the engine are: + +* a frontal web (only twisted is available so far), transparent for dynamic objects +* an object that encapsulates the configuration +* a `registry` (`cubicweb.cwvreg`) containing the dynamic objects loaded automatically + +Every *appobject* may access to the instance configuration using its *config* attribute +and to the registry using its *vreg* attribute. + +API Python/RQL +~~~~~~~~~~~~~~ + +Inspired from the standard db-api, with a Connection object having the methods +cursor, rollback and commit essentially. The most important method is +the `execute` method of a cursor : + +`execute(rqlstring, args=None, eid_key=None, build_descr=True)` + +:rqlstring: the RQL query to execute (unicode) +:args: if the query contains substitutions, a dictionnary containing the values to use +:eid_key: + an implementation detail of the RQL queries cache implies that if a substitution + is used to introduce an eid *susceptible to raise the ambiguities in the query + type resolution*, then we have to specify the correponding key in the dictionnary + through this argument + + +The `Connection` object owns the methods `commit` and `rollback`. You *should +never need to use them* during the development of the web interface based on +the `CubicWeb` framework as it determines the end of the transaction depending +on the query execution success. + +.. note:: + While executing updates queries (SET, INSERT, DELETE), if a query generates + an error related to security, a rollback is automatically done on the current + transaction. + + +The `Request` class (`cubicweb.web`) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A request instance is created when an HTPP request is sent to the web server. +It contains informations such as forms parameters, user authenticated, etc. + +**Globally, a request represents a user query, either through HTTP or not +(we also talk about RQL queries on the server side by example)** + +An instance of `Request` has the following attributes: + +* `user`, instance of `cubicweb.common.utils.User` corresponding to the authenticated + user +* `form`, dictionnary containing the values of a web form +* `encoding`, characters encoding to use in the response + +But also: + +:Session data handling: + * `session_data()`, returns a dictinnary containing all the session data + * `get_session_data(key, default=None)`, returns a value associated to the given + key or the value `default` if the key is not defined + * `set_session_data(key, value)`, assign a value to a key + * `del_session_data(key)`, suppress the value associated to a key + + +:Cookies handling: + * `get_cookie()`, returns a dictionnary containing the value of the header + HTTP 'Cookie' + * `set_cookie(cookie, key, maxage=300)`, adds a header HTTP `Set-Cookie`, + with a minimal 5 minutes length of duration by default (`maxage` = None + returns a *session* cookie which will expire when the user closes the browser + window + * `remove_cookie(cookie, key)`, forces a value to expire + +:URL handling: + * `url()`, returns the full URL of the HTTP request + * `base_url()`, returns the root URL of the web application + * `relative_path()`, returns the relative path of the request + +:And more...: + * `set_content_type(content_type, filename=None)`, adds the header HTTP + 'Content-Type' + * `get_header(header)`, returns the value associated to an arbitrary header + of the HTTP request + * `set_header(header, value)`, adds an arbitrary header in the response + * `cursor()` returns a RQL cursor on the session + * `execute(*args, **kwargs)`, shortcut to ``.cursor().execute()`` + * `property_value(key)`, properties management (`EProperty`) + * dictionnary `data` to store data to share informations between components + *while a request is executed* + +Please note down that this class is abstract and that a concrete implementation +will be provided by the *frontend* web used (in particular *twisted* as of +today). For the views or others that are executed on the server side, +most of the interface of `Request` is defined in the session associated +to the client. + +The `AppObject` class +~~~~~~~~~~~~~~~~~~~~~ + +In general: + +* we do not inherit directly from this class but from a more specific + class such as `AnyEntity`, `EntityView`, `AnyRsetView`, + `Action`... + +* to be recordable, a subclass has to define its own register (attribute + `__registry__`) and its identifier (attribute `id`). Usually we do not have + to take care of the register, only the identifier `id`. + +We can find a certain number of attributes and methods defined in this class +and so common to all the application objects: + +At the recording, the following attributes are dynamically added to +the *subclasses*: + +* `vreg`, the `vregistry` of the application +* `schema`, the application schema +* `config`, the application configuration + +We also find on instances, the following attributes: + +* `req`, `Request` instance +* `rset`, the *result set* associated to the object if necessarry +* `cursor`, rql cursor on the session + + +:URL handling: + * `build_url(method=None, **kwargs)`, returns an absolute URL based on + the given arguments. The *controller* supposed to handle the response + can be specified through the special parameter `method` (the connection + is theoretically done automatically :). + + * `datadir_url()`, returns the directory of the application data + (contains static files such as images, css, js...) + + * `base_url()`, shortcut to `req.base_url()` + + * `url_quote(value)`, version *unicode safe* of the function `urllib.quote` + +:Data manipulation: + + * `etype_rset(etype, size=1)`, shortcut to `vreg.etype_rset()` + + * `eid_rset(eid, rql=None, descr=True)`, returns a *result set* object for + the given eid + * `entity(row, col=0)`, returns the entity corresponding to the data position + in the *result set* associated to the object + + * `complete_entity(row, col=0, skip_bytes=True)`, is equivalent to `entity` but + also call the method `complete()` on the entity before returning it + +:Data formatting: + * `format_date(date, date_format=None, time=False)` + * `format_time(time)` + +:And more...: + + * `external_resource(rid, default=_MARKER)`, access to a value defined in the + configuration file `external_resource` + + * `tal_render(template, variables)`, + + +.. note:: + When we inherit from `AppObject` (even not directly), you *always* have to use + **super()** to get the methods and attributes of the superclasses, and not + use the class identifier. + By example, instead of writting: :: + + class Truc(PrimaryView): + def f(self, arg1): + PrimaryView.f(self, arg1) + + You'd better write: :: + + class Truc(PrimaryView): + def f(self, arg1): + super(Truc, self).f(arg1) + + +Standard structure for a cube +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A complex cube is structured as follows: + +:: + + mycube/ + | + |-- schema.py + | + |-- entities/ + | + |-- sobjects/ + | + |-- views/ + | + |-- test/ + | + |-- i18n/ + | + |-- data/ + | + |-- migration/ + | |- postcreate.py + | \- depends.map + | + |-- debian/ + | + \-- __pkginfo__.py + +We can use simple Python module instead of packages, by example: + +:: + + mycube/ + | + |-- entities.py + |-- hooks.py + \-- views.py + + +where : + +* ``schema`` contains the schema definition (server side only) +* ``entities`` contains the entities definition (server side and web interface) +* ``sobjects`` contains hooks and/or views notifications (server side only) +* ``views`` contains the different components of the web interface (web interface only) +* ``test`` contains tests specifics to the application (not installed) +* ``i18n`` contains the messages catalog for supported languages (server side and + web interface) +* ``data`` contains arbitrary data files served statically + (images, css, javascripts files)... (web interface only) +* ``migration`` contains the initialization file for new instances + (``postcreate.py``) and in general a file containing the `CubicWeb` dependancies + of the cube depending on its version (``depends.map``) +* ``debian`` contains all the files that manages the debian packaging + (you would find there the classical structure with ``control``, ``rules``, + ``changelog``... (not installed) +* the file ``__pkginfo__.py`` provides meta-data on the cube, especially the + distribution name and the current version (server side and web interface) or + also the sub-cubes used by this cube + +The only required files are: + +* the file ``__pkginfo__.py`` +* the schema definition + XXX false, we may want to have cubes which are only adding a service, no persistent data (eg embeding for instance) + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B000-development.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B000-development.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,39 @@ +.. -*- coding: utf-8 -*- + + +===================== +Part II - Development +===================== + +This part is about developing web applications with the `CubicWeb` framework. + +.. toctree:: + :maxdepth: 1 + + B020-define-schema.en.txt + B030-define-views.en.txt + B040-define-workflows.en.txt + B050-data-as-objects.en.txt + B060-form-management.en.txt + B070-ajax-json.en.txt + B080-internationalization.en.txt + B090-ui-components.en.txt + B100-hooks.en.txt + B110-notifications.en.txt + B120-migration.en.txt + B130-tests.en.txt + B140-google-appengine.en.txt + BXXX-actions.en.txt + BXXX-boxes.en.txt + BXXX-configuration.en.txt + BXXX-dbapi.en.txt + BXXX-embedding-external-page.en.txt + BXXX-online-doc.en.txt + BXXX-registry.en.txt + BXXX-repository-operations.en.txt + BXXX-repository-session.en.txt + BXXX-repository-tasks.en.txt + BXXX-request.en.txt + BXXX-sessions.en.txt + BXXX-templates.en.txt + BXXX-urlrewrite.en.txt diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B020-define-schema.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B020-define-schema.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,22 @@ +.. -*- coding: utf-8 -*- + +Data model definition (*schema*) +================================ + +The schema is the core piece of a `CubicWeb` application as it defines +the data model handled. It is based on entities types already defined +in the `CubicWeb` standard library and others, more specific, we would +expect to find in one or more Python files under the `schema` directory. + +At this point, it is important to make clear the difference between +relation type and relation definition: a relation type is only a relation +name with potentially other additionnal properties (see XXXX), whereas a +relation definition is a complete triplet +" ". +A relation type could have been implied if none is related to a +relation definition of the schema. + + +.. include:: B021-schema-stdlib.en.txt +.. include:: B022-schema-definition.en.txt + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B021-schema-stdlib.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B021-schema-stdlib.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,71 @@ +.. -*- coding: utf-8 -*- + +Pre-defined schemas in the library +---------------------------------- + +The library defines a set of entities schemas that are required by the system +or commonly used in `CubicWeb` applications. +Of course, you can extend those schemas if necessarry. + + +System schemas +`````````````` +The system entities available are : + +* `EUser`, system users +* `EGroup`, users groups +* `EEType`, entity type +* `ERType`, relation type + +* `State`, workflow state +* `Transition`, workflow transition +* `TrInfo`, record of a transition trafic for an entity + +* `EmailAddress`, email address, used by the system to send notifications + to the users and also used by others optionnals schemas + +* `EProperty`, used to configure the application +* `EPermission`, used to configure the security of the application + +* `Card`, generic documenting card +* `Bookmark`, an entity type used to allow a user to customize his links within + the application + +Cubes in the library +```````````````````` + +An application is based on several basic cubes. In the set of available +basic cubes we can find by example : + +* `comment`, provides an entity type for `Comment` allowing us to comment others + site's entities + +* `mailinglist`, provides an entity type for `Mailinglist` which groups informations + in a discussion list + +* `file`, provides entity types for `File` et `Image` used to represent + files (text or binary) with additionnal informations such as MIME type or + encoding. + +* `link`, provides an entity type for hypertext link (`Link`) + +* `blog`, provides an entity type weblog (`Blog`) + +* `person`, provides an entity type for a person (`Person`) + +* `addressbook`, provides an entity type used to represent phone + numbers (`PhoneNumber`) and mailing address (`PostalAddress`) + +* `classtags`, categorization system based on tags (`Tag`) + +* `classfolders`, categorization system based on folders hierarchy in order + to create navigation sections (`Folder`) + +* `email`, archiving management for emails (`Email`, `Emailpart`, + `Emailthread`) + +* `basket`, basket management (`Basket`) allowing to group entities + +To declare the use of a component, once installed, add the name of the component +to the variable `__use__` in the file `__pkginfo__.py` of your own component. + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B022-schema-definition.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B022-schema-definition.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,372 @@ +.. -*- coding: utf-8 -*- + +Entity type definition +---------------------- + +An entity type is defined by a Python class which inherits `EntityType`. The +class name correponds to the type name. Then the content of the class contains +the description of attributes and relations for the defined entity type, +by example :: + + class Personne(EntityType): + """A person with the properties and the relations necessarry for my + application""" + + last_name = String(required=True, fulltextindexed=True) + first_name = String(required=True, fulltextindexed=True) + title = String(vocabulary=('M', 'Mme', 'Mlle')) + date_of_birth = Date() + works_for = SubjectRelation('Company', cardinality='?*') + +* the name of the Python attribute corresponds to the name of the attribute + or the relation in `CubicWeb` application. + +* all built-in types are available : `String`, `Int`, `Float`, + `Boolean`, `Date`, `Datetime`, `Time`, `Byte`. + +* each entity type has at least the following meta-relations : + + - `eid` (`Int`) + + - `creation_date` (`Datetime`) + + - `modification_date` (`Datetime`) + + - `created_by` (`EUser`) (which user created the entity) + + - `owned_by` (`EUser`) (who does the entity belongs to, by default the + creator but not necessarry and it could have multiple owners) + + - `is` (`EEType`) + + +* it is also possible to define relations of type object by using `ObjectRelation` + instead of `SubjectRelation` + +* the first argument of `SubjectRelation` and `ObjectRelation` gives respectively + the object/subject entity type of the relation. This could be : + + * a string corresponding to an entity type + + * a tuple of string correponding to multiple entities types + + * special string such as follows : + + - "**" : all types of entities + - "*" : all types of non-meta entities + - "@" : all types of meta entities but not system entities (e.g. used for + the basic schema description) + +* it is possible to use the attribute `meta` to flag an entity type as a `meta` + (e.g. used to describe/categorize other entities) + +* optional properties for attributes and relations : + + - `description` : string describing an attribute or a relation. By default + this string will be used in the editing form of the entity, which means + that it is supposed to help the end-user and should be flagged by the + function `_` to be properly internationalized. + + - `constraints` : list of conditions/constraints that the relation needs to + satisfy (c.f. `Contraints`_) + + - `cardinality` : two characters string which specify the cardinality of the + relation. The first character defines the cardinality of the relation on + the subject, the second on the object of the relation. When a relation + has multiple possible subjects or objects, the cardinality applies to all + and not on a one to one basis (so it must be consistent...). The possible + values are inspired from regular expressions syntax : + + * `1`: 1..1 + * `?`: 0..1 + * `+`: 1..n + * `*`: 0..n + + - `meta` : boolean indicating that the relation is a meta-relation (false by + default) + +* optionnal properties for attributes : + + - `required` : boolean indicating if the attribute is required (false by default) + + - `unique` : boolean indicating if the value of the attribute has to be unique + or not within all entities of the same type (false by default) + + - `indexed` : boolean indicating if an index needs to be created for this + attribute in the database (false by default). This is usefull only if + you know that you will have to run numerous searches on the value of this + attribute. + + - `default` : default value of the attribute. In case of date types, the values + which could be used correpond to the RQL keywords `TODAY` and `NOW`. + + - `vocabulary` : specify static possible values of an attribute + +* optionnal properties of type `String` : + + - `fulltextindexed` : boolean indicating if the attribute is part of + the full text index (false by default) (*applicable on the type `Byte` + as well*) + + - `internationalizable` : boolean indicating if the value of the attribute + is internationalizable (false by default) + + - `maxsize` : integer providing the maximum size of the string (no limit by default) + +* optionnal properties for relations : + + - `composite` : string indicating that the subject (composite == 'subject') + is composed of the objects of the relations. For the opposite case (when + the object is composed of the subjects of the relation), we just need + to set 'object' as the value. The composition implies that when the relation + is deleted (so when the composite is deleted), the composed are also deleted. + +Contraints +`````````` +By default, the available constraints types are : + +* `SizeConstraint` : allows to specify a minimum and/or maximum size on + string (generic case of `maxsize`) + +* `BoundConstraint` : allows to specify a minimum and/or maximum value on + numeric types + +* `UniqueConstraint` : identical to "unique=True" + +* `StaticVocabularyConstraint` : identical to "vocabulary=(...)" + +* `RQLConstraint` : allows to specify a RQL query that needs to be satisfied + by the subject and/or the object of the relation. In this query the variables + `S` and `O` are reserved for the entities subject and object of the + relation. + +* `RQLVocabularyConstraint` : similar to the previous type of constraint except + that it does not express a "strong" constraint, which means it is only used to + restrict the values listed in the drop-down menu of editing form, but it does + not prevent another entity to be selected + + +Relation definition +------------------- + +XXX add note about defining relation type / definition + +A relation is defined by a Python class heriting `RelationType`. The name +of the class corresponds to the name of the type. The class then contains +a description of the properties of this type of relation, and could as well +contains a string for the subject and a string for the object. This allows to create +new definition of associated relations, (so that the class can have the +definition properties from the relation) by example :: + + class locked_by(RelationType): + """relation on all entities indicating that they are locked""" + inlined = True + cardinality = '?*' + subject = '*' + object = 'EUser' + +In addition to the permissions, the properties of the relation types +(shared also by all definition of relation of this type) are : + + +* `inlined` : boolean handling the physical optimization for archiving + the relation in the subject entity table, instead of creating a specific + table for the relation. This applies to the relation when the cardinality + of subject->relation->object is 0..1 (`?`) or 1..1 (`1`) + +* `symetric` : boolean indication that the relation is symetrical, which + means `X relation Y` implies `Y relation X` + +In the case of simultaneous relations definitions, `subject` and `object` +can both be equal to the value of the first argument of `SubjectRelation` +and `ObjectRelation`. + +When a relation is not inlined and not symetrical, and it does not require +specific permissions, its definition (by using `SubjectRelation` and +`ObjectRelation`) is all we need. + + +The security model +------------------ + +The security model of `cubicWeb` is based on `Access Control List`. +The main principles are: + +* users and groups of users +* a user belongs to at least one group of user +* permissions (read, update, create, delete) +* permissions are assigned to groups (and not to users) + +For `CubicWeb` in particular: + +* we associate rights at the enttities/relations schema level +* for each entity, we distinguish four kind of permissions: read, + add, update and delete +* for each relation, we distinguish three king of permissions: read, + add and delete (we can not modify a relation) +* the basic groups are: Administrators, Users and Guests +* by default, users belongs to the group Users +* there is a virtual group called `Owners users` to which we + can associate only deletion and update permissions +* we can not add users to the `Owners users` group, they are + implicetely added to it according to the context of the objects + they own +* the permissions of this group are only be checked on update/deletion + actions if all the other groups the user belongs does not provide + those permissions + + +Permissions definition +`````````````````````` + +Define permissions is set through to the attribute `permissions` of entities and +relations types. It defines a dictionnary where the keys are the access types +(action), and the values are the authorized groups or expressions. + +For an entity type, the possible actions are `read`, `add`, `update` and +`delete`. + +For a relation type, the possible actions are `read`, `add`, and `delete`. + +For each access type, a tuple indicates the name of the authorized groups and/or +one or multiple RQL expressions to satisfy to grant access. The access is +provided once the user is in the listed groups or one of the RQL condition is +satisfied. + +The standard groups are : + +* `guests` + +* `users` + +* `managers` + +* `owners` : virtual group corresponding to the entity's owner. + This can only be used for the actions `update` and `delete` of an entity + type. + +It is also possible to use specific groups if they are defined in the precreate +of the cube (``migration/precreate.py``). + + +Use of RQL expression for writing rights +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It is possible to define RQL expression to provide update permission +(`add`, `delete` and `update`) on relation and entity types. + +RQL expression for entity type permission : + +* you have to use the class `ERQLExpression` + +* the used expression corresponds to the WHERE statement of an RQL query + +* in this expression, the variables X and U are pre-defined references + respectively on the current entity (on which the action is verified) and + on the user who send the request + +* it is possible to use, in this expression, a special relation + "has__permission" where the subject is the user and the + object is a any variable, meaning that the user needs to have + permission to execute the action on the entities related + to this variable + +For RQL expressions on a relation type, the principles are the same except +for the following : + +* you have to use the class `RQLExpression` in the case of a non-final relation + +* in the expression, the variables S, O and U are pre-defined references + to respectively the subject and the object of the current relation (on + which the action is being verified) and the user who executed the query + +* we can also defined rights on attributes of an entity (non-final relation), + knowing that : + + - to defines RQL expression, we have to use the class `ERQLExpression` + in which X represents the entity the attribute belongs to + + - the permissions `add` and `delete` are equivalent. Only `add`/`read` + are actually taken in consideration. + +In addition to that the entity type `EPermission` from the standard library +allow to build very complex and dynamic security architecture. The schema of +this entity type is as follow : :: + + class EPermission(MetaEntityType): + """entity type that may be used to construct some advanced security configuration + """ + name = String(required=True, indexed=True, internationalizable=True, maxsize=100) + require_group = SubjectRelation('EGroup', cardinality='+*', + description=_('groups to which the permission is granted')) + require_state = SubjectRelation('State', + description=_("entity'state in which the permission is applyable")) + # can be used on any entity + require_permission = ObjectRelation('**', cardinality='*1', composite='subject', + description=_("link a permission to the entity. This " + "permission should be used in the security " + "definition of the entity's type to be useful.")) + + +Example of configuration :: + + + ... + + class Version(EntityType): + """a version is defining the content of a particular project's release""" + + permissions = {'read': ('managers', 'users', 'guests',), + 'update': ('managers', 'logilab', 'owners',), + 'delete': ('managers', ), + 'add': ('managers', 'logilab', + ERQLExpression('X version_of PROJ, U in_group G,' + 'PROJ require_permission P, P name "add_version",' + 'P require_group G'),)} + + ... + + class version_of(RelationType): + """link a version to its project. A version is necessarily linked to one and only one project. + """ + permissions = {'read': ('managers', 'users', 'guests',), + 'delete': ('managers', ), + 'add': ('managers', 'logilab', + RRQLExpression('O require_permission P, P name "add_version",' + 'U in_group G, P require_group G'),) + } + inlined = True + +This configuration indicates that an entity `EPermission` named +"add_version" can be associated to a project and provides rights to create +new versions on this project to specific groups. It is important to notice that : + +* in such case, we have to protect both the entity type "Version" and the relation + associating a version to a project ("version_of") + +* because of the genricity of the entity type `EPermission`, we have to execute + a unification with the groups and/or the states if necessary in the expression + ("U in_group G, P require_group G" in the above example) + +Use of RQL expression for reading rights +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The principles are the same but with the following restrictions : + +* we can not use `RRQLExpression` on relation types for reading + +* special relations "has__permission" can not be used + + +Note on the use of RQL expression for `add` permission +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Potentially, the use of an RQL expression to add an entity or a relation +can cause problems for the user interface, because if the expression uses +the entity or the relation to create, then we are not able to verify the +permissions before we actually add the entity (please note that this is +not a problem for the RQL server at all, because the permissions checks are +done after the creation). In such case, the permission check methods +(check_perm, has_perm) can indicate that the user is not allowed to create +this entity but can obtain the permission. +To compensate this problem, it is usually necessary, for such case, +to use an action that reflects the schema permissions but which enables +to check properly the permissions so that it would show up if necessary. diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B030-define-views.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B030-define-views.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,238 @@ +.. -*- coding: utf-8 -*- + +.. _DefinitionVues: + +Views definition +================ + +Basic class for views +--------------------- + +Class `View` (`cubicweb.common.view`) +````````````````````````````````````` + +A view writes in its output exit thanks to its attribute `w` (`UStreamIO`). + +The basic interface for views is as follows: + +* `dispatch(**context)`, render the view by calling `call` or + `cell_call` depending on the given parameters +* `call(**kwargs)`, call the view for a complete result set or null +* `cell_call(row, col, **kwargs)`, call the view for a given cell of a result set +* `url()`, returns the URL enabling us to get the view with the current + result set +* `view(__vid, rset, __fallback_vid=None, **kwargs)`, call the view of identifier + `__vid` on the given result set. It is possible to give a view identifier + of fallback that will be used if the view requested is not applicable to the + result set + +* `wview(__vid, rset, __fallback_vid=None, **kwargs)`, similar to `view` except + the flow is automatically passed in the parameters + +* `html_headers()`, returns a list of HTML headers to set by the main template + +* `page_title()`, returns the title to use in the HTML header `title` + +* `creator(eid)`, returns the eid and the login of the entity creator of the entity + having the eid given in the parameter + +Other basic classes: + +* `EntityView`, view applying to lines or cell containing an entity (e.g. an eid) +* `StartupView`, start view that does not require a result set to apply to +* `AnyRsetView`, view applied to any result set + + +The selection view principle +---------------------------- + +A view includes : + +- an identifier (all objects in `LAX` are entered in a registry + and this identifier will be used as a key) + +- a filter to select the resulsets it can be applied to + + +For a given identifier, multiple views can be defined. `CubicWeb` uses +a selector which computes scores so that it can identify and select the +best view to apply in context. The selector library is in +``cubicweb.common.selector`` and a library of the methods used to +compute scores is in ``cubicweb.vregistry.vreq``. + + +`CubicWeb` provides a lot of standard views, for a complete list, you +will have to read the code in directory ``cubicweb/web/views/`` (XXX +improve doc). + +For example, the view named ``primary`` is the one used to display +a single entity. + +If you want to change the way a ``BlogEntry`` is displayed, just +override the view ``primary`` in ``BlogDemo/views.py`` :: + + 01. from ginco.web.views import baseviews + 02. + 03. class BlogEntryPrimaryView(baseviews.PrimaryView): + 04. + 05. accepts = ('BlogEntry',) + 06. + 07. def cell_call(self, row, col): + 08. entity = self.entity(row, col) + 09. self.w(u'

    %s

    ' % entity.title) + 10. self.w(u'

    published on %s in category %s

    ' % \ + 11. (entity.publish_date.strftime('%Y-%m-%d'), entity.category)) + 12. self.w(u'

    %s

    ' % entity.text) + +The above source code defines a new primary view (`line 03`) for +``BlogEntry`` (`line 05`). + +Since views are applied to resultsets and resulsets can be tables of +data, it is needed to recover the entity from its (row,col) +coordinates (`line 08`). We will get to this in more detail later. + +The view has a ``self.w()`` method that is used to output data. Here `lines +09-12` output HTML tags and values of the entity's attributes. + +When displaying same blog entry as before, you will notice that the +page is now looking much nicer. + +.. image:: images/lax-book.09-new-view-blogentry.en.png + :alt: blog entries now look much nicer + +Let us now improve the primary view of a blog :: + + 01. class BlogPrimaryView(baseviews.PrimaryView): + 02. + 03. accepts = ('Blog',) + 04. + 05. def cell_call(self, row, col): + 06. entity = self.entity(row, col) + 07. self.w(u'

    %s

    ' % entity.title) + 08. self.w(u'

    %s

    ' % entity.description) + 09. rset = self.req.execute('Any E WHERE E entry_of B, B eid "%s"' % entity.eid) + 10. self.wview('primary', rset) + +In the above source code, `lines 01-08` are similar to the previous +view we defined. + +At `line 09`, a simple request in made to build a resultset with all +the entities linked to the current ``Blog`` entity by the relationship +``entry_of``. The part of the framework handling the request knows +about the schema and infer that such entities have to be of the +``BlogEntry`` kind and retrieves them. + +The request returns a selection of data called a resultset. At +`line 10` the view 'primary' is applied to this resultset to output +HTML. + +**This is to be compared to interfaces and protocols in object-oriented +languages. Applying a given view to all the entities of a resultset only +requires the availability, for each entity of this resultset, of a +view with that name that can accepts the entity.** + +Assuming we added entries to the blog titled `MyLife`, displaying it +now allows to read its description and all its entries. + +.. image:: images/lax-book.10-blog-with-two-entries.en.png + :alt: a blog and all its entries + +**Before we move forward, remember that the selection/view principle is +at the core of `CubicWeb`. Everywhere in the engine, data is requested +using the RQL language, then HTML/XML/text/PNG is output by applying a +view to the resultset returned by the query. That is where most of the +flexibility comes from.** + +[WRITE ME] + +* implementing interfaces, calendar for blog entries +* show that a calendar view can export data to ical + +We will implement the cubicwweb.interfaces.ICalendarable interfaces on +entities.BloEntry and apply the OneMonthCalendar and iCalendar views +to resultsets like "Any E WHERE E is BlogEntry" + +* create view "blogentry table" with title, publish_date, category + +We will show that by default the view that displays +"Any E,D,C WHERE E publish_date D, E category C" is the table view. +Of course, the same can be obtained by calling +self.wview('table',rset) + +* in view blog, select blogentries and apply view "blogentry table" +* demo ajax by filtering blogentry table on category + +we did the same with 'primary', but with tables we can turn on filters +and show that ajax comes for free. +[FILLME] + + +Templates +--------- + +*Templates* are specific view that does not depend on a result set. The basic +class `Template` (`cubicweb.common.view`) is derived from the class `View`. + +To build a HTML page, a *main template* is used. In general, the template of +identifier `main` is the one (it is not used in case an error is raised or for +the login form by example). This template uses other templates in addition +to the views which depends on the content to generate the HTML page to return. + +A *template* is responsible for: + +1. executing RQL query of data to render if necessarry +2. identifying the view to use to render data if it is not specified +3. composing the HTML page to return + + +The default main template (`cubicweb.web.views.basetemplates.TheMainTemplate`) +------------------------------------------------------------------------------ + +The default main template build the page based on the following pattern: + +.. image:: images/main_template_layout.png + +The rectangle containing `view.dispathc()` represents the area where the content +view has to be displayed. The others represents sub-templates called to complete +the page. A default implementation of those is provided in +`cubicweb.views.basetemplates`. You can, of course, overload those sub-templates +to implement your own customization of the HTML page. + +We can also control certain aspects of the main template thanks to the following +forms parameters: + +* `__notemplate`, if present (whatever the value assigned), only the content view + is returned +* `__force_display`, if present and its value is not null, no navigation + whatever the number of entities to display +* `__method`, if the result set to render contains only one entity and this + parameter is set, it refers to a method to call on the entity by passing it + the dictionnary of the forms parameters, before going the classic way (through + step 1 and 2 described juste above) + +.. include:: B031-views-stdlib.en.txt + + +XML views, binaries... +---------------------- +For the views generating other formats that HTML (an image generated dynamically +by example), and which can not usually be included in the HTML page generated +by the main template (see above), you have to: + +* set the atribute `templatable` of the class to `False` +* set, through the attribute `content_type` of the class, the MIME type generated + by the view to `application/octet-stream` + +For the views dedicated to binary content creation (an image dynamically generated +by example), we have to set the attribute `binary` of the class to `True` (which +implies that `templateable == False`, so that the attribute `w` of the view could be +replaced by a binary flow instead of unicode). + +(X)HTML tricks to apply +----------------------- + +Some web browser (Firefox by example) are not happy with empty `
    ` +(by empty we mean that there is no content in the tag, but there +could be attributes), so we should always use `
    ` even if +it is empty and not use `
    `. + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B031-views-stdlib.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B031-views-stdlib.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,65 @@ +.. -*- coding: utf-8 -*- + +Predefined views in the library +------------------------------- + +A certain number of views are used to build the web interface, which apply +to one or more entities. Their identifier is what distinguish them from +each others and the main ones are: + +:primary: + primary view of an entity, this is the view called by default when a single + entity is in the result set and needs to be displayed. This view is supposed + to render a maximum of informations about the entity. +:secondary: + secondary view of an entity. By default it renders the two first attributes + of the entity as a clickable link redirecting to the primary view. +:oneline: + similar to the `secondary` view, but called when we want the view to stand + on a single line, or just get a brief view. By default this view uses the + parameter `MAX_LINE_CHAR` to control the result size. +:text: + similar to the `oneline` view, but should not contain HTML. +:incontext, outofcontext: + similar to the `secondary` view, but called when an entity is considered + as in or out of context. By default it respectively returns the result of + `textincontext` and `textoutofcontext` wrapped in a link leading to + the primary view of the entity. +:textincontext, textoutofcontext: + similar to the `text` view, but called is an entity is considered out or + in context. By default it returns respectively the result of the + methods `.dc_title` and `.dc_long_title` of the entity. +:list: + creates a HTML list (`
      `) and call the view `listitem` for each entity + of the result set +:listitem: + redirects by default to the `outofcontext` view +:rss: + creates a RSS/XML view and call the view `rssitem` for each entity of + the result set +:rssitem: + create a RSS/XML view for each entity based on the results of the dunblin core + methods of the entity (`dc_*`) + +Start view: + +:index: + home page +:schema: + display the schema of the application + +Special views: + +:noresult: + called if the result set is empty +:finall: + display the value of a cell without trasnformation (in case of a non final + entity, we see the eid). Applicable on any result set. +:table: + creates a HTML table (``) and call the view `cell` for each cell of + the result set. Applicable on any result set. +:cell: + by default redirects to the `final` view if this is a final entity or + `outofcontext` view otherwise +:null: + view always applicable and which does not return anything diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B040-define-workflows.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B040-define-workflows.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,159 @@ +.. -*- coding: utf-8 -*- + +Workflow definition +====================== + +General +------- + +A workflow can be defined in a `CubicWeb` application thanks to the system +entities ``State`` and ``Transition``. Those are defined within all +`CubicWeb` application and can be set-up through the main administrator interface. + +Once your schema is defined, you can start creating the set of states and +the required transitions for your applications entities. + +You first need to define the states and then the transitions between those +to complete your workflow. + +A ``State`` defines the status of an entity. While creating a new state, +you will be first given the option to select the entity type the state +can be applied to. By choosing ``Apply``, a new section will be displayed +in the editing screen to enable you to add relation to the state you are +creating. + +A ``Transition`` is also based on an entity type it can be applied to. +By choosing ``Apply``, a new section will be displayed in the editing +screen to enable you to add relation to the transition you are +creating. + +At the transition level you will also define the group of user which can +aplly this transition to an object. + + +Example of a simple workflow +---------------------------- + +Please see the tutorial to view and example of a simple workflow. + + +[Create a simple workflow for BlogDemo, to have a moderator approve new blog +entry to be published. This implies, specify a dedicated group of blog +moderator as well as hide the view of a blog entry to the user until +it reaches the state published] + +Set-up a workflow +----------------- + +Before starting, make sure you refresh your mind by reading [link to +definition_workflow chapter]. + +We want to create a workflow to control the quality of the BlogEntry +submitted on your application. When a BlogEntry is created by a user +its state should be `submitted`. To be visible to all, it needs to +be in the state `published`. To move from `submitted` to `published` +we need a transition that we can name `approve_blogentry`. + +We do not want every user to be allowed to change the state of a +BlogEntry. We need to define a group of user, `moderators`, and +this group will have appropriate permissions to approve BlogEntry +to be published and visible to all. + +There are two ways to create a workflow, form the user interface, +and also by defining it in ``migration/postcreate.py``. This script +is executed each time a new ``./bin/laxctl db-init`` is done. +If you create the states and transitions through the user interface +this means that next time you will need to initialize the database +you will have to re-create all the entities. +We strongly recommand you create the workflow in ``migration\postcreate.py`` +and we will now show you how. +The user interface would only be a reference for you to view the states +and transitions but is not the appropriate interface to define your +application workflow. + +Update the schema +~~~~~~~~~~~~~~~~~ +To enable a BlogEntry to have a State, we have to define a relation +``in_state`` in the schema of BlogEntry. Please do as follows, add +the line ``in_state (...)``:: + + class BlogEntry(EntityType): + title = String(maxsize=100, required=True) + publish_date = Date(default='TODAY') + text_format = String(meta=True, internationalizable=True, maxsize=50, + default='text/rest', constraints=[format_constraint]) + text = String(fulltextindexed=True) + category = String(vocabulary=('important','business')) + entry_of = SubjectRelation('Blog', cardinality='?*') + in_state = SubjectRelation('State', cardinality='1*') + +As you updated the schema, you will have re-execute ``./bin/laxctl db-init`` +to initialize the database and migrate your existing entities. +[WRITE ABOUT MIGRATION] + +Create states, transitions and group permissions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +At the time the ``postcreate.py`` script is executed, several methods +can be used. They are all defined in the ``class ServerMigrationHelper``. +We will only discuss the method we use to create a wrokflow here. + +To define our workflow for BlogDemo, please add the following lines +to ``migration/postcreate.py``:: + + _ = unicode + + moderators = add_entity('EGroup', name=u"moderators") + + submitted = add_state(_('submitted'), 'BlogEntry', initial=True) + published = add_state(_('published'), 'BlogEntry') + + add_transition(_('approve_blogentry'), 'BlogEntry', (submitted,), published, ('moderators', 'managers'),) + + checkpoint() + +.. note:: + Do not forget to add the `_()` in front of all states and transitions names while creating + a workflow so that they will be identified by the i18n catalog scripts. + +``add_entity`` is used here to define the new group of users that we +need to define the transitions, `moderators`. +If this group required by the transition is not defined before the +transition is created, it will not create the relation `transition +require the group moderator`. + +``add_state`` expects as the first argument the name of the state you are +willing to create, then the entity type on which the state can be applied, +and an optionnal argument to set if the state is the initial state +of the entity type or not. + +``add_transition`` expects as the first argument the name of the +transition, then the entity type on which we can apply the transition, +then the list of possible initial states from which the transition +can be applied, the target state of the transition, and the permissions +(e.g. list of the groups of users who can apply the transition, the user +needs to belong to at least one of the listed group). + + +We could have also added a RQL condition in addition to a group to +which the user should belong to. + +If we use both RQL condition and group, the two must be satisfied +for the user to be allowed to apply the transition. + +If we use a RQL condition on a transition, we can use the following +variables: + +* `%(eid)s`, object's eid +* `%(ueid)s`, user executing the query eid +* `%(seid)s`, the object's current state eid + + +.. image:: images/lax-book.03-transitions-view.en.png + +You can now notice that in the actions box of a BlogEntry, the state +is now listed as well as the possible transitions from this state +defined by the workflow. This transition, as defined in the workflow, +will only being displayed for the users belonging to the group +moderators of managers. + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B050-data-as-objects.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B050-data-as-objects.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,144 @@ +.. -*- coding: utf-8 -*- + + +Stored data handling +==================== + +Classes `Entity` and `AnyEntity` +-------------------------------- + +To provide a specific behavior for each entity, we just need to define +a class inheriting from `cubicweb.entities.EnyEntity`. In genera, we have +to defined those classes in a module of `entites` package of an application +so that it will be available on both server and client side. + +The class `AnyEntity` is loaded dynamically from the class `Entity` +(`cubciweb.common.entity`). We define a sub-class to add methods or to +specialize the handling of a given entity type + +Descriptors are added when classes are registered in order to initialize the class +according to its schema: + +* we can access the defined attributes in the schema thanks the attributes of + the same name on instances (typed value) + +* we can access the defined relations in the schema thanks to the relations of + the same name on instances (entities instances list) + +The methods defined for `AnyEntity` or `Entity` are the following ones: + +* `has_eid()`, returns true is the entity has an definitive eid (e.g. not in the + creation process) + +* `check_perm(action)`, checks if the user has the permission to execcute the + requested action on the entity + +:Formatting and output generation: + + * `view(vid, **kwargs)`, apply the given view to the entity + + * `absolute_url(**kwargs)`, returns an absolute URL to access the primary view + of an entity + + * `rest_path()`, returns a relative REST URL to get the entity + + * `format(attr)`, returns the format (MIME type) of the field given un parameter + + * `printable_value(attr, value=_marker, attrtype=None, format='text/html')`, + returns a string enabling the display of an attribute value in a given format + (the value is automatically recovered if necessarry) + + * `display_name(form='')`, returns a string to display the entity type by + specifying the preferred form (`plural` for a plural form) + +:Data handling: + + * `as_rset()`, converts the entity into an equivalent result set simulating the + request `Any X WHERE X eid _eid_` + + * `complete(skip_bytes=True)`, executes a request that recovers in one time + all the missing attributes of an entity + + * `get_value(name)`, returns the value associated to the attribute name given + in parameter + + * `related(rtype, x='subject', limit=None, entities=False)`, returns a list + of entities related to the current entity by the relation given in parameter + + * `unrelated(rtype, targettype, x='subject', limit=None)`, returns a result set + corresponding to the entities not related to the current entity by the + relation given in parameter and satisfying its constraints + + * `set_attributes(**kwargs)`, updates the attributes list with the corresponding + values given named parameters + + * `copy_relations(ceid)`, copies the relations of the entities having the eid + given in the parameters on the current entity + + * `last_modified(view)`, returns the date the object has been modified + (used by HTTP cache handling) + + * `delete()` allows to delete the entity + +:Standard meta-data (Dublin Core): + + * `dc_title()`, returns a unicode string corresponding to the meta-data + `Title` (used by default the first attribute non-meta of the entity + schema) + + * `dc_long_title()`, same as dc_title but can return a more + detailled title + + * `dc_description(format='text/plain')`, returns a unicode string + corresponding to the meta-data `Description` (look for a description + attribute by default) + + * `dc_authors()`, returns a unicode string corresponding to the meta-data + `Authors` (owners by default) + + * `dc_date(date_format=None)`, returns a unicode string corresponding to + the meta-data `Date` (update date by default) + +:Vocabulary control on relations: + + * `vocabulary(rtype, x='subject', limit=None)`, called by the + editing views, it returns a list of couples (label, eid) of entities + that could be related to the entity by the relation `rtype` + * `subject_relation_vocabulary(rtype, limit=None)`, called internally + by `vocabulary` in the case of a subject relation + * `object_relation_vocabulary(rtype, limit=None)`, called internally + by `vocabulary` in the case of an object relation + * `relation_vocabulary(rtype, targettype, x, limit=None)`, called + internally by `subject_relation_vocabulary` and `object_relation_vocabulary` + + +*rtags* +------- + +*rtags* allows to specify certain behaviors of relations relative to a given +entity type (see later). They are defined on the entity class by the attribute +`rtags` which is a dictionnary with as its keys the triplet :: + + , , + +and as the values a `set` or a tuple of markers defining the properties that +apply to this relation. + +It is possible to simplify this dictionnary: + +* if we want to specifiy a single marker, it is not necessarry to + use a tuple as the value, the marker by itself (characters string) + is enough +* if we only care about a single type of relation and not about the target + and the context position (or when this one is not ambigous), we can simply + use the name of the relation type as the key +* if we want a marker to apply independently from the target entity type, + we have to use the string `*` as the target entity type + + +Please note that this dictionnary is *treated at the time the class is created*. +It is automatically merged with the parent class(es) (no need to copy the +dictionnary from the parent class to modify it). Also, modify it after the +class is created will not have any effect... + +.. include:: B051-define-entities.en.txt diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B051-define-entities.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B051-define-entities.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,170 @@ +.. -*- coding: utf-8 -*- + +Parametrization and specific extensions +--------------------------------------- + +Dynamic default values +`````````````````````` +It is possible to define in the schema *static* default values. +It is also possible to define in the schema *dynamic* default values +by defining in the entity class a method `default_` for +a given attribute. + + +Control of loaded attributes and default sorting +```````````````````````````````````````````````` + +* The class attribute `fetch_attrs` allows to defined in an entity class + a list of names of attributes or relations that should be automatically + loaded when we recover the entities of this type. In the case of relations, + we are limited to *subject of cardinality `?` or `1`* relations. + +* The class method `fetch_order(attr, var)` expects an attribute (or relation) + name as a parameter and a variable name, and it should return a string + to use in the requirement `ORDER BY` of an RQL query to automatically + sort the list of entities of such type according to this attribute, or + `None` if we do not want to sort on the attribute given in the parameter. + By default, the entities are sorted according to their creation date. + +* The class method `fetch_unrelated_order(attr, var)` is similar to the + method `fetch_order` except that it is essentially used to control + the sorting of drop-down lists enabling relations creation in + the editing view of an entity. + +The function `fetch_config(fetchattrs, mainattr=None)` simplifies the +definition of the attributes to load and the sorting by returning a +list of attributes to pre-load (considering automatically the attributes +of `AnyEntity`) and a sorting function based on the main attribute +(the second parameter if specified otherwisethe first attribute from +the list `fetchattrs`). +This function is defined in `cubicweb.entities`. + +By example: :: + + class Transition(AnyEntity): + """...""" + id = 'Transition' + fetch_attrs, fetch_order = fetch_config(['name']) + +Indique que pour le type d'entité "Transition" il faut précharger l'attribut +"name" et trier par défaut selon cet attribut. + + +Contrôle des formulaires d'édition +`````````````````````````````````` +Il est possible de contrôler les attributs/relations dans la vue d'édition +simple ou multiple à l'aide des *rtags* suivants : + +* `primary`, indique qu'un attribut ou une relation doit être incorporé dans + les formulaires d'édition simple et multiple. Dans le cas d'une relation, + le formulaire d'édition de l'entité liée sera inclus dans le formulaire + +* `secondary`, indique qu'un attribut ou une relation doit être incorporé dans + le formulaire d'édition simple uniquement. Dans le cas d'une relation, + le formulaire d'édition de l'entité liée sera inclus dans le formulaire + +* `generic`, indique qu'une relation doit être incorporé dans le formulaire + d'édition simple dans la boite générique d'ajout de relation + +* `generated`, indique qu'un attribut est caculé dynamiquement ou autre, et + qu'il ne doit donc pas être présent dans les formulaires d'édition + +Au besoin il est possible de surcharger la méthode +`relation_category(rtype, x='subject')` pour calculer dynamiquement la catégorie +d'édition d'une relation. + + +Contrôle de la boîte "add_related" +`````````````````````````````````` +La boite `add related` est une boite automatique proposant de créer une entité +qui sera automatiquement liée à l'entité de départ (le contexte dans lequel +s'affiche la boite). Par défaut, les liens présents dans cette boite sont +calculés en fonction des propriétés du schéma de l'entité visualisée, mais il +est possible de les spécifier explicitement à l'aide des *rtags* suivants : + +* `link`, indique qu'une relation est généralement créée vers une entité + existante et qu'il ne faut donc pas faire apparaitre de lien pour cette + relation + +* `create`, indique qu'une relation est généralement créée vers de nouvelles + entités et qu'il faut donc faire apparaitre un lien pour créer une nouvelle + entité et la lier automatiquement + +Au besoin il est possible de surcharger la méthode +`relation_mode(rtype, targettype, x='subject')` pour caculer dynamiquement la +catégorie de création d'une relation. + +A noter également que si au moins une action dans la catégorie "addrelated" est +trouvée pour le contexte courant, le fonctionnement automatique est désactivé +en faveur du fonctionnement explicite (i.e. affichage des actions de la +catégorie "addrelated" uniquement). + +Contrôle des formulaires de filtrage de table +````````````````````````````````````````````` +La vue "table" par défaut gère dynamiquement un formulaire de filtrage du +contenu de celle-ci. L'algorithme est le suivant : + +1. on considère que la première colonne contient les entités à restreindre +2. on recupère la première entité de la table (ligne 0) pour "représenter" + toutes les autres +3. pour toutes les autres variables définies dans la requête originale : + + 1. si la variable est liée à la variable principale par au moins une + n'importe quelle relation + 2. on appelle la méthode `filterform_vocabulary(rtype, x)` sur l'entité + et si rien est retourné (ou plus exactement un tuple de valeur `None`, + voir ci-dessous) on passe à la variable suivante, sinon un élément de + formulaire de filtrage sera créé avec les valeurs de vocabulaire + retournées + +4. il n'y a pas d'autres limitations sur le rql, il peut comporter des clauses + de tris, de groupes... Des fonctions javascripts sont utilisées pour + regénérer une requête à partir de la requête de départ et des valeurs + séléctionnées dans les filtres de formulaire. + + +La méthode `filterform_vocabulary(rtype, x, var, rqlst, args, cachekey)` prend +en argument le nom d'une relation et la "cible", qui indique si l'entité sur +laquelle la méthode est appellée est sujet ou objet de la relation. Elle doit +retourner : + +* un 2-uple de None si elle ne sait pas gérer cette relation + +* un type et une liste contenant le vocabulaire + + * la liste doit contenir des couples (valeur, label) + * le type indique si la valeur désigne un nombre entier (`type == 'int'`), une + chaîne de caractères (`type == 'string'`) ou une entité non finale (`type + == 'eid'`) + +Par exemple dans notre application de gestion de tickets, on veut pouvoir +filtrés ceux-ci par : + +* type +* priorité +* état (in_state) +* étiquette (tags) +* version (done_in) + +On définit donc la méthode suivante : :: + + + class Ticket(AnyEntity): + + ... + + def filterform_vocabulary(self, rtype, x, var, rqlst, args, cachekey): + _ = self.req._ + if rtype == 'type': + return 'string', [(x, _(x)) for x in ('bug', 'story')] + if rtype == 'priority': + return 'string', [(x, _(x)) for x in ('minor', 'normal', 'important')] + if rtype == 'done_in': + rql = insert_attr_select_relation(rqlst, var, rtype, 'num') + return 'eid', self.req.execute(rql, args, cachekey) + return super(Ticket, self).filterform_vocabulary(rtype, x, var, rqlst, + args, cachekey) + + +NOTE: Le support du filtrage sur les étiquettes et l'état est installé +automatiquement, pas besoin de le gérer ici. diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B060-form-management.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B060-form-management.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,133 @@ +.. -*- coding: utf-8 -*- + +Gestion de formulaires +====================== + +Contrôle de la génération automatique de formulaire pour les entités manipulée +------------------------------------------------------------------------------ +XXX FILLME + +* les formulaires 'edition' et 'creation' + +Le formulaire généré par défaut ne vous convient pas ? Vous êtes peut-être pas +obligé de le refaire à la main ! :) + +* rtags primary, secondary, generated, generic, + `Entity.relation_category(rtype, x='subject')` +* inline_view (now a rtag?) +* spécification widget + + +Fonctionnement du contrôleur d'édition par défaut (id: 'edit') +-------------------------------------------------------------- + +Contrôle de l'édition +````````````````````` +Prérequis: les paramètres liés aux entités à éditer sont spécifiés de la forme :: + + : + +où l'eid de l'entité pourra être une lettre dans le cas d'une entité à créer. On +dénommera ces paramètres comme *qualifié*. + +1. récupération des entités à éditer en cherchant les paramètres de formulaire + commençant par 'eid:' ayant également un paramètre '__type' associé + (également *qualifié* par l'eid évidemment) + +2. pour tous les attributs et relations de chaque entité à éditer + + 1. recherche d'un paramètre 'edits-' ou 'edito-' + qualifié dans le cas d'une relation dont l'entité est objet + 2. si trouvé, la valeur récupérée est considérée comme la valeur originale + pour cette relation, et on cherche la (ou les) nouvelle(s) valeur(s) dans + le paramètre (qualifié) + 3. si la valeur est différente de l'originale, une requête de modification en + base est effectuée + +3. pour chaque entité à éditer + + 1. si un paramètre `__linkto` qualifié est spécifié, sa valeur doit être une + chaine (ou une liste de chaine) de la forme : :: + + :: + + où vaut 'subject' ou 'object' et chaque eid peut-être séparé d'un + autre par un '_'. Target spécifie *l'entité éditée* est sujet ou objet de la + relation et chaque relation ainsi spécifiée sera insérée. + + 2. si un paramètre `__cloned_eid` qualifié est spécifié pour une entité, les + relations de l'entité spécifiée en valeur de cette argument sont copiées sur + l'entité éditée + + + 3. si un paramètre `__delete` qualifié est spécifié, sa valeur doit être une + chaine (ou une liste de chaine) de la forme : :: + + :: + + où chaque eid sujet ou objet peut-être séparé d'un autre par un '_'. Chaque + relation ainsi spécifiée sera supprimée. + + 4. si un paramètre `__insert` qualifié est spécifié, sa valeur doit être de + même format que pour `__delete`, mais chaque relation ainsi spécifiée sera + insérée. + +4. si les paramètres `__insert` et/ou `__delete` sont trouvés non qualifiés, + ils sont interprétés comme décrit ci-dessus (quelque soit le nombre d'entité + édité) + +5. si aucune entité n'est éditée mais que le formulaire contient les paramètres + `__linkto` et `eid`, celui-ci est interprété en prenant la valeur spécifié + par le paramètre `eid` pour désigner l'entité sur laquelle ajouter les + relations + + +A noter que : + +* si le paramètre `__action_delete` est trouvé, toutes les entités comme + spécifiées à éditer seront supprimées + +* si le paramètre `__action_cancel` est trouvé, aucune action n'est effectuée + +* si le paramètre `__action_apply` est trouvé, l'édition est effectuée + normalement mais la redirection sera effectuée sur le formulaire (cf `Contrôle + de la redirection`_) + +* le paramètre `__method` est également supporté comme sur le template principal + (XXX not very consistent, maybe __method should be dealed in the view controller) + +* si aucune entité à éditer n'est trouvée et qu'il n'y a pas de paramètre + `__action_delete`, `__action_cancel`, `__linkto`, `__delete` ou `__insert`, + une erreur est levée + +* placer dans le formulaire le paramètre `__message` permettra d'utiliser la + valeur de ce paramètre comme message d'information à l'utilisateur une fois + l'édition effectuée. + + +Contrôle de la redirection +`````````````````````````` +Une fois que l'édition s'est bien passé, reste un problème : c'est bien beau +tout ça, mais où qu'on va maintenant ?? Si rien n'est spécifié, le controlleur +se débrouille, mais comme il fait pas toujours ce qu'on voudrait, on peut +controller ça en utilisant les paramètres suivant : + +* `__redirectpath`: chemin de l'url (relatif à la racine du site, sans paramètre + de formulaire + +* `__redirectparams`: paramètres de formulaires à ajouter au chemin + +* `__redirectrql`: requête RQL de redirection + +* `__redirectvid`: identifiant de vue de redirection + +* `__errorurl`: url du formulaire original, utilisé pour la redirection en cas + d'erreur de validation pendant l'édition. Si celui-ci n'est pas spécifié, une + page d'erreur sera présentée plutot qu'un retour sur le formulaire (qui est le + cas échéant responsable d'afficher les erreurs) + +* `__form_id`: identifiant de vue du formulaire original, utilisée si + `__action_apply` est trouvé + +En général on utilise soit `__redirectpath et `__redirectparams` soit +`__redirectrql` et `__redirectvid`. diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B070-ajax-json.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B070-ajax-json.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,16 @@ +.. -*- coding: utf-8 -*- + +AJAX +==== +JSON bla bla +XXX FILLME + + +Le contrôleur 'json' +-------------------- +XXX FILLME + + +API Javascript +-------------- +XXX FILLME diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B080-internationalization.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B080-internationalization.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,100 @@ +.. -*- coding: utf-8 -*- + +.. _internationalization: + + +Internationalization +==================== + +Cubicweb fully supports the internalization of it's content and interface. + +Cubicweb's interface internationalization is based on the translation project `GNU gettext`_. + +.. _`GNU gettext`: http://www.gnu.org/software/gettext/ + +Cubicweb' internalization involves two steps: + +* in your Python code and cubicweb-tal templates : mark translatable strings + +* in your application : handle the translation catalog + +String internalization +---------------------- + +In the Python code and cubicweb-tal templates translatable strings can be +marked in one of the following ways : + + * by using the *built-in* function `_` :: + + class PrimaryView(EntityView): + """the full view of an non final entity""" + id = 'primary' + title = _('primary') + + OR + + * by using the equivalent request's method :: + + class NoResultView(EmptyRsetView): + """default view when no result has been found""" + id = 'noresult' + + def call(self, **kwargs): + self.w(u'
      %s
      \n' + % self.req._('No result matching query')) + +The goal of the *built-in* function `_` is only **to mark the +translatable strings**, it will only return the translation string +it-self, but not it's translation. + +In the other hand the request's method `_` is ment to retrive the +proper translation of translation strings in the requested language. + +Translations in cubicweb-tal template can also be done with TAL tags +`i18n:content` and `i18n:replace`. + +Note :: + + We dont need to mark the translation strings of entities/relations + used by a particular application's schema as they are generated + automatically. + + +Handle the translation catalog +------------------------------ + +Once the internalization is done in your application's code, you need +to populate and update the translation catalog. Cubicweb provides the +following commands for this purpose: + + +* `i18nlibupdate` updates Cubicweb framework's translation + catalogs. Unless you work on the framework development, you dont + need to use this command. + +* `i18nupdate` updates the translation catalogs of *one particular + component* (or of all components). FIXME After this command is + executed you must update the translation files *.po* in the "i18n" + directory of your template. This command will of course not remove + existing translations still in use + +* `i18ncompile` recompile the transaltion catalogs of *one particular + instance* (or of all instances) after the translation catalogs of + its components have been updated. This command is automatically + called every time you create or update your instance. The compiled + catalogs (*.mo*) are stored in the i18n//LC_MESSAGES of + application where `lang` is the language identifier ('en' or 'fr' + for exemple). + + +Example +``````` +You have added and/or modified some translation strings in your application +(after creating a new view or modifying the application's schema for exemple). +To update the translation catalogs you need to do: + +1. `cubicweb-ctl i18nupdate ` +2. Edit the /xxx.po files and add missing translations (empty `msgstr`) +3. `hg ci -m "updated i18n catalogs"` +4. `cubicweb-ctl i18n compile ` + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B081-i18n.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B081-i18n.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,71 @@ +.. -*- coding: utf-8 -*- + +.. _Internationalisation: + + +Internationalisation +==================== + +Le système d'internationalisation de l'interface web de CubicWeb est basé sur le +système `GNU gettext`_. + +.. _`GNU gettext`: http://www.gnu.org/software/gettext/ + +Messages à internationaliser +---------------------------- + +Marquage des messages à internaliser +```````````````````````````````````` +Les chaines de caractères à internationaliser sont marqués par l'appel à la +fonction `_` *OU* par la méthode équivalent de la requête dans le code python ou +dans les expressions python de template TAL. + +Dans les templates cubicweb-tal, il est également possible d'insérer une chaine à +traduire via les balises `i18n:content` et `i18n:replace`. + +De plus des messages correspondant aux entités/relations utilisés par le schéma +de l'application seront automatiquement ajoutés. + +Renvoi d'un message internationalisé lors de la construction d'une page +``````````````````````````````````````````````````````````````````````` +La fonction *built-in* `_` ne doit servir qu'**à marquer les messages à +traduire**, non pas à récupérer une traduction. Il faut pour cela utiliser la +méthode `_` de l'objet requête, sans quoi vous récupérerez l'identifiant de +message au lieu de sa traduction dans la langue propre à la requête.1 + + +Gestion des catalogues de traduction +------------------------------------ +Une fois l'application rendu internationalisable coté code, reste à gérer les +catalogues de traductions. cubicweb-ctl intègre pour cela les commandes suivantes : + +* `i18nlibupdate`, met à jour les catalogues de messages *de la librairie + cubicweb*. Sauf si vous développez sur le framework (et non votre propre + application), vous ne devriez pas avoir à utiliser cette commande + +* `i18nupdate`, met à jour les catalogues de messages *du composant* (ou de tous + les composants). A la suite de cette commande, vous devez mettre à jour les + fichiers de traduction *.po* dans le sous-répertoire "i18n" de votre + template. Évidemment les traductions précédentes toujours utilisées ont été + conservées. + +* `i18ncompile`, recompile les catalogues de messages *d'une instance* (ou de + toutes les instances) après mise à jour des catalogues de son composant. Cela + est effectué automatiquement lors d'une création ou d'une mise à jour. Les + catalogues de messages compilés se trouvent dans le répertoire + "i18n//LC_MESSAGES/cubicweb.mo" de l'application où `lang` est + l'identifiant de la langue sur 2 lettres ('en' ou 'fr' par exemple) + + +Le cas classique +```````````````` +Vous avez ajouté et/ou modifié des messages d'un composant utilisé par votre +application (en ajoutant une nouvelle vue ou en ayant modifié le schéma par +exemple) : + +1. `cubicweb-ctl i18nupdate ` +2. éditer les fichiers /xxx.po dans pour y rajouter les traductions + manquantes (`msgstr` vide) +3. `hg ci -m "updated i18n catalogs"` +4. `cubicweb-ctl i18n compile ` + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B090-ui-components.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B090-ui-components.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,14 @@ +Autres composants de l'interface web +==================================== + +Actions +------- +XXXFILLME + +Component, VComponent +--------------------- +XXXFILLME + +EProperty +--------- +XXXFILLME diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B100-hooks.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B100-hooks.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,31 @@ +.. -*- coding: utf-8 -*- + +Les crochets (*hooks*) +====================== + +XXX FILLME + +Les crochets sont appelés avant ou après la mise à jour d'une entité ou d'une +relations dans le dépot + +Leur prototypes sont les suivants + + + * after_add_entity (session, entity) + * after_update_entity (session, entity) + * after_delete_entity (session, eid) + * before_add_entity (session, entity) + * before_update_entity (session, entity) + * before_delete_entity (session, eid) + + * after_add_relation (session, fromeid, rtype, toeid) + * after_delete_relation (session, fromeid, rtype, toeid) + * before_add_relation (session, fromeid, rtype, toeid) + * before_delete_relation (session, fromeid, rtype, toeid) + + * server_startup + * server_shutdown + + * session_open + * session_close + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B110-notifications.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B110-notifications.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,6 @@ +.. -*- coding: utf-8 -*- + +Gestion de notifications +======================== + +XXX FILLME diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B120-migration.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B120-migration.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,218 @@ +.. -*- coding: utf-8 -*- + + +Migration +========= + +Une des idées de base d'Erudi est la création incrémentale d'application, et +pour cela de nombreuses actions sont fournies afin de facilement faire évoluer +une application et tout particulièrement le modèle de données manipulé sans +perdre les données des instances existantes. + +La version courante d'un modèle d'application est données dans le fichier +`__pkginfo__.py` sous forme d'un tuple de 3 entiers. + + +Gestion des scripts de migrations +--------------------------------- +Les scripts des migrations doivent être placés dans le répertoire `migration` de +l'application, et nommé de la manière suivante : + +:: + + [_]_.py + +dans lequel : + +* X.Y.Z correspond au n° de version du modèle vers lequel le script permet de + migrer, + +* le *mode* (entre le dernier "_" et l'extension ".py") indique à quelle partie + de l'application (serveur RQL, serveur web) le script s'applique en cas + d'installation distribuée. Il peut valoir : + + * `common`, s'applique aussi bien sur le serveur RQL que sur le serveur web, + et met à jour des fichiers sur le disque (migration de fichier de + configuration par exemple). + + * `web`, s'applique uniquement sur le serveur web, et met à jour des fichiers + sur le disque + + * `repository`, s'applique uniquement sur le serveur RQL, et met à jour des + fichiers sur le disque + + * `Any`, s'applique uniquement sur le serveur RQL, et met à jour des + données en base (migrations de schéma et de données par ex.) + + +Toujours dans le répertoire `migration`, le fichier spécial `depends.map` permet +d'indiquer que pour migrer vers une version spécifique du modèle, il faut tout +d'abord avoir migrer vers une version données de erudi. Ce fichier peut contenir +des commentaires (lignes commençant par un "#"), et une dépendance est notée sur +une ligne de la manière suivante : :: + + : + +Par exemple :: + + 0.12.0: 2.26.0 + 0.13.0: 2.27.0 + # 0.14 works with 2.27 <= erudi <= 2.28 at least + 0.15.0: 2.28.0 + + +Contexte de base +---------------- +Les identifiants suivants sont préféfinis dans les scripts de migration : + +* `config`, configuration de l'instance + +* `interactive_mode`, booléen indiquant si le script est éxécuté en mode + interactif ou non + +* `appltemplversion`, version du modèle d'application de l'instance + +* `applerudiversion`, version erudi de l'instance + +* `templversion`, version du modéle d'application installée + +* `erudiversion`, version erudi installée + +* `confirm(question)`, fonction posant une question et retournant vrai si + l'utilisateur a répondu oui, faux sinon (retourne toujours vrai en mode non + interactif) + +* `_`, fonction équivalente à `unicode` permettant de marquer des chaines à + internationaliser dans les scripts de migration + +Dans les scripts "repository", les identifiants suivant sont également définis : + +* `checkpoint`, demande confirmant et effectue un "commit" au point d'appel + +* `repo_schema`, schéma persistent de l'instance (i.e. schéma de l'instance en + cours de migration) + +* `newschema`, schéma installé sur le système de fichier (i.e. schéma de la + version à jour du modèle et de erudi) + +* `sqlcursor`, un curseur SQL pour les très rares cas où il est réellement + nécessaire ou avantageux de passer par du sql + +* `repo`, l'objet repository + + +Migration de schéma +------------------- +Les fonctions de migration de schéma suivantes sont disponibles dans les scripts +"repository" : + +* `add_attribute(etype, attrname, attrtype=None, commit=True)`, ajoute un + nouvel attribut à un type d'entité existante. Si le type de celui-ci n'est pas + spécifié il est extrait du schéma à jour. + +* `drop_attribute(etype, attrname, commit=True)`, supprime un + attribut à un type d'entité existante. + +* `rename_attribute(etype, oldname, newname, commit=True)`, renomme un attribut + +* `add_entity_type(etype, auto=True, commit=True)`, ajoute un nouveau type + d'entité. Si `auto` est vrai, toutes les relations utilisant ce type d'entité + et ayant un type d'entité connu à l'autre extrémité vont également être + ajoutées. + +* `drop_entity_type(etype, commit=True)`, supprime un type d'entité et toutes + les relations l'utilisant. + +* `rename_entity_type(oldname, newname, commit=True)`, renomme un type d'entité + +* `add_relation_type(rtype, addrdef=True, commit=True)`, ajoute un nouveau type + de relation. Si `addrdef` est vrai, toutes les définitions de relation de ce + type seront également ajoutées. + +* `drop_relation_type(rtype, commit=True)`, supprime un type de relation et + toutes les définitions de ce type. + +* `rename_relation(oldname, newname, commit=True)`, renomme une relation. + +* `add_relation_definition(subjtype, rtype, objtype, commit=True)`, ajoute une + définition de relation. + +* `drop_relation_definition(subjtype, rtype, objtype, commit=True)`, supprime + une définition de relation. + +* `synchronize_permissions(ertype, commit=True)`, synchronise les permissions + d'un type d'entité ou de relation + +* `synchronize_rschema(rtype, commit=True)`, synchronise les propriétés et + permissions d'un type de relation. + +* `synchronize_eschema(etype, commit=True)`, synchronise les propriétés et + permissions d'un type d'entité. + +* `synchronize_schema(commit=True)`, synchronise le schéma persistent avec le + schéma à jour (mais sans ajouter ni supprimer de nouveaux types d'entités ou + de relations ni de définitions de relation). + +* `change_relation_props(subjtype, rtype, objtype, commit=True, **kwargs)`, change + les propriétés d'une definition de relation en utilisant les arguments nommés + pour les propriétés à changer. + +* `set_widget(etype, rtype, widget, commit=True)`, change le widget à utiliser + pour la relation du type d'entité + +* `set_size_constraint(etype, rtype, size, commit=True)`, change la contrainte + de taille pour la relation du type d'entité + + +Migration de données +-------------------- +Les fonctions de migration de données suivantes sont disponibles dans les scripts +"repository" : + +* `rql(rql, kwargs=None, cachekey=None, ask_confirm=True)`, éxécute une + requête rql arbitraire, d'interrogation ou de modification. Un objet result + set est retourné. + +* `add_entity(etype, *args, **kwargs)`, ajoute une nouvelle entité du type + données. La valeur des attributs et relations est spécifiée en utilisant les + arguments nommés et positionnels. + + +Création de workflow +-------------------- +Les fonctions de création de workflow suivantes sont disponibles dans les scripts +"repository" : + +* `add_state(name, stateof, initial=False, commit=False, **kwargs)`, ajoute un + nouvel état de workflow + +* `add_transition(name, transitionof, fromstates, tostate, requiredgroups=(), commit=False, **kwargs)`, + ajoute une nouvelle transtion de workflow + +Migration de configuration +-------------------------- +Les fonctions de migration de configuration suivantes sont disponibles dans tout +les scripts : + +* `option_renamed(oldname, newname)`, indique qu'une option a été renommée + +* `option_group_change(option, oldgroup, newgroup)`, indique qu'une option a + changé de groupe + +* `option_added(oldname, newname)`, indique qu'une option a été ajoutée + +* `option_removed(oldname, newname)`, indique qu'une option a été supprimée + + +Autres fonctions de migration +----------------------------- +Ces fonctions ne sont utilisés que pour des opérations de bas niveau +irréalisables autrement ou pour réparer des bases cassées lors de session +interactive. Elles sont disponibles dans les scripts "repository". + +* `sqlexec(sql, args=None, ask_confirm=True)`, éxécute une requête sql + arbitraire, à n'utiliser + +* `add_entity_type_table(etype, commit=True)` +* `add_relation_type_table(rtype, commit=True)` +* `uninline_relation(rtype, commit=True)` diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B130-tests.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B130-tests.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,38 @@ +.. -*- coding: utf-8 -*- + +Tests +===== + +Écriture de tests unitaires +--------------------------- +Le framework de test fournit principalement deux classes de tests dans le module +`ginco.devtools.apptest`: + +* `EnvBasedTC`, pour simuler un environnement complet (web + repository) +* `RepositoryBasedTC`, pour simuler un environnement de repository uniquement + +Ces deux classes ont quasiment la même interface et proposent un certain nombre de méthodes +rendant l'écriture de test puissante et rapide. + +XXXFILLME describe API + +Dans la plupart des cas, vous allez vouloir hériter de `EnvBasedTC` pour écrire des tests +unitaires ou fonctionnels pour vos entités, vues, crochets... + + +Test des courriels de notifications +``````````````````````````````````` +Lors de l'éxécution de tests les courriels potentiellement générés ne sont pas réellement +envoyé mais se retrouve dans la liste `MAILBOX` du module `ginco.devtools.apptest`. Cette +liste est remise à zéro au *setUp* de chaque test (par le setUp des classes `EnvBasedTC` +et `RepositoryBasedTC`). + +Vous pouvez donc tester vos notifications en analysant le contenu de cette liste, qui +contient des objets ayant deux attributs : +* `recipients`, la liste des destinataires +* `msg`, l'objet email.Message + + +Tests automatiques +------------------ +XXXFILLME diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B140-google-appengine.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B140-google-appengine.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,11 @@ +.. -*- coding: utf-8 -*- + +.. _contents: + +========================== +Google AppEngine Datastore +========================== + + +.. include:: B141-intro.en.txt +.. include:: B142-install.en.txt diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B141-intro.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B141-intro.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,44 @@ +.. -*- coding: utf-8 -*- + +Introduction +============ + +What is `Google AppEngine` ? +------------------------------ + +`Google AppEngine`_ is provided with a partial port of the `Django` +framework, but Google stated at Google IO 2008 that it would not +support a specific Python web framework and that all +community-supported frameworks would be more than welcome [1]_. + +Therefore `Logilab`_ ported `CubicWeb` to run on top of `Google AppEngine`'s +datastore. + +.. _`Google AppEngine`: http://code.google.com/appengine/docs/whatisgoogleappengine.html +.. _Logilab: http://www.logilab.fr/ +.. [1] for more on this matter, read our blog at http://www.logilab.org/blogentry/5216 + + +Essentials +---------- + +To build a web application for `Google App Engine`'s datastore, you +need to have a good understanding of the main concepts of our +`CubicWeb` framework. + +The main concepts are: + + - *schema* + + - *query language* + + - *result set* + + - *views* + + - *generated user interface* + + - *cube* + +You can find detailled explanation of those concepts in :ref:`TermsVocabulary`. + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/B142-install.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B142-install.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,220 @@ +.. -*- coding: utf-8 -*- + +.. _installation: + +Installation +============ + +Download the source +------------------- + +- The `Google AppEngine SDK` can be downloaded from: + http://code.google.com/appengine/downloads.html + +- `LAX` is available as an extension of `CubicWeb` under the GPLv2 + license which can be downloaded from : http://cubicweb.org/ + +Please follow instructions on how to install `CubicWeb` framework. + +Once ``cubicweb-ctl`` is installed, then you can create a Google +App Engine extension of our framework by running the command :: + + cubicweb-ctl newgapp + +This will create a directory containing :: + + `-- myapp/ + |-- app.conf + |-- app.yaml + |-- bin/ + | `-- laxctl + |-- boostrap_cubes + |-- cubes/ + | |-- addressbook/ + | .. + | |-- comment + | .. + | `-- zone/ + |-- cubicweb/ + |-- custom.py + |-- cw-cubes/ + |-- dateutil/ + |-- docutils/ + |-- fckeditor/ + |-- i18n/ + |-- index.yaml + |-- loader.py + |-- logilab/ + |-- main.py + |-- migration.py + |-- mx/ + |-- roman.py + |-- rql/ + |-- schema.py + |-- simplejson/ + |-- tools/ + |-- views.py + |-- vobject/ + |-- yams/ + `-- yapps/ + + +This skeleton directory is a working `AppEngine` application. You will +recognize the files ``app.yaml`` and ``main.py``. All the rest is the +`LAX` framework and its third-party libraries. You will notice that +the directory ``cubes`` is a library of reusable components. + +The main directories that you should know about are: + + - ``cubes`` : this is a library of reusable yams components. To use + those components you will list them in the variable + `included-yams-cubes` of ``app.conf``. See also :ref:`components`. + - [WHICH OTHER ONES SHOULD BE LISTED HERE?] + +Dependencies +------------ + +Before starting anything, please make sure the following packages are installed: + - yaml : by default google appengine is providing yaml; make sure you can + import it. We recommend you create a symbolic link yaml instead of installing + and using python-yaml: + yaml -> full/path/to/google_appengine/lib/yaml/lib/yaml/ + - gettext + +Setup +----- + +Once you executed ``cubicweb-ctl newgapp ``, you can use that ``myapp/`` +as an application directory and do as follows. + +This installation directory provides a configuration for an instance of `CubicWeb` +ported for Google App Engine. It is installed with its own command ``laxctl`` +which is a port of the command tool ``cubicweb-ctl`` originally developped for +`CubicWeb`. + +You can have the details of available commands by running :: + + $ python myapp/bin/laxctl --help + + +Generating translation files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`LAX` is fully internationalized. Translation catalogs are found in +``myapp/i18n``. To compile the translation files, use the `gettext` tools +or the ``laxctl`` command :: + + $ python myapp/bin/laxctl i18nupdate + $ python myapp/bin/laxctl i18ncompile + +Ignore the errors that print "No translation file found for domain +'erudi'". They disappear after the first run of i18ncompile. + +.. note:: The command myapp/bin/laxctl i18nupdate needs to be executed + only if your application is using components from ginco-apps. + Otherwise, please skip it. + +You will never need to add new entries in the translation catalog. Instead we would +recommand you to use ``self.req._("msgId")`` in your application code +to flag new message id to add to the catalog, where ``_`` refers to +xgettext that is used to collect new strings to translate. +While running ``laxctl i18nupdate``, new string will be added to the catalogs. + +Generating the data directory +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In order to generate the ``myapp/data`` directory that holds the static +files like stylesheets and icons, you need to run the command:: + + $ python myapp/bin/laxctl populatedata + +Generating the schema diagram +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There is a view named ``schema`` that displays a diagram of the +entity-relationship graph defined by the schema. This diagram has to +be generated from the command line:: + + $ python myapp/bin/laxctl genschema + +Application configuration +------------------------- + +Authentication +~~~~~~~~~~~~~~ + +You have the option of using or not google authentication for your application. +This has to be define in ``app.conf`` and ``app.yaml``. + +In ``app.conf`` modify the following variable:: +  + # does this application rely on google authentication service or not. + use-google-auth=no + +In ``app.yaml`` comment the `login: required` set by default in the handler:: + + - url: .* + script: main.py + # comment the line below to allow anonymous access or if you don't want to use + # google authentication service + #login: required + + + + +Quickstart : launch the application +----------------------------------- + +On Mac OS X platforms, drag that directory on the +`GoogleAppEngineLauncher`. + +On Unix and Windows platforms, run it with the dev_appserver:: + + $ python /path/to/google_appengine/dev_appserver.py /path/to/myapp/ + +Once the local server is started, visit `http://MYAPP_URL/_load `_ and sign in as administrator. +This will initialize the repository and enable you to log in into +the application and continue the installation. + +You should be redirected to a page displaying a message `content initialized`. + +Initialize the datastore +~~~~~~~~~~~~~~~~~~~~~~~~ + +You, then, want to visit `http://MYAPP_URL/?vid=authinfo `_ . +If you selected not to use google authentication, you will be prompted to a +login form where you should initialize the administrator login (recommended +to use admin/admin at first). You will then be redirected to a page providing +you the value to provide to ``./bin/laxctl --cookie``. + +If you choosed to use google authentication, then you will not need to set up +and administrator login but you will get the cookie value as well. + +This cookie values needs to be provided to ``laxctl`` commands +in order to handle datastore administration requests. + +.. image:: images/lax-book.02-cookie-values.en.png + :alt: displaying the detailed view of the cookie values returned + + +.. note:: In case you are not redirected to a page providing the + option --cookie value, please visit one more time + `http://MYAPP_URL/?vid=authinfo `_ . + +Once, you have this value, then return to the shell and execute :: + + $ python myapp/bin/laxctl db-init --cookie='dev_appserver_login=test@example.com:True; __session=7bbe973a6705bc5773a640f8cf4326cc' localhost:8080 + +.. note:: In the case you are not using google authentication, the value returned + by `http://MYAPP_URL/?vid=authinfo `_ + will look like : + --cookie='__session=2b45d1a9c36c03d2a30cedb04bc37b6d' + +Log out by clicking in the menu at the top right corner +and restart browsing from `http://MYAPP_URL/ `_ +as a normal user. + +Unless you did something to change it, http://MYAPP_URL should be +http://localhost:8080/ + + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-actions.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-actions.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +Actions +========= + +[WRITE ME] + +* talk about actions that appear in the action box + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-boxes.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-boxes.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +Boxes +========= + +[WRITE ME] + +* boxes in the web interface + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-configuration.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-configuration.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +Configuration +------------- + +[WRITE ME] + +* the config object. adding configuration option + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-dbapi.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-dbapi.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +DB-API +========= + +[WRITE ME] + +* direct connection to the repository + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-embedding-external-page.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-embedding-external-page.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +Embedding external pages +======================== + +[WRITE ME] + +* including external content + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-online-doc.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-online-doc.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +Online documentation system +=========================== + +[WRITE ME] + +* describe the on-line documentation system + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-registry.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-registry.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,147 @@ +.. -*- coding: utf-8 -*- + +The Registry +------------ + +[WRITE ME] + +* talk about the vreg singleton, appobjects, registration and selection + + +Details of the recording process +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +At startup, the `registry` or registers base, inspects a number of directories +looking for compatible classes definition. After a recording process, the objects +are assigned to registers so that they can be selected dynamically while the +application is running. + +The base class of those objects is `AppRsetObject` (module `cubicweb.common.appobject`). + +XXX registers example +XXX actual details of the recording process! + +Runtime objects selection +~~~~~~~~~~~~~~~~~~~~~~~~~ + +XXX tell why it's a cw foundation! + +Application objects are stored in the registry using a two level hierarchy : + + object's `__registry__` : object's `id` : [list of app objects] + +The following rules are applied to select an object given a register and an id and an input context: +* each object has a selector + - its selector may be derivated from a set of basic (or not :) + selectors using `chainall` or `chainfirst` combinators +* a selector return a score >= 0 +* a score of 0 means the objects can't be applied to the input context +* the object with the greatest score is selected. If multiple objects have an + identical score, one of them is selected randomly (this is usually a bug) + +The object's selector is the `__select__` class method on the object's class. + +The score is used to choose the most pertinent objects where there are more than +one selectable object. For instance, if you're selecting the primary +(eg `id = 'primary'`) view (eg `__registry__ = 'view'`) for a result set containing +a `Card` entity, 2 objects will probably be selectable: + +* the default primary view (`accepts = 'Any'`) +* the specific `Card` primary view (`accepts = 'Card'`) + +This is because primary views are using the `accept_selector` which is considering the +`accepts` class attribute of the object's class. Other primary views specific to other +entity types won't be selectable in this case. And among selectable objects, the +accept selector will return a higher score the the second view since it's more +specific, so it will be selected as expected. + +Usually, you won't define it directly but by defining the `__selectors__` tuple +on the class, with :: + + __selectors__ = (sel1, sel2) + +which is equivalent to :: + + __select__ = classmethod(chainall(sel1, sel2)) + +The former is prefered since it's shorter and it's ease overriding in +subclasses (you have access to sub-selectors instead of the wrapping function). + +:chainall(selectors...): if one selector return 0, return 0, else return the sum of scores + +:chainfirst(selectors...): return the score of the first selector which has a non zero score + +XXX describe standard selector (link to generated api doc!) + +Example +```````` + +Le but final : quand on est sur un Blog, on veut que le lien rss de celui-ci pointe +vers les entrées de ce blog, non vers l'entité blog elle-même. + +L'idée générale pour résoudre ça : on définit une méthode sur les classes d'entité +qui renvoie l'url du flux rss pour l'entité en question. Avec une implémentation +par défaut sur AnyEntity et une implémentation particulière sur Blog qui fera ce +qu'on veut. + +La limitation : on est embêté dans le cas ou par ex. on a un result set qui contient +plusieurs entités Blog (ou autre chose), car on ne sait pas sur quelle entité appeler +la méthode sus-citée. Dans ce cas, on va conserver le comportement actuel (eg appel +à limited_rql) + +Donc : on veut deux cas ici, l'un pour un rset qui contient une et une seule entité, +l'autre pour un rset qui contient plusieurs entité. + +Donc... On a déja dans web/views/boxes.py la classe RSSIconBox qui fonctionne. Son +sélecteur :: + + class RSSIconBox(ExtResourcesBoxTemplate): + """just display the RSS icon on uniform result set""" + __selectors__ = ExtResourcesBoxTemplate.__selectors__ + (nfentity_selector,) + + +indique qu'il prend en compte : + +* les conditions d'apparition de la boite (faut remonter dans les classes parentes + pour voir le détail) +* nfentity_selector, qui filtre sur des rset contenant une liste d'entité non finale + +ça correspond donc à notre 2eme cas. Reste à fournir un composant plus spécifique +pour le 1er cas :: + + class EntityRSSIconBox(RSSIconBox): + """just display the RSS icon on uniform result set for a single entity""" + __selectors__ = RSSIconBox.__selectors__ + (onelinerset_selector,) + + +Ici, on ajoute onelinerset_selector, qui filtre sur des rset de taille 1. Il faut +savoir que quand on chaine des selecteurs, le score final est la somme des scores +renvoyés par chaque sélecteur (sauf si l'un renvoie zéro, auquel cas l'objet est +non sélectionnable). Donc ici, sur un rset avec plusieurs entités, onelinerset_selector +rendra la classe EntityRSSIconBox non sélectionnable, et on obtiendra bien la +classe RSSIconBox. Pour un rset avec une entité, la classe EntityRSSIconBox aura un +score supérieur à RSSIconBox et c'est donc bien elle qui sera sélectionnée. + +Voili voilou, il reste donc pour finir tout ça : + +* à définir le contenu de la méthode call de EntityRSSIconBox +* fournir l'implémentation par défaut de la méthode renvoyant l'url du flux rss sur + AnyEntity +* surcharger cette methode dans blog.Blog + + +When to use selectors? +``````````````````````` + +Il faut utiliser les sélecteurs pour faire des choses différentes en +fonction de ce qu'on a en entrée. Dès qu'on a un "if" qui teste la +nature de `self.rset` dans un objet, il faut très sérieusement se +poser la question s'il ne vaut pas mieux avoir deux objets différent +avec des sélecteurs approprié. + +If this is so fundamental, why don't I see them more often? +``````````````````````````````````````````````````````````` + +Because you're usually using base classes which are hiding the plumbing +of __registry__ (almost always), id (often when using "standard" object), +register and selector. diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-repository-operations.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-repository-operations.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +Repository operations +====================== + +[WRITE ME] + +* repository operations + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-repository-session.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-repository-session.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +Repository sessions +=================== + +[WRITE ME] + +* repository sessions + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-repository-tasks.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-repository-tasks.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +Tasks +========= + +[WRITE ME] + +* repository tasks + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-request.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-request.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +request +======= + +[WRITE ME] + +* the request object + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-sessions.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-sessions.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +sessions +======== + +[WRITE ME] + +* authentication and management of sessions + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-templates.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-templates.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +Templates +========= + +[WRITE ME] + +* talk about main templates, etc. + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/BXXX-urlrewrite.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/BXXX-urlrewrite.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,11 @@ +.. -*- coding: utf-8 -*- + +URL Rewriting +============= + +XXX FIXME this should be a chapter + +[WRITE ME] + +* show how urls are mapped to selections and views and explain URLRewriting + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/C000-administration.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/C000-administration.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,17 @@ +.. -*- coding: utf-8 -*- + + +========================== +Part III - Administration +========================== + +This part is for installation and administration of the `CubicWeb` framework and +applications based on that framework. + +.. toctree:: + :maxdepth: 1 + + C010-setup.en.txt + C020-site-config.en.txt + C030-instance-config.en.txt + C040-rql.en.txt diff -r 3159772915c4 -r d5acef862c58 doc/book/en/C010-setup.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/C010-setup.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,13 @@ +.. -*- coding: utf-8 -*- + +.. _MiseEnPlaceEnv: + +=================================================== +Installation and set-up of a `CubicWeb` environment +=================================================== +.. contents:: + +.. include:: C011-installation.en.txt +.. include:: C012-create-instance.en.txt +.. include:: C013-cubicweb-ctl.en.txt + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/C011-bis-installation.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/C011-bis-installation.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,79 @@ +.. -*- coding: utf-8 -*- + +.. _installationGAE: + +Installation de `CubicWeb` pour GoogleAppEngine +=============================================== + +Qu'est-ce que `LAX` ? +======================= + +`LAX` (Logilab Appengine eXtension) est un framework d'application +web basé sur `Google AppEngine`. + +`LAX` est un portage de la partie web de la plate-forme applicative +développée par Logilab depuis 2001. Cette plate-forme publie des +données tirées de bases SQL, d'annuaires LDAP et de systèmes de +gestion de version. En avril 2008, elle a été portée pour fonctionner +sur le "datastore" de `Google AppEngine`. + +XXX: faire un parallèle entre Django/GAE et LAX/GAE + + +Téléchargement des sources +========================== + +- Les sources de `Google AppEngine` peuvent être récupérées à l'adresse + suivante : http://code.google.com/appengine/downloads.html + +- Les sources de `LAX` se trouvent à l'adresse suivante : + http://lax.logilab.org/ + + +Installation +============ + +Une fois décompactée, l'archive `lax-0.1.0-alpha.tar.gz`, on obtient +l'arborescence suivante:: + + . + |-- app.yaml + |-- custom.py + |-- data + |-- ginco/ + |-- i18n/ + |-- logilab/ + |-- main.py + |-- mx/ + |-- rql/ + |-- schema.py + |-- simplejson/ + |-- tools/ + | |-- generate_schema_img.py + | `-- i18ncompile.py + |-- views.py + |-- yams/ + `-- yapps/ + + +On retrouve le squelette d'une application web de `Google AppEngine` +(fichiers ``app.yaml``, ``main.py`` en particulier) avec les dépendances +supplémentaires nécessaires à l'utilisation du framework `LAX` + + +Lancement de l'application de base +================================== + +Plusieurs répertoires doivent être accessibles via la variable +d'environnement ``PYTHONPATH`` :: + + $ export PYTHONPATH=/path/to/google_appengine:/path/to/google_appengine/lib/yaml/lib:/path/to/myapp/ + +Le répertoire yaml n'est nécessaire que pour le lancement des scripts +qui se trouvent dans lax/tools et pour l'exécution des tests unitaires. + +Pour démarrer:: + + $ python /path/to/google_appengine/dev_appserver.py /path/to/lax + + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/C011-installation.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/C011-installation.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,158 @@ +.. -*- coding: utf-8 -*- + +Installation +============ + +Installation of `Cubicweb` and its dependancies +----------------------------------------------- + +`CubicWeb` is available as a debian package as well as an archive. +We will detail here the two easiest way to set-up `CubciWeb` +environment. + +Debian packages +``````````````` +You need first to make sure that you added our public repository +in the list of sources you packages manager will search in. + +Depending on the debian distribution you are using here are all the +available options: :: + + deb http://ftp.logilab.org/dists/ lenny/ + deb http://ftp.logilab.org/dists/ hardy/ + deb http://ftp.logilab.org/dists/ sid/ + +As we assume you are installing `CubciWeb` on a debian machine, please +add the appropriate line from above in ``/etc/apt/sources.list``. + +You can now install the required packages with the follwoing command: :: + + apt-get install cubicweb + +This is it! + +``tar.gz`` archive +`````````````````` + +You can download our sources at: :: + + http://ftp.logilab.org/pub/cubicweb/ + +Unpack the sources + + + + +.. note:: + `CubicWeb` is also available as a Mercurial repository using the forest + extension (see :ref:`MercurialForestInstall` for more details). + + +Postgres installation +````````````````````` + +Please refer to the project online documentation Postgres_. + +.. _Postgres: http://www.postgresql.org/ + +You need to install the three following packages: `postgres-8.3`, +`postgres-contrib-8.3` and `postgresql-plpython-8.3`. + + +Then you can install: + +* `pyro` if you wish the repository is accessible through Pyro + or if the client and the server are not running on the same machine + (in suche case the packages will have to be isntalled on both + machines) + +* `python-ldap` if you plan to use a LDAP source on the server + +.. _ConfigurationEnv: + +Environment configuration +------------------------- + +[FIXME] +Ces variables ne sont plus requises pour le bon fonctionnement de `CubicWeb`, non? +A part rajouter la foret dans le PYTHONPATH, rien de plus ne doit etre fait? + +Update the environment variable PYTHONPATH to add to it the path to +the forest ``cubicweb``. + +Add the following lines to either `.bashrc` or `.bash_profile` to configure +your development environment :: + + export PYTHONPATH=/full/path/to/cubicweb-forest + + //deprecated?? + export ERUDI_REGISTRY=~/etc/erudi.d/ + export ERUDI_TEMPLATES=~/hg/ + export ERUDI_RUNTIME=/tmp/ + +Cela suppose que le composant erudi que vous développez est dans un +sous-répertoire de *~/hg/* et que vous avez créé le répertoire *~/etc/erudi.d/* +pour que `cubicweb-ctl` y place vos instances de test. + +.. _ConfigurationPostgres: + +Postgres configuration +---------------------- + +* First you have to initialize the database Postgres with the command ``initdb``. + :: + + $ initdb -D /path/to/pgsql + + Once initialized, you can launch the database server Postgres + with the command: :: + + $ postgres -D /path/to/psql + + If you cannot execute this command due to permission issues, please + make sure that your username has write access on the database. + :: + + $ chown username /path/to/pgsql + +* Create a superuser for `CubicWeb` instance (**root**) :: + + createuser -s username + + Initialize the password of the superuser you juste created with + ``su - postgres`` and ``psql``. + + This password will be asked to you later on where you will create an + instance with `cubicweb-ctl create` + +[XXX] +Est-ce que ces etapes sont vraiment necessaires? +sand : lors de l'installation de ma bdd cela n'a pas ete fait +et il semble que tout aille bien. Doit etre verifie avec les experts. + +* installation of plain-text index extension :: + + cat /usr/share/postgresql/8.3/contrib/tsearch2.sql | psql -U username template1 + +* installation of plpythonu language by default :: + + createlang -U pgadmin plpythonu template1 + + +Pyro configuration +------------------ + +If you use Pyro, it is required to have a name server Pyro runing on your +network (by default it is identified by a broadcast request). + +To do so, you need to : + +* launch the server manually before starting cubicweb with `pyro-ns` + +* launch the server manually before starting cubicweb as a server with + `pyro-nsd start` + +* edit the file ``/etc/default/pyro-nsd`` so that the name server pyro + will be launched automatically when the macine fire up + + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/C012-create-instance.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/C012-create-instance.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,123 @@ +.. -*- coding: utf-8 -*- + +Creation of your first instance +=============================== + +What is an instance? +-------------------- + +A `CubicWeb` instance is a directory in ``~/etc/cubicweb.d`` +which enables us to run a web application. An instance is based on +one or more cubes. + +An instance is a container that refers to cubes and configuration +parameters for your web application. + +We recommand not to define schema, entities or views in the instance +file system itself but in the cube, in order to maintain re-usability of +entities and their views. We strongly recommand to develop cubes which +could be used in other instances (modular approach). + + +What is a cube? +--------------- + +A cube defines entities, their views, their schems and workflows +in an independant directory located in ``/path/to/forest/cubicweb/cubes/``. + +When an instance is created, you list one or more cubes that your instance +will use. Use a cube means having the entities defined in your cube's schema +available in your instance as well as their views and workflows. + +.. note:: + The commands used below are more detailled in the section dedicated to + :ref:`cubicweb-ctl`. + + +Create a cube +------------- + +Let's start by creating the cube environment in which we will develop :: + + cd ~/hg + + cubicweb-ctl newcube mycube + + # answer questions + hg init moncube + cd mycube + hg add . + hg ci + +If all went well, you should see the cube you just create in the list +returned by `cubicweb-ctl list` in the section *Available components*, +and if it is not the case please refer to :ref:`ConfigurationEnv`. + +To use a cube, you have to list it in the variable ``__use__`` +of the file ``__pkginfo__.py`` of the instance. +This variable is used for the instance packaging (dependencies +handled by system utility tools such as APT) and the usable cubes +at the time the base is created (import_erschema('MyCube') will +not properly work otherwise). + +Instance creation +----------------- + +Now that we created our cube, we can create an instance to view our +application in a web browser. To do so we will use a `all-in-on` +configuration to simplify things :: + + cubicweb-ctl create -c all-in-one mycube myinstance + +.. note:: + Please note that we created a new cube for a demo purpose but + you could have use an existing cube available in our standard library + such as blog or person by example. + +A serie of questions will be prompted to you, the default answer is usually +sufficient. You can anyway modify the configuration later on by editing +configuration files. When a user/psswd is requested to access the database +please use the login you create at the time you configured the database +(:ref:`ConfigurationPostgres`). + +It is important to distinguish here the user used to access the database and +the user used to login to the cubicweb application. When a `CubicWeb` application +starts, it uses the login/psswd for the database to get the schema and handle +low transaction [FIXME - bas niveau]. But, when ``cubicweb-ctl create`` asks for +a manager login/psswd of `CubicWeb`, it refers to an application user you will +use during the development to administrate your web application. It will be +possible, later on, to create others users for your final web application. + +When this command is completed, the definition of your instance is +located in *~/etc/cubicweb.d/moninstance/*. To launch it, you just type :: + + cubicweb-ctl start -D myinstance + +The option `-D` specify the *debug mode* : the instance is not running in +server mode and does not disconnect from the termnial, which simplifies debugging +in case the instance is not properly launched. You can see how it looks by +visiting the URL `http://localhost:8080` (the port number depends of your +configuration). To login, please use the cubicweb administrator login/psswd you +defined when you created the instance. + +To shutdown the instance, Crtl-C in the terminal window is enough. +If you did not use the option `-D`, then type :: + + cubicweb-ctl stop myinstance + +This is it! All is settled down to start developping your data model... + + +Usage of `cubicweb-liveserver` +`````````````````````````````` + +To quickly test a new cube, you can also use the script `cubicweb-liveserver` +which allows to create an application in memory (use of SQLite database by +default) and make it accessible through a web server :: + + cubicweb-ctl live-server mycube + +or by using an existing database (SQLite or Postgres):: + + cubicweb-ctl live-server -s myfile_sources mycube + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/C013-cubicweb-ctl.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/C013-cubicweb-ctl.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,123 @@ +.. -*- coding: utf-8 -*- + +.. _cubicweb-ctl: + +``cubicweb-ctl`` tool +===================== + +`cubicweb-ctl` is the swiss knife to manage `CubicWeb` instances. +The general syntax is :: + + cubicweb-ctl [options command] + +To view available commands :: + + cubicweb-ctl + cubicweb-ctl --help + +Please note that the commands available depends on the `CubicWeb` packages +and cubes that have been installed. + +To view the help menu on specific command :: + + cubicweb-ctl --help + +Command to create a cube +------------------------ + +* ``newcube``, create a new cube on the file system based on the name + given in the parameters. This command create a cube from an application + skeleton that includes default files required for debian packaging. + + +Command to create an instance +----------------------------- +* ``create``, creates the files for the instance configuration +* ``db-create``, creates the system database of an instance (tables and + extensions only) +* ``db-init``, initializes the system database of an instance + (schema, groups, users, workflows...) + +By default, those three commandes are encapsulated in ``create`` so +that they can be executed consecutively. + +Command to create an instance for Google AppEngine datastore source +------------------------------------------------------------------- +* ``newgapp``, creates the configuration files for an instance + +This command needs to be followed by the commands responsible for +the database initialization. As those are specific to the `datastore`, +specific Google AppEgine database, they are not available for now +in cubicweb-ctl, but they are available in the instance created. + +[FIXME] - add link to gae install +For more details, please see :ref:`` . + +Commands to launch instance +--------------------------- +* ``start``, starts one or more or all instances +* ``stop``, stops one or more or all instances +* ``restart``, restarts one or more or all instances +* ``status``, returns the status of the instance + +Commands to maintain instances +------------------------------ +* ``upgrade``, launches the existing instances migration when a new version + of `CubicWeb` or the cubes installed is available +* ``shell``, opens a migration shell for manual maintenance of the instance +* ``db-dump``, creates a dump of the system database +* ``db-restore``, restores a dump of the system database +* ``db-check``, checks data integrity of an instance. If the automatic correction + is activated, it is recommanded to create a dump before this operation. +* ``schema-sync``, synchronizes the persistent schema of an instance with + the application schema. It is recommanded to create a dump before this operation. + +Commands to maintain i18n catalogs +---------------------------------- +* ``i18nlibupdate``, regenerates messages catalogs of the `CubicWeb` library +* ``i18nupdate``, regenerates the messages catalogs of a cube +* ``i18ncompile``, recompiles the messages catalogs of an instance. + This is automatically done while upgrading. + +Cf :ref:`Internationalisation`. + +Other commands +-------------- +* ``list``, provides a list of the available configuration, cubes + and instances. +* ``delete``, deletes an instance (configuration files and database) + +Examples +-------- + +Create an instance from an existing cube +```````````````````````````````````````` + +To create an instance from an existing cube, execute the following +command :: + + cubicweb-ctl create + +This command will create the configuration files of an instance in +``~/etc/cubicweb.d/``. +The tool ``cubicweb-ctl`` allows you to execute the command ``db-create`` +and ``db-init`` when you run ``create`` so that you can complete an +instance creation in a single command. + +If you decide not to execut those commands while ``cubicweb-ctl create``, +then you will have to execute them seperately(``cubicweb-ctl db-create``, +``cubicweb-ctl db-init`` ) otherwise your installation will not be complete +and you will not be able to launch your instance. + + +Creation of an instance from a new cube +``````````````````````````````````````` + +Create first your new cube cube :: + + cubicweb-ctl newcube + +This will create a new cube in ``/path/to/forest/cubicweb/cubes/`` +and then create an instance as explained just above. + + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/C020-site-config.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/C020-site-config.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,94 @@ +.. -*- coding: utf-8 -*- + +Interface de configuration du site +================================== + +.. image:: images/lax-book.03-site-config-panel.en.png + +This panel allows you to configure the appearance of your application site. +Six menus are available and we will go through each of them to explain how +to use them. + +Navigation +~~~~~~~~~~ +This menu provides you a way to adjust some navigation options depending on +your needs, such as the number of entities to display by page of results. +Follows the detailled list of available options : + +* navigation.combobox-limit : maximum number of entities to display in related + combo box (sample format: 23) +* navigation.page-size : maximum number of objects displayed by page of results + (sample format: 23) +* navigation.related-limit : maximum number of related entities to display in + the primary view (sample format: 23) +* navigation.short-line-size : maximum number of characters in short description + (sample format: 23) + +UI +~~ +This menu provides you a way to customize the user interface settings such as +date format or encoding in the produced html. +Follows the detailled list of available options : + +* ui.date-format : how to format date in the ui ("man strftime" for format description) +* ui.datetime-format : how to format date and time in the ui ("man strftime" for format + description) +* ui.default-text-format : default text format for rich text fields. +* ui.encoding : user interface encoding +* ui.fckeditor :should html fields being edited using fckeditor (a HTML WYSIWYG editor). + You should also select text/html as default text format to actually get fckeditor. +* ui.float-format : how to format float numbers in the ui +* ui.language : language of the user interface +* ui.main-template : id of main template used to render pages +* ui.site-title : site title, which is displayed right next to the logo in the header +* ui.time-format : how to format time in the ui ("man strftime" for format description) + + +Actions +~~~~~~~ +This menu provides a way to configure the context in which you expect the actions +to be displayed to the user and if you want the action to be visible or not. +You must have notice that when you view a list of entities, an action box is +available on the left column which display some actions as well as a drop-down +menu for more actions. + +The context available are : + +* mainactions : actions listed in the left box +* moreactions : actions listed in the `more` menu of the left box +* addrelated : add actions listed in the left box +* useractions : actions listed in the first section of drop-down menu + accessible from the right corner user login link +* siteactions : actions listed in the second section of drop-down menu + accessible from the right corner user login link +* hidden : select this to hide the specific action + +Boxes +~~~~~ +The application has already a pre-defined set of boxes you can use right away. +This configuration section allows you to place those boxes where you want in the +application interface to customize it. + +The available boxes are : + +* actions box : box listing the applicable actions on the displayed data + +* boxes_blog_archives_box : box listing the blog archives + +* possible views box : box listing the possible views for the displayed data + +* rss box : RSS icon to get displayed data as a RSS thread + +* search box : search box + +* startup views box : box listing the configuration options available for + the application site, such as `Preferences` and `Site Configuration` + +Components +~~~~~~~~~~ +[WRITE ME] + +Contextual components +~~~~~~~~~~~~~~~~~~~~~ +[WRITE ME] + diff -r 3159772915c4 -r d5acef862c58 doc/book/en/C030-instance-config.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/C030-instance-config.en.txt Tue Nov 25 17:45:11 2008 +0100 @@ -0,0 +1,162 @@ +.. -*- coding: utf-8 -*- + +Configuration d'une instance +============================ + +À la création d'une instance, un fichier de configuration est généré dans :: + + $(CW_REGISTRY)//.conf + +par exemple :: + + /etc/cubicweb.d/jpl/all-in-one.conf + +C'est un simple fichier texte au format INI. Dans la description suivante, +chaque nom d'option est préfixé de sa section et suivi de sa valeur par défaut +le cas échéant, e.g. "`
      .