# HG changeset patch # User Nicolas Chauvat # Date 1226657132 -3600 # Node ID 9a9fe515934d66ff5a681cf6d106cfd6bf4f780e # Parent 58fd269f626ba03d1bf8b334a10ffcd92fc21288 [doc] reuse the lax book diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/01-intro.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/01-intro.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,85 @@ +.. -*- coding: utf-8 -*- + +Introduction +============ + +This book uses version 0.4.0 of `LAX`. + +What is `LAX` ? +---------------- + +`LAX` stands for `Logilab Appengine eXtension`. It is a web application framework +based on `Google AppEngine`. + +`LAX` is a port of the web framework Logilab_ has been developping since 2001. +This framework originally published data queried from different sources including +SQL databases, LDAP directories and concurrent versionning systems +(like subversion). In April/May 2008, it was adapted to run also on +top of `Google AppEngine`'s datastore. + +`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]_. + +`LAX` competes with other Python web application frameworks to get +developers' attention and support. It originates from Logilab and is +the result of about ten years of experience in developing large-scale +web applications. + +Distinctive features include a data-model driven engine, a full-blown +query language, a selection/view mechanism for HTML/XML/text +generation, reuseable components, etc. It all sums up to very fast and +efficient development. + +If you like Python and its standard library, chances are you will like +`LAX` for it comes with batteries included thanks to its standard +component library. + +Compare `LAX` with other frameworks and see for yourself what is your +best option. + +.. _Logilab: http://www.logilab.fr/ +.. [1] for more on this matter, read our blog at http://www.logilab.org/blog/5216 + +Essentials +---------- + +Schema + + The schema defines the data model of an application as entities and + relationships. It is the core of an application. Entities and + relationships are modeled with a comprehensive language made of + Python classes. + +Query language + + A full-blown query language named RQL is used to formulate + requests to the datastore. + +Result set + + A resultset encapsulates the results of a request sent to + the datastore and informations about this request. + +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. + +Components + + Pieces of schema and sets of views can be combined into + components. Larger applications can be built faster by importing + components, adding entities and relationships and overriding the + views that need to display or edit informations not provided by + components. diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/02-install.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/02-install.en.txt Fri Nov 14 11:05:32 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 58fd269f626b -r 9a9fe515934d doc/book/en/03-create-app.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/03-create-app.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,201 @@ +.. -*- coding: utf-8 -*- + + +Creating your first application +=============================== + +This tutorial will guide you step by step to build a blog application +and discover the unique features of `LAX`. It assumes that you followed +the installation guidelines and that both the `AppEngine SDK` and the +`LAX` framework are setup on your computer. + +Creating a new application +-------------------------- + +When you installed `LAX`, you saw a directory named ``skel``. Make a copy of +this directory and call it ``BlogDemo``. + +Defining a schema +----------------- + +With `LAX`, the schema/datamodel is the core of the application. + +Let us start with something simple and improve on it iteratively. + +In schema.py, we define two entities : ``Blog`` and ``BlogEntry``. + +:: + + class Blog(EntityType): + title = String(maxsize=50, required=True) + description = String() + + class BlogEntry(EntityType): + title = String(maxsize=100, required=True) + publish_date = Date(default='TODAY') + text = String(fulltextindexed=True) + category = String(vocabulary=('important','business')) + entry_of = SubjectRelation('Blog', cardinality='?*') + +A Blog has a title and a description. The title is a string that is +required 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 text. 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 text 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 link 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`. + +Using the application +--------------------- + +Defining this simple schema is enough to get us started. Make sure you +followed the setup steps described in detail in the installation +chapter (especially visiting http://localhost:8080/_load as an +administrator), then launch the application with the command:: + + python dev_appserver.py BlogDemo + +and point your browser at http://localhost:8080/ (if it is easier for +you, use the on-line demo at http://lax.appspot.com/). + +.. image:: images/lax-book.00-login.en.png + :alt: login screen + +After you log in, you will see the home page of your application. It +lists the entity types: Blog and BlogEntry. If these links read +``blog_plural`` and ``blogentry_plural`` it is because +internationalization (i18n) is not working for you yet. Please ignore +this for now. + +.. image:: images/lax-book.01-start.en.png + :alt: home page + +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 ``button_ok``. + +.. image:: images/lax-book.02-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. You should be seeing a list with a single item +``Tech-blog``. + +.. image:: images/lax-book.03-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``. + +.. image:: images/lax-book.04-detail-one-blog.en.png + :alt: displaying the detailed view of a blog + +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/lax-book.05-list-two-blog.en.png + :alt: displaying a list of two blogs + +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 ``button_ok``. 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``. + +.. image:: images/lax-book.06-add-relation-entryof.en.png + :alt: editing a blog entry to add a relation to a blog + +Validate the changes by clicking ``button_ok``. The entity BlogEntry +that is displayed now includes a link to the entity Blog named +``MyLife``. + +.. image:: images/lax-book.07-detail-one-blogentry.en.png + :alt: displaying the detailed view of a blogentry + +Remember 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, run the ``laxctl genschema BlogDemo`` command as +explained in the installation section and point your browser to the +URL http://localhost:8080/schema + +.. image:: images/lax-book.08-schema.en.png + :alt: graphical view of the schema (aka data-model) + +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. + +Create states and transitions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Let us create a state `submitted`. Click on the [+] at the right +of the link States. Call this new Blog ``submitted`` and type in +``Initial State of a BlogEntry`` as the description, then validate the +form by clicking on ``Apply``. This will leave us in the editing form +with an additional section to create the relations related to the +entity State we juste created. Select the relation ``initial_state_of`` +and select the entity type ``BlogEntry``. + +.. image:: images/lax-book.03-state-submitted.en.png + + + + +Create group and set permissions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +Change view permission +~~~~~~~~~~~~~~~~~~~~~~ + + +Conclusion +---------- + +Exercise +~~~~~~~~ + +Create new blog entries in ``Tech-blog``. + +What we learned +~~~~~~~~~~~~~~~ + +Creating a simple schema was enough to set up a new application that +can store blogs and blog entries. + +What is next ? +~~~~~~~~~~~~~~ + +Although the application is fully functionnal, its look is very +basic. In the following section we will learn to create views to +customize how data is displayed. diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/03-definition-schema.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/03-definition-schema.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,20 @@ +.. -*- 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-sect-stdlib-schemas.en.txt +.. include:: 03-sect-definition-schema.en.txt diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/03-sect-definition-schema.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/03-sect-definition-schema.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,344 @@ +.. -*- 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 58fd269f626b -r 9a9fe515934d doc/book/en/03-sect-stdlib-schemas.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/03-sect-stdlib-schemas.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,86 @@ +.. -*- 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 58fd269f626b -r 9a9fe515934d doc/book/en/04-develop-views.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/04-develop-views.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,126 @@ +.. -*- coding: utf-8 -*- + + +Developing the user interface with Views +======================================== + +Before moving to this section, make sure you read the `Essentials` +section in the Introduction. + +Tip: when modifying views, you do not need to restart the local +server. Just save the file in your editor and reload the page in your +browser to see the changes. + +The selection/view principle +---------------------------- + +With `LAX`, views are defined by Python classes. 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 + +`LAX` provides a lot of standard views, for a complete list, you +will have to read the code in directory ``ginco/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 `LAX`. 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 ginco.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. diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/05-components.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/05-components.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,150 @@ +.. -*- 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 58fd269f626b -r 9a9fe515934d doc/book/en/06-maintemplate.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/06-maintemplate.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,210 @@ +.. -*- 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. + +1 +[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 58fd269f626b -r 9a9fe515934d doc/book/en/07-rss-xml.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/07-rss-xml.en.txt Fri Nov 14 11:05:32 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 58fd269f626b -r 9a9fe515934d doc/book/en/08-rql.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/08-rql.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,211 @@ +.. -*- coding: utf-8 -*- + +RQL language (Relation Query Language) +======================================== + +Introduction +------------ +* RQL language focuses on browsing relations. +* Attributes are considered as particular relations. +* RQL is inspired from SQL but is a high level language. +* A good knowledge of Erudi's schemas defining the application is required. + + +Types of requests +----------------- + +Search (`Any`) + query the repository to extract entities and/or attributes. + +Insertion (`INSERT`) + insert new entities in the database. + +Updates of entities, creation of relations (`SET`) + update existing entities in the database, or create relations between existing + entities + +Deletion of entities or relations (`DELETE`) + delete existing entities and relations from the database. + + +Variables and typing +-------------------- + +Entities and values to browse and/or select are set in the query through *variables* +which should be written in capital letters. + +The possible types for each variable can be deducted from the schema depending on +the conditions expressed in the query. + +You can force the possible types for a variable thanks to the special relation `is`. + + + +Built-in types +-------------- +* `String` (literal: between double or single quotes). +* `Int`, `Float` (separator is '.'). +* `Date`, `Datetime`, `Time` (literal: pattern YYYY/MM/DD[ hh:mm] or keywords + `TODAY` and `NOW`). +* `Boolean` (keywords `TRUE` et `FALSE`). +* keyword `NULL`. + +Operators +---------- +* Logical operators: `AND`, `OR`, `,`. +* Mathematical operators: `+`, `-`, `*`, `/`. +* Comparison operators: `=`, `<`, `<=`, `>=`, `>`, `~=`, `LIKE`, `IN`. + + * The operator `=` is the default operator. + + * The operator `LIKE` / `~=` allows the use of the character `%` in a string + to indicate that the string should start/end with a prefix/suffix:: + + Any X WHERE X nom ~= 'Th%' + Any X WHERE X nom LIKE '%lt' + + * The operator `IN` allows to provide a list of possible values:: + + Any X WHERE X nom IN ('chauvat', 'fayolle', 'di mascio', 'thenault') + +Search query +------------ + + [`DISTINCT`] V1(, V2)\* + [`GROUPBY` V1(, V2)\*] [`ORDERBY` ] + [`WHERE` ] + [`LIMIT` ] [`OFFSET` ] + +:entity type: + Type of the selected variable + Special type `Any` is equivalent to not specify a type +:condition: + list of relations to browse following the pattern + `V1 relation V2|` +:orderterms: + Setting of the selection order : variable or column number followed by the + sorting method (`ASC`, `DESC`), ASC being the default value. +:note for grouped queries: + For grouped queries (e.g. using function `GROUPBY`), all the selected + variables must be grouped or aggregated. + +Examples - search +````````````````` +:: + + Any X WHERE X eid 53 + Personne X + Personne X WHERE X travaille_pour S, S nom "logilab" + Any E,COUNT(X) GROUPBY E ORDERBY EN WHERE X is E, E name EN + Any E,COUNT(X) GROUPBY E ORDERBY 2 WHERE X is E + + +Advanced features +````````````````` +* Aggregate functions : `COUNT`, `MIN`, `MAX`, `SUM`. +* String functions :`UPPER`, `LOWER`. +* Optional relations : + + * They allow to select entities related to others or not. + + * You should use `?` behind the variable to specify the relation to itself is + optional. + + - Project anomalies related to a version or not :: + + Any X,V WHERE X concerns P, P eid 42, X corrected_in V? + + - All the cards and the project they document otherwise :: + + Any C,P WHERE C is Card, P? documented_by C + +Negation +```````` +* A query such as `Document X WHERE NOT X owned_by U` is equivalent to + "the documents which do not have relation `owned_by`". +* Whereas the query `Document X WHERE NOT X owned_by U, U login "syt"` + is equivalent to "the documents which do not have relation `owned_by` + with the user syt". They could have a relation with other users. + + +Identity +```````` + +We could use the special relation `identity` in a query in order to add a +condition of identity between two variables. This is equivalent to ``is`` +in Python. + + Any A WHERE A comments B, A identity B + +returns the set of objects which comment themselves. The relation `identity` +is very usefull while defining security rules with `RQLExpressions`. + +Insertion queries +----------------- + `INSERT` V1(, V2)\* `:` + [`WHERE` ] + +:assignments: + list of relations to assign such as `V1 relation V2|` + +The condition allow to define the variables we would use in assignments. + +Be careful, if a condition is specified, the insertion is done *for each result +returned by the condition*. + +Examples - insertion +````````````````````` +* Insertion of a new person named 'bidule':: + + INSERT Person X: X name 'bidule' + +* Insertion of a new person named 'bidule', another named + 'chouette' and a relation 'friend' between them:: + + INSERT Person X, Person Y: X name 'bidule', Y name 'chouette', X friend Y + +* Insertion of a new person named 'bidule' and a relation 'friend'with an + existing person 'chouette':: + + INSERT Person X: X name 'bidule', X friend Y WHERE Y name 'chouette' + + +Update queries +-------------- + `SET` + [`WHERE` ] + +Be careful, if a condition is specified, the update is done *for each result +returned by the condition*. + +Examples - update +````````````````` +* Renaming of the person named 'bidule' to 'toto', with change on the first name:: + + SET X name 'toto', X firstname 'original' WHERE X is 'Person', X name 'bidule' + +* Insertion of a relation of type 'know' between two objects linked with the relation + of type 'friend' :: + + SET X know Y WHERE X friend Y + +Deletion queries +---------------- + `DELETE` ( V) | (V1 relation v2),... + [`WHERE` ] + + +Be careful, if a condition is specified, the deletion is done *for each result +returned by the condition*. + + +Examples +```````` +* Deletion of the person named 'toto':: + + DELETE Person X WHERE X name 'toto' + +* Deletion of all the relations of type 'friend' linked to the person named + 'toto':: + + DELETE X friend Y WHERE X is 'Person', X name 'toto' diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/09-urlrewrite.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/09-urlrewrite.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,9 @@ +.. -*- coding: utf-8 -*- + +URL Rewriting +============= + +[WRITE ME] + +* show how urls are mapped to selections and views and explain URLRewriting + diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/10-security.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/10-security.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,10 @@ +.. -*- coding: utf-8 -*- + +Security +========= + +[WRITE ME] + +* talk about security access rights and show that security is defined + using RQL + diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/11-definition-workflow.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/11-definition-workflow.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,43 @@ +.. -*- coding: utf-8 -*- + +Defining a Workflow +=================== + +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] diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/11-faq.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/11-faq.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,54 @@ +.. -*- coding: utf-8 -*- + +Frequently Asked Questions +========================== + +* Why does not LAX have a template language ? + + It does. Actually, you can use your preferred template language if you + want. [explain how to use a template language] + + The reason template languages are not used in this book is that + experience has proved us that using pure python was more efficient. + +* Why do you think using pure python is better than using a template language ? + + [copy answer from forum] + + code is easier to maintain, does not have to learn a new dialect + each time, real function/classes etc -> real development + +* Why do you use the GPL license to prevent me from doing X ? + + [copy answer from forum] + +* LAX looks pretty recent. Is it stable ? + + [answer that framework has evolved over the past seven years and that + data migrated from one schema to the other ever since] + +* Why is the RQL query language looking similar to X ? + + [copy answer from forum, explain why similar to sparql and why better + than django and SQL] + +* which ajax library + + [we use mochikit and things on top of that] + +* `Error while publishing rest text ...` + + While modifying the description of an entity, you get an error message in + the application `Error while publishing ...` for Rest text and plain text. + The server returns a traceback like as follows : + 2008-10-06 15:05:08 - (erudi.rest) ERROR: error while publishing ReST text + Traceback (most recent call last): + File "/home/sandrine/src/blogdemo/ginco/common/rest.py", line 217, in rest_publish + File "/usr/lib/python2.5/codecs.py", line 817, in open + file = __builtin__.open(filename, mode, buffering) + TypeError: __init__() takes at most 3 arguments (4 given) + + + This can be fixed by applying the patch described in : + http://code.google.com/p/googleappengine/issues/detail?id=48 +[ADD MORE FAQ] diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/12-internationalization.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/12-internationalization.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,73 @@ +.. -*- coding: utf-8 -*- + +.. _internationalization: + + +Internationalization +==================== + +The internationalization + +Le système d'internationalisation de l'interface web d'erudi 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 erudi-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. erudi-ctl intègre pour cela les commandes suivantes : + +* `i18nlibupdate`, met à jour les catalogues de messages *de la librairie + erudi*. 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/erudi.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 58fd269f626b -r 9a9fe515934d doc/book/en/12-reference.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/12-reference.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,33 @@ +.. -*- coding: utf-8 -*- + +API Reference +============= + +Schema API +---------- + +Base Types +~~~~~~~~~~ + +Base types are defined as a set in yams.BASE_TYPES that includes: +`String`, `Int`, `Float`, `Boolean`, `Date`, `Time`, `Datetime`, +`Interval`, `Password`, `Bytes`. + +See `yams' API `_ + +Constraints +~~~~~~~~~~~ + +Constraints are defined in yams.constraints and include: +`UniqueConstraint`, `SizeConstraint`, `RegexpConstraint`, +`BoundConstraint`, `IntervalBoundConstraint`, +`StaticVocabularyConstraint`, `MultipleStaticVocabularyConstraint`. + +See `yams' API `_ + +Views API +--------- + +See `yams' API `_ +[WRITE ME] + diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/faq.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/faq.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,56 @@ +.. -*- coding: utf-8 -*- + +Frequently Asked Questions +========================== + +* Why does not LAX have a template language ? + + It does. Actually, you can use your preferred template language if you + want. [explain how to use a template language] + + The reason template languages are not used in this book is that + experience has proved us that using pure python was more efficient. + +* Why do you think using pure python is better than using a template language ? + + [copy answer from forum] + + code is easier to maintain, does not have to learn a new dialect + each time, real function/classes etc -> real development + +* Why do you use the GPL license to prevent me from doing X ? + + [copy answer from forum] + +* LAX looks pretty recent. Is it stable ? + + [answer that framework has evolved over the past seven years and that + data migrated from one schema to the other ever since] + +* Why is the RQL query language looking similar to X ? + + [copy answer from forum, explain why similar to sparql and why better + than django and SQL] + +* which ajax library + + [we use mochikit and things on top of that] + +* `Error while publishing rest text ...` + + While modifying the description of an entity, you get an error message in + the application `Error while publishing ...` for Rest text and plain text. + The server returns a traceback like as follows :: + + 2008-10-06 15:05:08 - (erudi.rest) ERROR: error while publishing ReST text + Traceback (most recent call last): + File "/home/sandrine/src/blogdemo/ginco/common/rest.py", line 217, in rest_publish + (...) + File "/usr/lib/python2.5/codecs.py", line 817, in open + file = __builtin__.open(filename, mode, buffering) + TypeError: __init__() takes at most 3 arguments (4 given) + + This can be fixed by applying the patch described in : + `Google group appengine `_ + +[ADD MORE FAQ] diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/lax-book.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/lax-book.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,27 @@ +.. LAX documentation master file, created by sphinx-quickstart on Wed Sep 10 08:23:04 2008. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +.. _contents: + +LAX book +======== + + +.. toctree:: + :maxdepth: 2 + + + 01-intro.en.txt + 02-install.en.txt + 03-definition-schema.en.txt + 04-develop-views.en.txt + 05-components.en.txt + 06-maintemplate.en.txt + 07-rss-xml.en.txt + 08-rql.en.txt + 09-urlrewrite.en.txt + 10-security.en.txt + 11-definition-workflow.en.txt + 12-internationalization.en.txt + diff -r 58fd269f626b -r 9a9fe515934d doc/book/en/reference.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/reference.en.txt Fri Nov 14 11:05:32 2008 +0100 @@ -0,0 +1,33 @@ +.. -*- coding: utf-8 -*- + +API Reference +============= + +Schema API +---------- + +Base Types +~~~~~~~~~~ + +Base types are defined as a set in yams.BASE_TYPES that includes: +`String`, `Int`, `Float`, `Boolean`, `Date`, `Time`, `Datetime`, +`Interval`, `Password`, `Bytes`. + +See `yams' API `_ + +Constraints +~~~~~~~~~~~ + +Constraints are defined in yams.constraints and include: +`UniqueConstraint`, `SizeConstraint`, `RegexpConstraint`, +`BoundConstraint`, `IntervalBoundConstraint`, +`StaticVocabularyConstraint`, `MultipleStaticVocabularyConstraint`. + +See `yams' API `_ + +Views API +--------- + +See `yams' API `_ +[WRITE ME] +