Creating Custom Repository
Contents
Creating Custom Repository#
Creating custom repositories can be done by simply
sublcassing TemplateRepo
. TemplateRepo
is
a Pydantic model that is integrated with Red Bird
repository system.
In order to successfully create a custom repository, the following methods must be implemented:
insert(item)
: This method creates an item to the repositoryquery_data(query)
: This method gets items from the repository accoding toquery
query_update(query, values)
: This method updates items in the repository matching toquery
with values defined invalues
query_delete(query)
: This method deletes items from the repository matching the givenquery
In addition, the following methods could also be implemented for better performance:
query_read_first(query)
: This method queries the first record from the data store from items matching thequery
query_read_limit(query, n)
: This method queries the firstn
items from the data store from items matching thequery
query_read_last(query)
: This method queries the last item from the data store from items matching thequery
query_replace(query, values)
: This method replaces the found item(s) from the data store from items matching thequery
using the values given invalues
query_count(query)
: This method counts the values from the data store from items matching thequery
The following methods could also be implemented for handling of the internals:
item_to_data(item)
: This method transforms an instance ofrepo.model
to data undestood by the underlying data storedata_to_item(data)
: This method transforms raw data from the data store to an instance ofrepo.model
format_query(query)
: This method formats thequery
to a form suitable for the data store
Example#
To demonstrate the subclassing, first we create a simple example that
only works with dict
as a model and without supporting any complicated
querying options:
from redbird.templates import TemplateRepo
class MyRepo(TemplateRepo):
store = [] # List that acts as our data store
def insert(self, item):
"Insert an item to the data store"
self.store.append(item)
def query_data(self, query):
"Read data from the data store"
for item in self.store:
include_item = all(
query_value == item[key]
for key, query_value in query.items()
)
if include_item:
yield item
def query_update(self, query, values):
"Update items in the data store"
for item in self.store:
update_item = all(
query_value == item[key]
for key, query_value in query.items()
)
if update_item:
for key, updated_value in values.items():
item[key] = updated_value
def query_delete(self, query):
"Delete items from the data store"
for i, item in enumerate(self.store.copy()):
delete_item = all(
query_value == item[key]
for key, query_value in query.items()
)
if delete_item:
del self.store[i]
Then we may use this repository as:
>>> repo = MyRepo()
>>> # Creating some items
>>> repo.add({'name': 'Jack', 'age': 30})
>>> repo.add({'name': 'John', 'age': 30})
>>> repo.add({'name': 'James', 'age': 40})
>>> # Getting all items
>>> repo.filter_by().all()
[
{'name': 'Jack', 'age': 30},
{'name': 'John', 'age': 30},
{'name': 'James', 'age': 40}
]
>>> # Getting an item
>>> repo.filter_by(age=30).first()
{'name': 'Jack', 'age': 30}
>>> # Getting some items depending on the query
>>> repo.filter_by(age=30).all()
[
{'name': 'Jack', 'age': 30},
{'name': 'John', 'age': 30}
]
>>> # Updating some items
>>> repo.filter_by(name='James').update(age=41)
>>> # Deleting some items
>>> repo.filter_by(age=30).delete()
Template Class#
- class redbird.templates.TemplateRepo(*, model=<class 'dict'>, id_field=None, query_model=<class 'redbird.base.BasicQuery'>, errors_query='raise', field_access='infer', ordered=False)
Template repository for easy subclassing
- Parameters
model (Type) – Class of an item in the repository. Commonly dict or subclass of Pydantic BaseModel. By default dict
id_field (str, optional) – Attribute or key that identifies each item in the repository.
field_access ({'attr', 'key'}, optional) – How to access a field in an item. Either by attribute (‘attr’) or key (‘item’). By default guessed from the model.
query (Type, optional) – Query model of the repository.
errors_query ({'raise', 'warn', 'discard'}) – Whether to raise an exception, warn or discard the item inn case of validation error in converting data to the item model from the repository. By default raise
Examples
class MyRepo(TemplateRepo): def insert(self, item): # Insert item to the data store ... def query_read(self, query: dict): # Get data from repository for item in ...: yield item def query_update(self, query: dict, values: dict): # Update items with values matcing the query ... def query_delete(self, query: dict): # Delete items matcing the query ... def item_to_data(self, item): # Convert item to type that is understandable # by the repository's data store ... return data
- cls_result
alias of
redbird.templates.TemplateResult
- query_data(query)
Query (read) the data store and return raw data
Override this or
query_items()
method.- Parameters
query (dict) – Repository query, by default dict.
- Returns
Iterable of raw data that is converted to an item using
data_to_item()
- Return type
iterable (any)
Examples
Used in following cases:
repo.filter_by(color="red").all()
- query_items(query)
Query (read) the data store and return items
Override this or
query_data()
method.- Parameters
query (dict) – Repository query, by default dict.
- Returns
Items that are instances of the class in the
model
attibute. Typically dicts or instances of subclassed Pydantic BaseModel- Return type
iterable (
model
)
Examples
Used in following cases:
repo.filter_by(color="red").all()
- abstract query_update(query, values)
Update the result of the query with given values
Override this method.
- Parameters
query (any) – Repository query, by default dict.
Examples
Used in following cases:
repo.filter_by(color="red").update(color="blue")
- abstract query_delete(query)
Delete the result of the query
Override this method.
- Parameters
query (any) – Repository query, by default dict.
Examples
Used in following cases:
repo.filter_by(color="red").delete()
- query_read_first(query)
Query the first item
You may override this method. By default, the first item returned by
TemplateRepo.query_read
is returned.- Parameters
query (any) – Repository query, by default dict.
Examples
Used in the following case:
repo.filter_by(color="red").first()
- query_read_limit(query, n)
Query the first n items
You may override this method. By default, the N first items returned by
TemplateRepo.query_read
are returned.- Parameters
query (any) – Repository query, by default dict.
n (int) – Number of items to return
Examples
Used in the following case:
repo.filter_by(color="red").limit(3)
- query_read_last(query)
Query the last item
You may override this method. By default, the last item returned by
TemplateRepo.query_read
is returned.- Parameters
query (any) – Repository query, by default dict.
Examples
Used in the following case:
repo.filter_by(color="red").last()
- query_replace(query, values)
Replace the items with given values using given query
You may override this method. By default, the result of the query is deleted and an item from the values is generated.
- Parameters
query (any) – Repository query, by default dict.
values (dict) – Values to replace the items’ existing values with
Examples
Used in the following case:
repo.filter_by(color="red").replace(color="blue")
- query_count(query)
Count the items returned by the query
You may override this method. By default, the items returned by
TemplateRepo.query_read
are counted.- Parameters
query (any) – Repository query, by default dict.
Examples
Used in the following case:
repo.filter_by(color="red").count()
- format_query(query)
Format the query to a format suitable by the repository
You may override this method. By default, the query is as dictionary.
- Parameters
query (dict) – Query to reformat
Examples
Used in the following case:
repo.filter_by(color="red")