Skip to content

Commit e974daa

Browse files
Add Extending Model examples.
1 parent d307a77 commit e974daa

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import asyncio
4242

4343
# ...
4444

45+
4546
async def a_query() -> None:
4647
# we'll come back to this part
4748
# just know that it usins async/await to call Client.execute_and_return
@@ -66,6 +67,7 @@ import asyncio
6667

6768
# ...
6869

70+
6971
async def a_query() -> None:
7072
query = 'SELECT table_name' \
7173
'FROM information_schema.tables' \
@@ -93,6 +95,7 @@ To define a `Model`'s expected type, you simply need to subclass `ModelData` & s
9395
```python
9496
from db_wrapper import ModelData
9597

98+
9699
class AModel(ModelData):
97100
a_string_value: str
98101
a_number_value: int
@@ -123,6 +126,7 @@ from db_wrapper import (
123126
connection_parameters = ConnectionParameters(...)
124127
client = Client(...)
125128

129+
126130
class AModel(ModelData):
127131
# ...
128132

@@ -136,6 +140,73 @@ from typing import List
136140

137141
# ...
138142

143+
139144
async get_some_record() -> List[AModel]:
140145
return await a_model.read.one_by_id('some record id') # NOTE: in reality the id would be a UUID
141146
```
147+
148+
Of course, just having methods for creating, reading, updating, or deleting a single record at a time often won't be enough.
149+
Adding additional queries is accomplished by extending Model's CRUD properties.
150+
151+
For example, if you want to write an additional query for reading any record that that has a value of `'some value'` in the field `a_field`, you would start by subclassing `Read`, the class that `Model.read` is an instance of:
152+
153+
```python
154+
from db_wrapper import ModelData
155+
from db_wrapper.model import Read
156+
from psycopg2 import sql
157+
158+
# ...
159+
160+
161+
class AnotherModel(ModelData):
162+
a_field: str
163+
164+
165+
class ExtendedReader(Read[AnotherModel]):
166+
"""Add custom method to Model.read."""
167+
168+
async def all_with_some_string_value(self) -> List[AnotherModel]:
169+
"""Read all rows with 'some value' for a_field."""
170+
171+
# Because db_wrapper uses aiopg under the hood, & aiopg uses
172+
# psycopg2, we can define our queries safely using psycopg2's
173+
# sql module
174+
query = sql.SQL(
175+
'SELECT * '
176+
'FROM {table} ' # a Model knows it's own table name, no need to specify it manually here
177+
'WHERE a_field = 'some value';'
178+
).format(table=self._table)
179+
180+
result: List[AnotherModel] = await self \
181+
._client.execute_and_return(query)
182+
183+
return result
184+
```
185+
186+
Then, you would subclass `Model` & redefine it's read property to be an instance of your new `ExtendedReader` class:
187+
188+
```python
189+
from db_wrapper import Client, Model, ModelData
190+
191+
# ...
192+
193+
class ExtendedModel(Model[AnotherModel]):
194+
"""Build an AnotherModel instance."""
195+
196+
read: ExtendedReader
197+
198+
def __init__(self, client: Client) -> None:
199+
super().__init__(client, 'another_model_table') # you can supply your table name here
200+
self.read = ExtendedReader(self.client, self.table)
201+
```
202+
203+
Finally, using your `ExtendedModel` is simple, just initialize the class with a `Client` instance & use it just as you would your previous `Model` instance, `a_model`:
204+
205+
```python
206+
# ...
207+
208+
another_model = AnotherModel(client)
209+
210+
async def read_some_value_from_another_model() -> None:
211+
return await another_model.all_with_some_string_value()
212+
```

0 commit comments

Comments
 (0)