Fetching Data¶
For a given model instance, three methods are available for fetching resource data. All three methods expect a dictionary of options as the first argument. These options represent the request query string parameters.
Single Objects¶
To fetch a single resource object, call the Model.get_object()
method, supplying the object id as the second
argument:
>>> await UserModel().get_object({}, 1)
{
'data': {
'id': '1',
'type': 'user',
'attributes': {
'email': 'dianagraham@fisher.com',
'first': 'Robert',
'last': 'Camacho',
'createdOn': '2019-05-18T11:49:43Z',
'status': 'active',
'name': 'Robert Camacho'}
}
}
The generated SQL query may look like this:
SELECT users.id AS id,
users.email AS email,
user_names.first AS first,
user_names.last AS last,
users.created_on AS created_on,
users.status AS status,
user_names.first || ' ' || public.user_names.last AS name
FROM public.users
JOIN public.user_names ON public.users.id = public.user_names.user_id
WHERE public.users.id = 1
If the resource object does not exist, a NotFound
exception is raised:
>>> await UserModel().get_object({}, 1001)
Traceback (most recent call last):
...
jsonapi.exc.NotFound: [UserModel] object not found: user(1001)
Collections¶
To fetch a collection of objects, call the Model.get_collection()
method:
>>> await UserModel().get_collection({})
{'data': [
{
'id': '1',
'type': 'user',
'attributes': {
'email': 'dianagraham@fisher.com',
'first': 'Robert',
'last': 'Camacho',
'createdOn': '2019-05-18T11:49:43Z',
'status': 'active',
'name': 'Robert Camacho'
}
},
...
]}
The generated SQL query may look like this:
SELECT users.id AS id,
users.email AS email,
user_names.first AS first,
user_names.last AS last,
users.created_on AS created_on,
users.status AS status,
user_names.first || ' ' || user_names.last AS name
FROM users
JOIN user_names ON users.id = user_names.user_id
Sparse Fieldsets¶
By default, only non-aggregate attribute fields are included in the response.
Aggregate fields must be requested explicitly and relationship fields are included when related resources are
requested using the include
request parameter (see Inclusion of Related Resources).
To include specific attributes in the response, pass a comma separated list of field names using the appropriate
fields[TYPE]
option, where TYPE
is the type
of the resource model:
>>> await UserModel().get_object({
>>> 'fields[user]': 'name,email,created-on'
>>> }, 1)
{
'data': {
'id': '1',
'type': 'user',
'attributes': {
'email': 'dianagraham@fisher.com',
'createdOn': '2019-05-18T11:49:43Z',
'name': 'Robert Camacho'}
}
}
You can pass an option for different resource types included in the response. For an example, see this.
Sorting¶
To sort a collection of resource objects, pass on the names of fields to order by as a comma separated list using the
sort
request parameter. You can use “+” or “-” prefix to indicate the sorting direction for each filed: ascending
or descending, respectively. No prefix implies ascending order.
For example, the following returns a collection of user
objects sorted by the created-on
field in descending
order:
>>> await UserModel().get_collection({'sort': '-created-on'})
To sort the collection of followers of a specific user
by last name first, and then by first name:
>>> await UserModel().get_related({
>>> 'sort': 'last,first'
>>> }, 1, 'followers')
Collections can be sorted by aggregate fields:
>>> await UserModel().get_collection({'sort': '-follower-count'})
Sorting by a relationship field, will sort by the related resource id
field.
The following calls have identical effect:
>>> await ArticleModel().get_collection({'sort': 'author'})
>>> await ArticleModel().get_collection({'sort': 'author.id'})
You can use dot notation to specify a different attribute. To sort articles by the author name:
>>> await ArticleModel().get_collection({'sort': 'author.name'})
Pagination¶
To limit the number of objects returned in the data
section of the response document, you can pass on the number
as the value of the page[size]
option:
>>> await UserModel().get_collection({
>>> 'page[size]': 10,
>>> 'sort': '-created-on'
>>> })
The above call will return the 10 most recent user
accounts.
To return the next batch, you can set the page[number]
option to the appropriate value (defaults to 1):
>>> await UserModel().get_collection({
>>> 'page[size]': 10,
>>> 'page[number]': 2,
>>> 'sort': '-created-on'
>>> })
Note
If page[number]
parameter is set without providing page[size]
, an exception will be raised.
When pagination options are set, the total
number of objects is provided in the meta
section of the response
document:
>>> await UserModel().get_collection({'page[size]': 10})
{
'data': [...],
'meta': {
'total': 1000
}
}
Filtering¶
The filter[SPEC]
option can be used to filter a collection of objects (or related objects).
In the simplest form, SPEC
can be the name of any field in the model.
This filter would include all objects where the field has a value equal to that supplied by the filter.
The value is parsed based on the datatype of the field.
For example, the following returns a list of active user accounts:
>>> await UserModel().get_collection({
>>> 'filter[status]': 'active'
>>> })
By default, the filter will use the equality operator. To specify a different operator, you can append a colin and the operator symbol to the name of the field. For example, to return all accounts created since September of 2019:
>>> await UserModel().get_collection({
>>> 'filter[created-on:gt]': '2019-09'
>>> })
The supported operators (and their symbols) and value formats depends of the field’s datatype.
For more details see :module:jsonapi.datatypes
.
You can combine multiple filters, which will be AND-ed together:
>>> await UserModel().get_collection({
>>> 'filter[status:eq]': 'active',
>>> 'filter[created-on:gt]': '2019-09'
>>> })
Some datatypes accept comma-separated values. To fetch a specific list of users:
>>> await UserModel().get_collection({
>>> 'filter[id]': '1,2,3,6,8,9,10,11,12'
>>> })
Ranges are also supported. The following is equivalent to the example above:
>>> await UserModel().get_collection({'filter[id]': '<=3,6,>=8,12'})
>>> await UserModel().get_collection({'filter[id]': '<4,6,>7,<13'})
Ranges are also supported by the date and time datatypes. To return all accounts created in September of 2019:
>>> await UserModel().get_collection({
>>> 'filter[created-on]': '>2019-09,<2019-10'
>>> })
When filtering by a relationship fields, the objects are filtered by the id
field related resource model. The
following calls are equivalent:
>>> await ArticleModel().get_collection({'filter[author]': '1,2,3'})
>>> await ArticleModel().get_collection({'filter[author.id]': '1,2,3'})
You can also filter by an attribute of a related resource model:
>>> await ArticleModel().get_collection({'filter[author.status]': 'active'})
The reserved literals none
, null
, or na
can be used to filter empty relationships. The values are
case-insensitive. The following calls return articles with and without a publisher, respectively:
>>> await ArticleModel().get_collection({'filter[publisher:ne]': 'none'})
>>> await ArticleModel().get_collection({'filter[publisher:eq]': 'none'})