.. -*- coding: utf-8 -*-.._Steps:Steps for creating your cube----------------------------The following steps will help you to create and customize a new cube.1.:ref:`CreateYourCube`Create the directory to hold the code of your cube. The most importantfiles that will be useful to customize your newly created cube are:* schema.py: contains the data model* views.py: contains your custom views* entities.py: contains XXXThe detailed structure of the code directory is described in :ref:`cubelayout`.2.:ref:`DefineDataModel`Define the data model of your application.3.:ref:`ExploreYourInstance`Create, run, and explore an instance of your cube.4.:ref:`DefineViews`Customize the views of your data: how and which part of your data are showed...note:: views do not define the look'n'feel and the design of your application. For that, you will use CSS and the files located 'blog/data/'.5.:ref:`DefineEntities`Define your own entities to add useful functions when you manipulate your data, especially when you write view..._CreateYourCube:Create your cube----------------The packages ``cubicweb`` and ``cubicweb-dev`` install a command linetool for *CubicWeb* called ``cubicweb-ctl``. This tool provides a widerange of commands described in details in :ref:`cubicweb-ctl`.Once your *CubicWeb* development environment is set up, you can createa new cube:: cubicweb-ctl newcube blogThis will create in the cubes directory (``/path/to/forest/cubes`` for Mercurialinstallation, ``/usr/share/cubicweb/cubes`` for debian packages installation)a directory named ``blog`` reflecting the structure described in :ref:`Concepts`.For packages installation, you can still create new cubes in your home directory using the following configuration. Let's say you want to develop your new cubes in `~src/cubes`, then set the following environment variables::: CW_CUBES_PATH=~/src/cubes CW_MODE=userand then create your new cube using::: cubicweb-ctl newcube --directory=~/src/cubes blog.._DefineDataModel:Define your data model----------------------The data model or schema is the core of your *CubicWeb* application.It defines the type of content your application will handle.The data model of your cube ``blog`` is defined in the file ``schema.py``:..sourcecode::pythonfromyams.buildobjsimportEntityType,String,SubjectRelation,DateclassBlog(EntityType):title=String(maxsize=50,required=True)description=String()classBlogEntry(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='?*')The first step is the import of the EntityType (generic class for entity andattributes that will be used in both Blog and BlogEntry entities.A Blog has a title and a description. The title is a string that isrequired and must be less than 50 characters. Thedescription is a string that is not constrained.A BlogEntry has a title, a publish_date and a content. The title is astring that is required and must be less than 100 characters. Thepublish_date is a Date with a default value of TODAY, meaning thatwhen a BlogEntry is created, its publish_date will be the current dayunless it is modified. The content is a string that will be indexed inthe database full-text index and has no constraint.A BlogEntry also has a relationship ``entry_of`` that links it to aBlog. The cardinality ``?*`` means that a BlogEntry can be part ofzero or one Blog (``?`` means `zero or one`) and that a Blog canhave any number of BlogEntry (``*`` means `any number includingzero`). For completeness, remember that ``+`` means `one or more`..._ExploreYourInstance:Create and explore your instance--------------------------------.._CreateYourInstance:Create your instance~~~~~~~~~~~~~~~~~~~~To use this cube as an instance and create a new instance named ``blogdemo``, do:: cubicweb-ctl create blog blogdemoThis command will create the corresponding database and initialize it..._WelcomeToYourWebInstance:Welcome to your web instance~~~~~~~~~~~~~~~~~~~~~~~~~~~~Start your instance in debug mode with the following command: :: cubicweb-ctl start -D blogdemoYou can now access your web instance to create blogs and post messagesby visiting the URL http://localhost:8080/.A login form will appear. By default, the instance will not allow anonymoususers to enter the instance. To login, you need then use the admin accountyou created at the time you initialized the database with ``cubicweb-ctlcreate``...image:: ../../images/login-form.pngOnce authenticated, you can start playing with your instanceand create entities...image:: ../../images/blog-demo-first-page.pngPlease notice that so far, the *CubicWeb* framework managed all aspects ofthe web application based on the schema provided at the beginning..._AddEntities:Add entities~~~~~~~~~~~~We will now add entities in our web application.Add a Blog**********Let us create a few of these entities. Click on the `[+]` at the left of thelink Blog on the home page. Call this new Blog ``Tech-blog`` and type in``everything about technology`` as the description, then validate the form byclicking on ``Validate``...image:: ../../images/cbw-create-blog_en.png:alt: from to create blogClick on the logo at top left to get back to the home page, thenfollow the Blog link that will list for you all the existing Blog.You should be seeing a list with a single item ``Tech-blog`` youjust created...image:: ../../images/cbw-list-one-blog_en.png:alt: displaying a list of a single blogClicking on this item will get you to its detailed description exceptthat in this case, there is not much to display besides the name andthe phrase ``everything about technology``.Now get back to the home page by clicking on the top-left logo, thencreate a new Blog called ``MyLife`` and get back to the home pageagain to follow the Blog link for the second time. The list nowhas two items...image:: ../../images/cbw-list-two-blog_en.png:alt: displaying a list of two blogsAdd a BlogEntry***************Get back to the home page and click on [+] at the left of the linkBlogEntry. Call this new entry ``Hello World`` and type in some textbefore clicking on ``Validate``. You added a new blog entry withoutsaying 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 formto edit the blog entry you just created, except that the form now hasanother 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 anew entity BlogEntry, hit ``Apply`` instead of ``Validate`` and thecombobox 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 blogValidate the changes by clicking ``Validate``. The entity BlogEntrythat 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 blogentryNote that all of this was handled by the framework and that the only inputthat 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).._DefineViews:Define your entity views------------------------Each entity defined in a model is associated with default viewsallowing different renderings of the data. You can redefine each ofthem according to your needs and preferences. So let's see how theviews are defined.The view selection principle~~~~~~~~~~~~~~~~~~~~~~~~~~~~A view is defined by a Python class which includes:- an identifier (all objects in *CubicWeb* are recorded in a registry and this identifier will be used as a key)- a filter to select the result sets it can be applied toA view has a set of methods complying with the `View` class interface(`cubicweb.common.view`).*CubicWeb* provides a lot of standard views for the type `EntityView`;for a complete list, read the code in directory ``cubicweb/web/views/``.A view is applied on a `result set` which contains a set of entitieswe are trying to display. *CubicWeb* uses a selector mechanism whichcomputes for each available view a score: the view with the highestscore is then used to display the given `result set`. The standardlibrary of selectors is in ``cubicweb.selector``.It is possible to define multiple views for the same identifierand to associate selectors and filters to allow the applicationto find the most appropriate way to render the data.For example, the view named ``primary`` is the one used to display asingle entity. We will now show you how to create a primary view forBlogEntry.Primary view customization~~~~~~~~~~~~~~~~~~~~~~~~~~If you wish to modify the way a `BlogEntry` is rendered, you will haveto subclass the `primary` view, for instance in the module ``views``of the cube ``cubes/blog/views.py``.The standard primary view is the most sophisticated view of all. Ithas more than a call() method. It is a template. Actually the entrypoint calls the following sequence of (redefinable) methods:* render_entity_title* render_entity_metadata* render_entity_attributes* render_entity_relations* render_side_boxesExcepted side boxes, we can see all of them already in action in theblog entry view. This is all described in more details in:ref:`primary_view`.We can for example add in front of the publication date a prefixspecifying that the date we see is the publication date.To do so, please apply the following changes:..sourcecode::pythonfromcubicweb.selectorsimportimplementsfromcubicweb.web.viewsimportprimaryclassBlogEntryPrimaryView(primary.PrimaryView):__select__=implements('BlogEntry')defrender_entity_attributes(self,entity):self.w(u'<p>published on %s</p>'%entity.publish_date.strftime('%Y-%m-%d'))super(BlogEntryPrimaryView,self).render_entity_attributes(entity)..note:: When a view is modified, it is not required to restart the instance 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 viewThe above source code defines a new primary view for ``BlogEntry``.Since views are applied to result sets and result sets can be tables ofdata, we have to recover the entity from its (row,col)-coordinates.The view has a ``self.w()`` method that is used to output data, in ourexample HTML output...note:: You can find more details about views and selectors in :ref:`Views`..._DefineEntities:Write entities to add logic in your data----------------------------------------By default, CubicWeb provides a default entity for each data type defined in the schema.A default entity mainly contains the attributes defined in the data model.You can redefine each entity to provide additional functions to help you write your views...sourcecode::pythonfromcubicweb.entitiesimportAnyEntityclassBlogEntry(AnyEntity):"""customized class for BlogEntry entities"""__regid__='BlogEntry'__implements__=AnyEntity.__implements__defdisplay_cw_logo(self):if'CW'inself.title:returnTrueelse:returnFalseCustomizing an entity requires that your entity: - inherits from ``cubicweb.entities`` or any subclass- defines a ``__regid__`` linked to the corresponding data type of your schema- implements the base class by explicitly using ``__implements__``.We implemented here a function ``display_cw_logo`` which tests if the blog entry title contains 'CW'.This function can then be used when you customize your views. For instance, you can modify your previous ``views.py`` as follows:..sourcecode::pythonclassBlogEntryPrimaryView(primary.PrimaryView):__select__=implements('BlogEntry')...defrender_entity_title(self,entity): if entity.display_cw_logo(): self.w(u'<image src="http://www.cubicweb.org/doc/en/_static/cubicweb.png"/>') super(BlogEntryPrimaryView, self).render_entity_title(entity)Then each blog entry whose title contains 'CW' is shown with the CubicWeb logo in front of it..._UpdatingSchemaAndSynchronisingInstance:Updating the schema and synchronising the instance--------------------------------------------------While developping your cube, you may want to update your data model. Let's say youwant to add a ``category`` attribute in the ``Blog`` data type. This is called a migration.The required steps are:1. modify the file ``schema.py``. The ``Blog`` class looks now like this:..sourcecode::pythonclassBlog(EntityType):title=String(maxsize=50,required=True)description=String()category=String(required=True,vocabulary=(_('Professional'),_('Personal')),default='Personal')2. stop your ``blogdemo`` instance:..sourcecode::bash cubicweb-ctlstopblogdemo3. start the cubicweb shell for your instance by running the following command:..sourcecode::bash cubicweb-ctlshellblogdemo4. at the cubicweb shell prompt, execute:..sourcecode::pythonadd_attribute('Blog','category')5. restart your instance:..sourcecode::bash cubicweb-ctlstartblogdemo6. modify a blog entity and check that the new attribute``category`` has been added.Of course, you may also want to add relations, entity types, etc. See :ref:`migration`for a list of all available migration commands.