Operations with collections

The attribute Person.cars is represented as a collection and hence we can use regular operations that applicable to collections: add(), remove(), in, len(), clear().

You can add or remove relationships using the Set.add() and Set.remove() methods:

  1. >>> p1.cars.remove(Car[1])
  2. >>> print p1.cars
  3. CarSet([])
  4. >>> p1.cars.add(Car[1])
  5. >>> print p1.cars
  6. CarSet([Car[1]])

You can check if a collection contains an element:

  1. >>> Car[1] in p1.cars
  2. True

Or make sure that there is no such element in the collection:

  1. >>> Car[1] not in p1.cars
  2. False

Check the collection length:

  1. >>> len(p1.cars)
  2. 1

If you need to create an instance of a car and assign it with a particular person instance, there are several ways to do it. One of the options is to call the create() method of the collection attribute:

  1. >>> p1.cars.create(model='Toyota', make='Prius')
  2. >>> commit()

Now we can check that a new Car instance was added to the Person.cars collection attribute of our instance:

  1. >>> print p1.cars
  2. CarSet([Car[2], Car[1]])
  3. >>> p1.cars.count()
  4. 2

You can iterate over a collection attribute:

  1. >>> for car in p1.cars:
  2. ... print car.model
  3. Toyota
  4. Camry

Attribute lifting

In Pony, the collection attributes provides the attribute lifting capability: the collection obtains its items’ attributes:

  1. >>> show(Car)
  2. class Car(Entity):
  3. id = PrimaryKey(int, auto=True)
  4. make = Required(str)
  5. model = Required(str)
  6. owner = Optional(Person)
  7. >>> p1 = Person[1]
  8. >>> print p1.cars.model
  9. Multiset({u'Camry': 1, u'Prius': 1})

Here we print out the entity declaration using the show() function and then print the value of the model attribute of the cars relationship attribute. The cars attribute has all the attributes of the Car entity: id, make, model and owner. In Pony we call this a Multiset and it is implemented using a dictionary. The dictionary’s key represents the value of the attribute - ‘Camry’ and ‘Prius’ in our example. And the dictionary’s value shows how many times it encounters in this collection.

  1. >>> print p1.cars.make
  2. Multiset({u'Toyota': 2})

Person[1] has two Toyotas.

We can iterate over the multiset:

  1. >>> for m in p1.cars.make:
  2. ... print m
  3. ...
  4. Toyota
  5. Toyota

Collection attribute parameters

Here is the list options that you can apply to collection attributes:

Example:

  1. class Photo(db.Entity):
  2. tags = Set('Tag', table='photo_to_tag', column='tag_id')
  3. class Tag(db.Entity):
  4. photos = Set(Photo)

Collection attribute queries and other methods

Starting with the release 0.6.1, Pony introduces queries for the relationship attributes.

You can use the following methods of the relationship attribute for retrieving data:

See the Collection attribute methods part of th API Reference for more details.

Below you can find several examples of using these methods. We’ll use the University schema for showing these queries, here are python entity definitions and Entity-Relationship diagram.

The example below selects all students with the gpa greater than 3 within the group 101:

  1. g = Group[101]
  2. g.students.filter(lambda student: student.gpa > 3)[:]

This query can be used for displaying the second page of group 101 student’s list ordered by the name attribute:

  1. g.students.order_by(Student.name).page(2, pagesize=3)

The same query can be also written in the following form:

  1. g.students.order_by(lambda s: s.name).limit(3, offset=3)

The following query returns two random students from the group 101:

  1. g.students.random(2)

And one more example. This query returns the first page of courses which were taken by Student[1] in the second semester, ordered by the course name:

  1. s = Student[1]
  2. s.courses.select(lambda c: c.semester == 2).order_by(Course.name).page(1)