# HG changeset patch # User Nicolas Chauvat # Date 1227213055 -3600 # Node ID 4b66ad23fbd183b2c1ee5ac7d4d138244891cad3 # Parent 9ecd54ea0634ce6d81d735d7da3e1c6b023ada48 [doc] merge old lax book with the rest diff -r 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/01-00-introduction.en.txt --- a/doc/book/en/01-00-introduction.en.txt Thu Nov 20 20:36:03 2008 +0100 +++ b/doc/book/en/01-00-introduction.en.txt Thu Nov 20 21:30:55 2008 +0100 @@ -227,11 +227,9 @@ .. image:: images/cbw-detail-one-blogentry.en.png :alt: displaying the detailed view of a blogentry -Please notice that so far, `CubicWeb` franework managed all aspects of -the web application based in the schema provided at first. -Also if you wish to get a graphical view of the schema, visit -the link `Application schema`` which will direct you to : -http://localhost:8080/view?vid=schema +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) diff -r 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/01-05-components.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/01-05-components.en.txt Thu Nov 20 21:30:55 2008 +0100 @@ -0,0 +1,152 @@ +.. -*- coding: utf-8 -*- + +.. _components: + +Components +=========== + +XXXFIXME TURN THIS INTO A CHAPTER + +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 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/01-06-maintemplate.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/01-06-maintemplate.en.txt Thu Nov 20 21:30:55 2008 +0100 @@ -0,0 +1,209 @@ +.. -*- 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 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/01-07-rss-xml.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/01-07-rss-xml.en.txt Thu Nov 20 21:30:55 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 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/16-00-rql.en.txt --- a/doc/book/en/16-00-rql.en.txt Thu Nov 20 20:36:03 2008 +0100 +++ b/doc/book/en/16-00-rql.en.txt Thu Nov 20 21:30:55 2008 +0100 @@ -1,11 +1,216 @@ .. -*- coding: utf-8 -*- -Le langage RQL (Relation Query Language) -======================================== +RQL language (Relation Query Language) +====================================== + +XXX see also RQL documentation in source rql/doc. + + +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`. + + -Voir la `documentation de RQL `_ . +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 -[TODO] -Specific link to RQL complete documentation to remove duplicated content. +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 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/20-00-google-appengine.en.txt --- a/doc/book/en/20-00-google-appengine.en.txt Thu Nov 20 20:36:03 2008 +0100 +++ b/doc/book/en/20-00-google-appengine.en.txt Thu Nov 20 21:30:55 2008 +0100 @@ -9,11 +9,3 @@ .. include:: 20-01-intro.en.txt .. include:: 20-02-install.en.txt -.. include:: 20-03-create-app.en.txt -.. include:: 20-04-develop-views.en.txt -.. include:: 20-05-components.en.txt -.. include:: 20-06-maintemplate.en.txt -.. include:: 20-07-rss-xml.en.txt -.. include:: 20-08-rql.en.txt -.. include:: 20-09-urlrewrite.en.txt -.. include:: 20-10-security.en.txt diff -r 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/20-02-install.en.txt --- a/doc/book/en/20-02-install.en.txt Thu Nov 20 20:36:03 2008 +0100 +++ b/doc/book/en/20-02-install.en.txt Thu Nov 20 21:30:55 2008 +0100 @@ -5,9 +5,6 @@ Installation ============ -XXXFIXME KEEP WHAT IS SPECIFIC TO APPENGINE AND MERGE THE REST WITH -03-setup.en.txt - Download the source ------------------- diff -r 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/20-03-create-app.en.txt --- a/doc/book/en/20-03-create-app.en.txt Thu Nov 20 20:36:03 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -.. -*- coding: utf-8 -*- - - -Creating your first application -=============================== - -XXXFIXME KEEP WHAT IS SPECIFIC TO APPENGINE AND MERGE THE REST WITH OVERVIEW OR -MAKE A NEW CHAPTER - -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 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/20-04-develop-views.en.txt --- a/doc/book/en/20-04-develop-views.en.txt Thu Nov 20 20:36:03 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -.. -*- coding: utf-8 -*- - - -Developing the user interface with Views -======================================== - -XXXFIXME MERGE THIS WITH 05-define-views.en.txt - -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 entries 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 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/20-05-components.en.txt --- a/doc/book/en/20-05-components.en.txt Thu Nov 20 20:36:03 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -.. -*- coding: utf-8 -*- - -.. _components: - -Components -=========== - -XXXFIXME TURN THIS INTO A CHAPTER - -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 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/20-06-maintemplate.en.txt --- a/doc/book/en/20-06-maintemplate.en.txt Thu Nov 20 20:36:03 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,211 +0,0 @@ -.. -*- coding: utf-8 -*- - -Views & Templates -================= - -XXXFIXME TURN THIS INTO A CHAPTER - -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 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/20-07-rss-xml.en.txt --- a/doc/book/en/20-07-rss-xml.en.txt Thu Nov 20 20:36:03 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -.. -*- coding: utf-8 -*- - -RSS Channel -=========== - -XXXFIXME TURN THIS INTO A CHAPTER - -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 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/20-08-rql.en.txt --- a/doc/book/en/20-08-rql.en.txt Thu Nov 20 20:36:03 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +0,0 @@ -.. -*- coding: utf-8 -*- - -RQL language (Relation Query Language) -====================================== - -XXXFIXME MERGE WITH 16-rql.en.txt - -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 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/20-09-urlrewrite.en.txt --- a/doc/book/en/20-09-urlrewrite.en.txt Thu Nov 20 20:36:03 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -.. -*- 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 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/20-10-security.en.txt --- a/doc/book/en/20-10-security.en.txt Thu Nov 20 20:36:03 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -.. -*- coding: utf-8 -*- - -Security -========= - -[WRITE ME] - -* talk about security access rights and show that security is defined - using RQL - diff -r 9ecd54ea0634 -r 4b66ad23fbd1 doc/book/en/XX-XX-urlrewrite.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/XX-XX-urlrewrite.en.txt Thu Nov 20 21:30:55 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 +