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 cubicweb-tutorial/cubicweb_tutorial/schema.py file:

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 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:

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:

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 (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).

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.

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.

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.

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.

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.

Museum entity creation.

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

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).

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.