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 repository

  • query_data(query): This method gets items from the repository accoding to query

  • query_update(query, values): This method updates items in the repository matching to query with values defined in values

  • query_delete(query): This method deletes items from the repository matching the given query

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 the query

  • query_read_limit(query, n): This method queries the first n items from the data store from items matching the query

  • query_read_last(query): This method queries the last item from the data store from items matching the query

  • query_replace(query, values): This method replaces the found item(s) from the data store from items matching the query using the values given in values

  • query_count(query): This method counts the values from the data store from items matching the query

The following methods could also be implemented for handling of the internals:

  • item_to_data(item): This method transforms an instance of repo.model to data undestood by the underlying data store

  • data_to_item(data): This method transforms raw data from the data store to an instance of repo.model

  • format_query(query): This method formats the query 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")