fix __all__ error in exclude, update docs
This commit is contained in:
88
docs/transactions.md
Normal file
88
docs/transactions.md
Normal file
@ -0,0 +1,88 @@
|
||||
# Transactions
|
||||
|
||||
Database transactions are supported thanks to `encode/databases` which is used to issue async queries.
|
||||
|
||||
## Basic usage
|
||||
|
||||
To use transactions use `database.transaction` as async context manager:
|
||||
|
||||
```python
|
||||
async with database.transaction():
|
||||
# everyting called here will be one transaction
|
||||
await Model1().save()
|
||||
await Model2().save()
|
||||
...
|
||||
```
|
||||
|
||||
!!!note
|
||||
Note that it has to be the same `database` that the one used in Model's `Meta` class.
|
||||
|
||||
To avoid passing `database` instance around in your code you can extract the instance from each `Model`.
|
||||
Database provided during declaration of `ormar.Model` is available through `Meta.database` and can
|
||||
be reached from both class and instance.
|
||||
|
||||
```python
|
||||
import databases
|
||||
import sqlalchemy
|
||||
import ormar
|
||||
|
||||
metadata = sqlalchemy.MetaData()
|
||||
database = databases.Database("sqlite:///")
|
||||
|
||||
class Author(ormar.Model):
|
||||
class Meta:
|
||||
database=database
|
||||
metadata=metadata
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=255)
|
||||
|
||||
# database is accessible from class
|
||||
database = Author.Meta.database
|
||||
|
||||
# as well as from instance
|
||||
author = Author(name="Stephen King")
|
||||
database = author.Meta.database
|
||||
|
||||
```
|
||||
|
||||
You can also use `.transaction()` as a function decorator on any async function:
|
||||
|
||||
```python
|
||||
@database.transaction()
|
||||
async def create_users(request):
|
||||
...
|
||||
```
|
||||
|
||||
Transaction blocks are managed as task-local state. Nested transactions
|
||||
are fully supported, and are implemented using database savepoints.
|
||||
|
||||
## Manual commits/ rollbacks
|
||||
|
||||
For a lower-level transaction API you can trigger it manually
|
||||
|
||||
```python
|
||||
transaction = await database.transaction()
|
||||
try:
|
||||
await transaction.start()
|
||||
...
|
||||
except:
|
||||
await transaction.rollback()
|
||||
else:
|
||||
await transaction.commit()
|
||||
```
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
Transactions can also be useful during testing when you can apply force rollback
|
||||
and you do not have to clean the data after each test.
|
||||
|
||||
```python
|
||||
@pytest.mark.asyncio
|
||||
async def sample_test():
|
||||
async with database:
|
||||
async with database.transaction(force_rollback=True):
|
||||
# your test code here
|
||||
...
|
||||
```
|
||||
Reference in New Issue
Block a user