Resources

REST-style architectures consist of Clients and servers. Clients initiate requests to servers; servers process requests and return appropriate responses. Requests and responses are built around the transfer of representations of Resources. A resource can be essentially any coherent and meaningful concept that may be addressed. A representation of a resource is typically a document that captures the current or intended state of a resource.

In RestORM, a Resource is the single, definitive source of data about a specific API endpoint. It contains the essential properties and behaviors of the data you’re accessing. Generally, each resource maps to a single API endpoint.

Defining resources

Imagine a RESTful library API, like described in the Tutorial and the Mocking part of this documentation. You can request a list of books in the library and a list of authors. The API provides data about a specific book, like its title and author. To represent the book on our client side, we define a Book resource that inherits from Resource.

We also define an inner Meta class that contains meta properties about the book resource. It contains for example an attribute item that holds a relative URL pattern for retrieving a single book.

from restorm.resource import Resource

class Book(Resource):
    class Meta:
        item = r'^book/(?P<isbn>\w+)$'

The item attribute holds a URL pattern that is a regular expression describing on what URL a single book representation can be retrieved. The r in front of the string in Python means to take the string “raw” and nothing should be escaped.

In Python regular expressions, the syntax for named regular-expression groups is (?P<name>pattern), where name is the name of the group and pattern is some pattern to match. In the example above the name isbn can be any word of any length. A valid relative URL would be: book/1 or book/abc123.

As you may have noticed, nothing is said about the book’s representation. There is no strict definition of what should be a book. The server decides this for you, or you can manually pass in data. All information passed to the Resource constructor as first argument, is available in the data attribute.

>>> book = Book({'title': 'Hello world', 'subtitle': 'A good start'})
>>> book.absolute_url
None
>>> book
<Book: None>
>>> book.data['title']
'Hello world'

You can add any custom function to your resource class to help you work with the data representation.

from restorm.resource import Resource

class Book(Resource):
    class Meta:
        item = r'^book/(?P<isbn>\w+)$'

    @property
    def full_title(self):
        return '%s: %s' % (self.data['title'], self.data['subtitle'])

>>> book = Book({'title': 'Hello world', 'subtitle': 'A good start'})
>>> book.full_title
'Hello world: A good start'

The default representation of a Resource is the class name followed by the (absolute) URL of the retrieved representation, in the example there was none so the value is None.

You can override this with the __unicode__ function:

class Book(Resource):
    # ...

    def __unicode__(self):
        if 'title' in self.data:
            return self.data['title']
        else:
            return '(unknown title)'

>>> book = Book({'title': 'Hello world', 'subtitle': 'A good start'})
>>> book.absolute_url
None
>>> book
<Book: Hello world>

Resource managers

A ResourceManager is the interface through which API requests can be performed on a Resource. At least one manager exists for every resource.

By default, RestORM adds a ResourceManager with the name objects to every RestORM resource class.

Let’s assume we already have a client ready, as described in Clients but we use our mock client so you can test the demonstrated code snippets yourself.

>>> from restorm.examples.mock.api import LibraryApiClient
>>> client = LibraryApiClient()

Our Book resource already allows us to get a single book from the library API:

>>> book = Book.objects.get(isbn=1, client=client)
>>> book.data['title']
u'Dive into Python'

To make life a little easier, we can stop passing the client argument by setting our client as the default client:

>>> from restorm.conf import settings
>>> settings.DEFAULT_CLIENT = client

You can typically add this to your (Django) project settings so you won’t have to bother about it anymore. We can now do:

>>> book = Book.objects.get(isbn=1)
>>> book.data['title']
u'Dive into Python'
class restorm.resource.ResourceManager
get(client=None, query=None, uri=None, **kwargs)

Returns the object matching the given lookup parameters. You should pass all arguments required by the resource URL pattern item, as specified in the Meta class of the resource.

Parameters:
  • client – The client to retrieve the object from the API. By default, the default client is used. If no client and no default client are specified, a ValueError is raised.
  • query – A dict with additional query string arguments. An empty dict by default.
  • uri – Rather than passing the resource URL pattern arguments, you can also provide a complete URL. This URL must match the resource URL pattern.
>>> Book.objects.get(isbn=1)
<Book: http://www.example.com/api/book/1>
all(client=None, query=None, uri=None, **kwargs)

Returns the raw response for the list of objects. You should pass all arguments required by the resource URL pattern collection, as specified in the Meta class of the resource.

Parameters:
  • client – The client to retrieve the object from the API. By default, the default client is used. If no client and no default client are specified, a ValueError is raised.
  • query – A dict with additional query string arguments. An empty dict by default.
  • uri – Rather than passing the resource URL pattern arguments, you can also provide a complete URL. This URL must match the resource URL pattern.
>>> Book.objects.all() # Returns a raw response.

Table Of Contents

Previous topic

Clients

Next topic

Mocking

This Page