doc/book/en/01-introduction.en.txt
author Sandrine Ribeau <sandrine.ribeau@logilab.fr>
Mon, 17 Nov 2008 23:54:24 -0800
changeset 95 a5c7609de579
parent 93 9c919a47e140
child 97 d507caa1b386
permissions -rw-r--r--
[doc] Initial translation of index and introduction for book/en.

.. -*- coding: utf-8 -*-

.. _Overview:

Quick overview of `CubicWeb`
============================

`CubicWeb` allows us to develop web applications instances based on
one or more `cubes`.

What we call a `cube` is a model defining the data types and views. 
A `cube` is a reusable component grouped with others cubes in the file
system.

An `instance` refers to a specific installation of one or more `cubes`
 where are grouped configuration files of the final web application.

In this document, we will show you how to create a `cube` and how to use it
in an `instance` for your web application.

Create your cube
----------------

After you installed your `CubicWeb` development environment, you can start
to build your first cube: ::

  cubicweb-ctl newcube blog

This will create in ``/path/to/forest/cubes`` a directory containing: ::

  blog/
  |
  |-- data/
  |   |-- cubes.blog.css
  |   |-- cubes.blog.js  
  |   |-- external_resources
  |
  |-- debian/
  |   |-- changelog
  |   |-- compat
  |   |-- control
  |   |-- copyright
  |   |-- cubicweb-blog.prerm
  |   |-- rules
  |
  |-- entities.py
  |
  |-- i18n/
  |   |-- en.po
  |   |-- fr.po
  |
  |-- __init__.py
  |
  |-- MANIFEST.in
  |
  |-- migration/
  |   |-- postcreate.py
  |   |-- precreate.py
  |
  |-- __pkginfo__.py
  |
  |-- schema.py
  |
  |-- setup.py
  |
  |-- site_cubicweb.py
  |
  |-- sobjects.py
  |
  |-- test/
  |   |-- data/
  |       |-- bootstrap_cubes
  |   |-- pytestconf.py
  |   |-- realdb_test_blog.py
  |   |-- test_blog.py
  |
  |-- views.py

Any changes applied to your data model should be done in this
directory.


Define your data schema
-----------------------

The data model or schema is hte core of your `CubicWeb` application.
This is where is defined the type of content you application will handle.

The data model is defined in the file ``schema.py`` of your cube
``blog`` such as follows.

::

  from cubicweb.schema import format_constraint
  class Blog(EntityType):
    title = String(maxsize=50, required=True)
    description = String()

  class BlogEntry(EntityType):
    title = String(required=True, fulltextindexed=True, maxsize=256)
    publish_date = Date(default='TODAY')
    content = String(required=True, fulltextindexed=True)
    entry_of = SubjectRelation('Blog', cardinality='?*') 


A Blog has a title and a description. The title is a string that is
required by the class EntityType and must be less than 50 characters. 
The description is a string that is not constrained.

A BlogEntry has a title, a publish_date and a content. The title is a
string that is required and must be less than 100 characters. The
publish_date is a Date with a default value of TODAY, meaning that
when a BlogEntry is created, its publish_date will be the current day
unless it is modified. The content is a string that will be indexed in
the full-text index and has no constraint.

A BlogEntry also has a relationship ``entry_of`` that links it to a
Blog. The cardinality ``?*`` means that a BlogEntry can be part of
zero or one Blog (``?`` means `zero or one`) and that a Blog can
have any number of BlogEntry (``*`` means `any number including
zero`). For completeness, remember that ``+`` means `one or more`.


Create your instance
--------------------

::
  
  cubicweb-ctl create blog blogdemo


This command will create a directory ``~/etc/cubicweb.d/blogdemo``
which will contain all the configuration files required to start
you web application.

The instance ``blogdemo`` is based on the cube ``blog``.


Welcome in your web application
-------------------------------

Run your application with the following command: ::

  cubicweb-ctl start -D blogdemo


You can now access to your web application to create blogs and post messages
by visitin the URL http://localhost:8080/.
A login form will first be prompted. By default, the application will not allow
anonymous user to get in the application. You should then use the admin
account you created at the time you initialized the database with
``cubicweb-ctl create``.

.. image:: images/login-form.png


Once authenticated, you can start playing with your application 
and create entities. Bravo!

.. image:: images/blog-demo-first-page.png

Please notice that so far, `CubicWeb` franework managed all aspects of 
the web application based in the schema provided at first.


Create entities
---------------

We will now create a couple of entities in our web application.

Create a Blog
~~~~~~~~~~~~~

Let us create a few of these entities. Click on the `[+]` at the right
of the link Blog.  Call this new Blog ``Tech-blog`` and type in
``everything about technology`` as the description, then validate the
form by clicking on ``Validate``.

.. image:: images/cbw-create-blog.en.png
   :alt: from to create blog

Click on the logo at top left to get back to the home page, then
follow the Blog link that will list for you all the existing Blog.
You should be seeing a list with a single item ``Tech-blog`` you
just created.

.. image:: images/cbw-list-one-blog.en.png
   :alt: displaying a list of a single blog

Clicking on this item will get you to its detailed description except
that in this case, there is not much to display besides the name and
the phrase ``everything about technology``.

Now get back to the home page by clicking on the top-left logo, then
create a new Blog called ``MyLife`` and get back to the home page
again to follow the Blog link for the second time. The list now
has two items.

.. image:: images/cbw-list-two-blog.en.png
   :alt: displaying a list of two blogs

Create a BlogEntry
~~~~~~~~~~~~~~~~~~

Get back to the home page and click on [+] at the right of the link
BlogEntry. Call this new entry ``Hello World`` and type in some text
before clicking on ``Validate``. You added a new blog entry without
saying to what blog it belongs. There is a box on the left entitled
``actions``, click on the menu item ``modify``. You are back to the form
to edit the blog entry you just created, except that the form now has
another section with a combobox titled ``add relation``. Chose
``entry_of`` in this menu and a second combobox appears where you pick
``MyLife``. 

You could also have, at the time you started to fill the form for a
new entity BlogEntry, hit ``Apply`` instead of ``Validate`` and the 
combobox titled ``add relation`` would have showed up.


.. image:: images/cbw-add-relation-entryof.en.png
   :alt: editing a blog entry to add a relation to a blog

Validate the changes by clicking ``Validate``. The entity BlogEntry
that is displayed now includes a link to the entity Blog named
``MyLife``.

.. image:: images/cbw-detail-one-blogentry.en.png
   :alt: displaying the detailed view of a blogentry

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

.. image:: images/cbw-schema.en.png
   :alt: graphical view of the schema (aka data-model)


Define your entities views
--------------------------

The views selection principle
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A view is defined by a Python class which includes: 
  
  - an identifier (all objects in `CubicWeb` are entered in a registry
    and this identifier will be used as a key)
  
  - a filter to select the resulsets it can be applied to


`CubicWeb` provides a lot of standard views for the type
`EntityView`, for a complete list, you
will have to read the code in directory ``cubicweb/web/views/``

A view is applied on a `result set` which contains a set of
entities we are trying to display. `CubicWeb` uses a selector
mecanism which computes a score used to identify which view
is the best to apply for the `result set` we are trying to 
display. The standard library of selectors is in 
``cubicweb.common.selector`` and a library of methods used to
compute scores is available in ``cubicweb.vregistry.vreq``.

It is possible to define multiple views for the same identifier
and to associate selectors and filters to allow the application
to find the best way to render the data. We will see more details
on this in :ref:`DefinitionVues`.

For example, the view named ``primary`` is the one used to display
a single entity. We will now show you hos to customize this view.


View customization
~~~~~~~~~~~~~~~~~~

If you wish to modify the way a `BlogEntry` is rendered, you will have to 
overwrite the `primary` view defined in the module ``views`` of the cube
``cubes/blog/views.py``.

We can by example add in front of the pulication date a prefix specifying
the date we see is the publication date.

To do so, please apply the following changes:

:: 

  from cubicweb.web.views import baseviews


  class BlogEntryPrimaryView(baseviews.PrimaryView):

    accepts = ('BlogEntry',)

    def render_entity_title(self, entity):
        self.w(u'<h1>%s</h1>' % html_escape(entity.dc_title()))

    def content_format(self, entity):
        return entity.view('reledit', rtype='content_format')

    def cell_call(self, row, col):
        entity = self.entity(row, col)

        # display entity attributes with prefixes
        self.w(u'<h1>%s</h1>' % entity.title)
        self.w(u'<p>published on %s</p>' % entity.publish_date.strftime('%Y-%m-%d'))
        self.w(u'<p>%s</p>' % entity.content)
        
        # display relations
        siderelations = []
        if self.main_related_section:
            self.render_entity_relations(entity, siderelations)

.. note::
  When a view is modified, it is not required to restart the application
  server. Save the Python file and reload the page in your web browser
  to view the changes.

You can now see that the publication date has a prefix.

.. image:: images/cbw-update-primary-view.en.png
   :alt: modified primary view


The above source code defines a new primary view for
``BlogEntry``. 

Le code que nous avons modifié définit une vue primaire pour une entité de 
type `BlogEntry`. 

Since views are applied to resultsets and resulsets can be tables of
data, it is needed to recover the entity from its (row,col)
coordinates. We will get to this in more detail later.

The view has a ``self.w()`` method that is used to output data. In our
example we use it to output HTML tags and values of the entity's attributes.