Creating and deleting elements

In computing, there is a common term called CRUD: creating, reading (accessing), updating and deleting. In the previous example, you learned how to retrieve collections and elements over HTTP. In this example, we’ll show how creating and deleting elements in collections works.

Example code

# -*- mode: python; coding: utf-8 -*-
cache()

from twisted.web.resource import IResource

from txyoga import Collection, Element


class Employee(Element):
    """
    An employee at a company.
    """
    exposedAttributes = "name", "title"
    updatableAttributes = "salary", "title"

    def __init__(self, name, title, salary):
        self.name = name
        self.title = title
        self.salary = salary



class Company(Collection):
    """
    A company.
    """
    defaultElementClass = Employee
    exposedElementAttributes = "name",



startup = Company()

startup.add(Employee(u"lvh", u"CEO", 10000))
startup.add(Employee(u"asook", u"Junior intern", 1))

resource = IResource(startup)

The example code is very similar, but not identical to that in the previous example.

First of all, there is the updatableAttributes attribute on the element class. This is an iterable of the attribute names for which updates are allowed. In this case, it’s salary and title – we can give people new positions and give them raises, but not change their names.

Then there is the elementClass attribute on the collection class. By default, this class will be instantiated when new elements are added. In this case, new elements will be instances of the Employee class.

Trying it out

Like before, start by creating the helper object for this example:

>>> example = Example("crud")

Creating an element

First, we’ll hire a new employee in the company. In REST, there are two usual ways of creating elements:

1. If you just want to add an element to a Collection and you don’t care what URL it will be available under, POST to the collection. 2. If you want to make an element accessible at a particular path, PUT it there.

Just like everywhere else, when faced with doubt, txyoga refuses the temptation to guess. In this case, when you provide data through POST or PUT, specifying the encoding is mandatory.

>>> data = {"name": u"alice", "salary": 100, "title": "engineer"}
>>> headers = {"content-type": "application/json"}
>>> response = example.put(json.dumps(data), headers, "alice")

As usual, we get the appropriate response:

>>> response.status, response.reason
(201, 'Created')

If accepted but not yet created, a txyoga server may optionally return 202 (Accepted).

Updating an element

The company’s success has really gotten to lvh’s head. He’s not happy unless we give him a ridiculous new title.

To do that, we update his record. In REST, updates are typically done using a PUT request.

>>> def getTitle(employee="lvh"):
...     response = example.get(employee)
...     return json.load(response)["title"]
>>> assert getTitle() == u'CEO'
>>> headers = {"content-type": "application/json"}
>>> data = {"title": u"Supreme Commander"}
>>> response = example.put(json.dumps(data), headers, "lvh")
>>> response.status, response.reason
(200, 'OK')
>>> assert getTitle() == u'Supreme Commander'

Deleting an element

Next, we’ll remove poor Asook from the workforce. As you might expect from a REST toolkit, you do that with the DELETE verb, or, with our helper abstraction layer, the delete method.

>>> response = example.delete("asook")

The server will respond with the appropriate response code:

>>> response.status, response.reason
(204, 'No Content')

When you access the collection again, Asook is missing, as expected:

>>> employees = json.load(example.get())["results"]
>>> assert u"asook" not in employees