OData query options
OData query options from Python - $filter, $select, $expand, $orderby, paging and counts, in both V2 and V4.
OData pushes filtering, sorting and shaping of results to the server - the client describes what it wants in query options and only the matching data travels over the wire. All the options below work with .read, .iter and .get, either as keyword arguments or through a reusable Query object.
Keyword arguments
The most direct form - each OData system query option is a keyword argument, without the dollar prefix:
conn = self.odata['OData.Sample']
customers = conn.read('Customers',
filter="City eq 'London' and IsBlocked eq false",
select='ID,DisplayName,City',
expand='Orders',
orderby='DisplayName desc',
top=20,
skip=40,
)
The client encodes each option correctly for the connection's OData version - for instance, inline counts are requested with $count=true in V4 and $inlinecount=allpages in V2.
| Name | Purpose |
|---|---|
| filter | Server-side filtering, e.g. Price gt 100 and Category eq 'Books' |
| select | Only the named properties travel back - a string or a list of names |
| expand | Related entities come inline, e.g. Orders or Orders($top=5) in V4 |
| orderby | Sorting, e.g. Name or Price desc - a string or a list |
| top | At most this many entities |
| skip | Skip this many entities first |
| count | Include the total match count alongside the results |
| search | Free-text search (V4) |
| apply | Aggregations and grouping (V4), e.g. groupby((Category),aggregate(Price with sum as Total)) |
| custom | A dict of extra parameters passed through as they are, e.g. SAP's sap-client |
The Query object
When the same options apply to more than one call, or when they are built up conditionally, use a Query object:
# Zato
from zato.common.odata.query import Query
query = Query(
filter="Country eq 'DE'",
select=['ID', 'DisplayName'],
orderby='DisplayName',
top=50,
)
customers = conn.read('Customers', query)
Escaping literals
Values embedded in filters follow OData's literal rules - single quotes inside strings are doubled, dates and GUIDs have version-specific formats. The format_literal function produces a correct literal for any Python value, matching the connection's OData version:
# Zato
from zato.common.odata.query import format_literal
name = "O'Brien"
customers = conn.read('Customers', filter=f'DisplayName eq {format_literal(name)}')
With ODataAdapter services, {placeholder} values substituted into the filter attribute are escaped automatically.
Counting
To learn only the number of matching entities, use .count - it maps to the $count path segment and transfers a single number, not the data:
Paging
Servers cap how many entities one response contains and include a link to the next page. The .iter method follows those links transparently:
If the connection's Page size is set, the client also asks the server for pages of that size using the Prefer: odata.maxpagesize header.