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

.. _TutosMuseumsGettingStarted:

Developping the application
---------------------------

Defining our data model
~~~~~~~~~~~~~~~~~~~~~~~

We want to manage museums. Each museum has a name, a postal address,
maybe one or several director, a geographical position (latitude and longitude) and are in a
city. Some of these concepts will be classes, others attributes.

Let's write the following code in the
:file:`cubicweb-tutorial/cubicweb_tutorial/schema.py` file:

.. sourcecode:: python

    from yams.buildobjs import EntityType, String, Float, RelationDefinition, Int

    class Museum(EntityType):
        name = String()
        latitude = Float()
        longitude = Float()
        postal_address = String()

    class City(EntityType):
        name = String()
        zip_code = Int()

    class Person(EntityType):
        name = String()
        email = String()

    class is_in(RelationDefinition):
        subject = 'Museum'
        object = 'City'
        cardinality = '1*'

    class director(RelationDefinition):
        subject = 'Museum'
        object = 'Person'
        cardinality = '**'

The first line imports from the :mod:`yams` package the classes necessary to
define the data model of our application.

There are three entity types and two relations:

* a `Museum` has a name, a latitude, a longitude and a postal address as attributes.

  - the name and postal address are strings;

  - the latitude and longitude are floating numbers.

* a `City` has a name and a zip code as attributes.

* a `Person` has a name and an email as attributes

* a `Museum` must be linked to a `City` using the `is_in` relation

  - ``*`` means a City may be linked to 0 to N Museum, ``1`` means a Museum must
    be linked to one and only one City. For completeness, you can also use ``+`` for
    1 to N, and ``?`` for 0 or 1.

* a `Museum` can be linked to 0 or several `Person` using the `director` relation, and
  a `Person` can be linked to 0 or several `Museum`.

Of course, there are a lot of other data types and things such as constraints,
permissions, etc, that may be defined in the schema, but those will not be covered
in this tutorial.

In our case, our relations have only on subject type. Thus, we can define them directly
in `Museum` class, using `SubjectRelation`, like this:

.. sourcecode:: python

    from yams.buildobjs import EntityType, String, Float, SubjectRelation, Int

    class Museum(EntityType):
        name = String()
        latitude = Float()
        longitude = Float()
        is_in = SubjectRelation("City", cardinality="1*")
        director = SubjectRelation("Person", cardinality="**")
        postal_address = String()

    class City(EntityType):
        name = String()
        zip_code = Int()

    class Person(EntityType):
        name = String()
        email = String()

Now that we have a defined our schema, we need to recreate our database to let
cubicweb initialise it correctly with this schema:

.. code-block:: console

    cubicweb-ctl db-create tutorial_instance

Since our database was empty, you can accept to drop it without losing data: say
Yes, then say Yes again to initialise it. If we had existing data in the
database and we changed the data model, we would have to write a migration
script and run `cubicweb-ctl upgrade` (:ref:`migration` for more information
about this topic).

Let's start our instance again to see our new entity types listed in the homepage:
City, Museum, Person; and for each, the number of instance of these types (currently 0, as
we don't have any of these entities).

.. image:: ../../images/tutos-museum_with_schema.png
   :alt: The instance homepage, with new entity types.

By clicking on `data model schema`, we can see our data model, with our three classes
and two relations.

.. image:: ../../images/tutos-museum_data_model_schema.png
   :alt: The instance data model schema, with new entity types.

Adding data
~~~~~~~~~~~

Now we have our entity types defined, we will see how to add some entities. To do this, we need to
be connected as administrator, using the `login` button at right top of the site, or visiting
http://localhost:8080/login. As you can see, we have more choices in the homepage, and beside
each entity type, we have a **+**, allowing to create a new entity of this type.

.. image:: ../../images/tutos-museum_admin.png
   :alt: The instance homepage, in administrator mode.

As we built our schema, a Museum have to be linked to a City, so we first need to create a City
before adding a museum. To do this, we just have to click on the **+** beside `City (0)`,
and fill the form.

.. image:: ../../images/tutos-museum_city_creation.png
   :alt: City entity creation.

As you can see, all the fields come directly from the schema and the form is automatically
generated by the code from the `web` cube.

When all the fields are filled, we just have to validate, and we are redirected on the city
page, where we can see its different attributes, and in the box at the top left, several
possible actions, such as modify and delete.

.. image:: ../../images/tutos-museum_city_created.png
   :alt: City entity view.

Now we have our first city, we will add its three museums. As for the city creation, we have an
autogenerated form; but with a little particularity: a field to choose the city to link
with our museum. This field must be filled to create our entity.

.. image:: ../../images/tutos-museum_museum_creation.png
   :alt: Museum entity creation.

As for the city, we are redirected on the entity view after its creation.

.. image:: ../../images/tutos-museum_museum_created.png
   :alt: Museum entity view.

We then add two other museums. When we go back to the homepage, we can see all three museums
when we click on `Museum_plural (3)`.

.. image:: ../../images/tutos-museum_list_view.png
   :alt: Our three museums.

If we click on `City` in the homepage, we do not have a list view, but our single entity view.
This is because in the first case, the framework chose to use the 'primary' view
(detailed view) since there is only one entity in the data to be displayed. As we have three museums,
the 'list' view is more appropriate and hence is being used.

There are various other places where |cubicweb| adapts to display data in the best
way, the main being provided by the view *selection* mechanism that will be detailed
later.
