Designing a class with a simple key

It is helpful to store the shelve key as an attribute of a shelved object. Keeping the key in the object makes the object easier to delete or replace. Clearly, when creating an object, we'll start with a keyless version of the object until it's stored in the shelf. Once stored, the Python object needs to have a key attribute set so that each object in the memory contains a correct key.

When retrieving objects, there are two use cases. We might want a specific object that is known by the key. In this case, the shelf will map the key to the object. We might also want a collection of related objects not known by their keys, but perhaps known by the values of some other attributes. In this case, we'll discover the keys of objects through some kind of search or query. We'll look at the search algorithms in the following Designing CRUD operations for complex objects section.

To support saving the shelf keys in objects, we'll add an _id attribute to each object. It will keep the shelve key in each object that has been put onto the shelf or retrieved from the shelf. This will simplify managing objects that need to be replaced in or removed from the shelf. A surrogate key won't have any method functions, for example, and it is never part of the processing layer of the application tier or the presentation tier. Here's a definition for an overall Blog:

from dataclasses import dataclass, asdict, field
@dataclass
class Blog:

title: str
entries: List[Post] = field(default_factory=list)
underline: str = field(init=False, compare=False)

# Part of the persistence, not essential to the class.
_id: str = field(default="", init=False, compare=False)

def __post_init__(self) -> None:
self.underline = "=" * len(self.title)

We've provided the essential title attribute. The entries attribute is optional, and has a default value of an empty list. underline is computed as a string with a length that matches the title; this makes some part of reStructuredText formatting slightly simpler. 

We can create a Blog object in the following manner:

>>> b1 = Blog(title="Travel Blog") 

This will have an empty list of individual postings within the blog. When we store this simple object in the shelf, we can do operations including the following:

>>> import shelve
>>> from pathlib import Path
>>> shelf = shelve.open(str(Path.cwd() / "data" / "ch11_blog"))
>>> b1._id = 'Blog:1'
>>> shelf[b1._id] = b1

We started by opening a new shelf. The file will end up being called ch11_blog.db. We put a key, Blog:1, into our Blog instance, b1. We stored that Blog instance in the shelf using the key given in the _id attribute.

We can fetch the item back from the shelf like this:

>>> shelf['Blog:1']
Blog(title='Travel Blog', entries=[], underline='===========', _id='Blog:1')
>>> shelf['Blog:1'].title
'Travel Blog'
>>> shelf['Blog:1']._id
'Blog:1'
>>> list(shelf.keys())
['Blog:1']
>>> shelf.close()

When we refer to shelf['Blog:1'], it will fetch our original Blog instance from the shelf. We've put only one object on the shelf, as we can see from the list of keys. Because we closed the shelf, the object is persistent. We can quit Python, start it back up again, open the shelf, and see that the object remains on the shelf, using the assigned key. Previously, we mentioned a second use case for retrieval—locating an item without knowing the key. Here's a search that locates all the blogs with a given title:

>>> path = Path.cwd() / "data" / "ch11_blog"
>>> shelf = shelve.open(str(path))
>>> results = (shelf[k]
... for k in shelf.keys()
... if k.startswith('Blog:') and shelf[k].title == 'Travel Blog'
... )
>>> list(results)
[Blog(title='Travel Blog', entries=[], underline='===========', _id='Blog:1')]

We opened the shelf to get access to the objects. The results generator expression examines each item in the shelf to locate those items where the key starts with 'Blog:', and the object's title attribute is the 'Travel Blog' string.

What's important is that the key, 'Blog:1', is stored within the object itself. The _id attribute ensures that we have the proper key for any item that our application is working with. We can now mutate any attribute of the object (except the key) and replace it in the shelf using its original key.

Now, let's see how to design classes for containers or collections.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset