Skip to content

Added base usage example for aiohttp server #231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
.DS_Store
.idea/
.vscode
.venv/
.env

# Byte-compiled / optimized / DLL files
__pycache__/
Expand All @@ -10,6 +13,7 @@ __pycache__/

# Distribution / packaging
.Python
.installed.cfg
env/
venv/
build/
Expand All @@ -23,7 +27,6 @@ parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg*
*.ini

Expand Down
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Overview
The complete documentation:
http://peewee-async-lib.readthedocs.io


Install
-------

Expand All @@ -37,14 +38,14 @@ or for MySQL:
pip install peewee-async[mysql]
```


Quickstart
----------

Create 'test' PostgreSQL database for running this snippet:

createdb -E utf-8 test


```python
import asyncio
import peewee
Expand Down Expand Up @@ -99,35 +100,54 @@ with objects.allow_sync():
# Not bad. Watch this, I'm async!
```


More examples
-------------

Build and run with Docker Compose:

```bash
docker compose -f examples/docker-compose.yaml build
docker compose -f examples/docker-compose.yaml up
```


Documentation
-------------

http://peewee-async-lib.readthedocs.io

http://peewee-async.readthedocs.io - **DEPRECATED**


Developing
----------

Install dependencies using pip:

```bash
pip install -e .[develop]
```

Or using [poetry](https://python-poetry.org/docs/):

```bash
poetry install -E develop
```

Run databases:

```bash
docker-compose up -d
```

Run tests:

```bash
pytest tests -v -s
```


Discuss
-------

Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ services:
postgres:
image: postgres
ports:
- '5432:5432'
- ${POSTGRES_PORT:-5432}:5432
command: postgres -c log_statement=all
environment:
- POSTGRES_PASSWORD=postgres
Expand All @@ -14,7 +14,7 @@ services:
mysql:
image: mysql
ports:
- '3306:3306'
- ${MYSQL_PORT:-3306}:3306
environment:
- MYSQL_ROOT_PASSWORD=mysql
- MYSQL_DATABASE=mysql
54 changes: 54 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
Examples for peewee-async
=========================

To run the examples install dependencies first:

```bash
pip install -r examples/requirements.txt
```

Also please run database service and provide credentials in environment variables.
Feel free to use development database services with the default credentials, e.g:

```bash
docker compose up postgres
```

## Example for `aiohttp` server

The example `aiohttp_example.py` is using older interface with `Manager` class. The `Manager`
will be deprecated in v1.0 but we aim to support it until that milestone.

Define database connection settings if needed, environment variables used:

- `POSTGRES_DB`
- `POSTGRES_USER`
- `POSTGRES_PASSWORD`
- `POSTGRES_HOST`
- `POSTGRES_PORT`

Run this command to create example tables in the database:

```bash
python -m examples.aiohttp_example
```

Run this command to start an example application:

```bash
gunicorn --bind 127.0.0.1:8080 --log-level INFO --access-logfile - \
--worker-class aiohttp.GunicornWebWorker --reload \
examples.aiohttp_example:app
```

Application should be up and running:

```bash
curl 'http://127.0.0.1:8080/?p=1'
```

the output should be:

```
This is a first post
```
104 changes: 104 additions & 0 deletions examples/aiohttp_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import json
import logging
import os
from secrets import token_hex
from datetime import datetime
from aiohttp import web
from peewee import Model, CharField, TextField, DateTimeField
from peewee_async import PooledPostgresqlDatabase, Manager

logger = logging.getLogger(__name__)

database = PooledPostgresqlDatabase(
os.environ.get('POSTGRES_DB', 'postgres'),
user=os.environ.get('POSTGRES_USER', 'postgres'),
password=os.environ.get('POSTGRES_PASSWORD', 'postgres'),
host=os.environ.get('POSTGRES_HOST', '127.0.0.1'),
port=int(os.environ.get('POSTGRES_PORT', 5432)),
min_connections=2,
max_connections=10,
)

objects = Manager(database)

app = web.Application()

routes = web.RouteTableDef()


class Post(Model):
title = CharField(unique=True)
key = CharField(unique=True, default=lambda: token_hex(8))
text = TextField()
created_at = DateTimeField(index=True, default=datetime.utcnow)

class Meta:
database = database

def __str__(self):
return self.title


def add_post(title, text):
with database.atomic():
Post.create(title=title, text=text)


@routes.get('/')
async def get_post_endpoint(request):
query = dict(request.query)
post_id = query.pop('p', 1)
post = await objects.get_or_none(Post, id=post_id)
if post:
return web.Response(text=post.text)
else:
return web.Response(text="Not found", status=404)


@routes.post('/')
async def update_post_endpoint(request):
query = dict(request.query)
post_id = query.pop('p', 1)
try:
data = await request.content.read()
data = json.loads(data)
text = data.get('text')
if not text:
raise ValueError("Missing 'text' in data")
except Exception as exc:
return web.Response(text=str(exc), status=400)

post = await objects.get_or_none(Post, id=post_id)
if post:
post.text = text
await objects.update(post)
return web.Response(text=post.text)
else:
return web.Response(text="Not found", status=404)


# Setup application routes

app.add_routes(routes)


if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)

print("Initialize tables and add some random posts...")

try:
with database:
database.create_tables([Post], safe=True)
print("Tables are created.")
except Exception as exc:
print("Error creating tables: {}".format(exc))

try:
add_post("Hello, world", "This is a first post")
add_post("Hello, world 2", "This is a second post")
add_post("42", "What is this all about?")
add_post("Let it be!", "Let it be, let it be, let it be, let it be")
print("Done.")
except Exception as exc:
print("Error adding posts: {}".format(exc))
11 changes: 11 additions & 0 deletions examples/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fastapi==0.111.0
uvicorn==0.29.0
tornado==6.4
aiohttp==3.9.5
gunicorn==22.0.0

aiopg~=1.4.0
aiomysql~=0.2.0

peewee~=3.17.3
# peewee-async~=0.10.0
2 changes: 1 addition & 1 deletion peewee_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ def execute_sql(self, *args, **kwargs):
return super().execute_sql(*args, **kwargs)

async def fetch_results(self, query, cursor):
if isinstance(query, peewee.ModelCompoundSelectQuery):
if isinstance(query, peewee.BaseModelSelect):
return await AsyncQueryWrapper.make_for_all_rows(cursor, query)
if isinstance(query, peewee.RawQuery):
return await AsyncQueryWrapper.make_for_all_rows(cursor, query)
Expand Down
2 changes: 0 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ pytest-asyncio = { version = "^0.21.1", optional = true }
sphinx = { version = "^7.1.2", optional = true }
sphinx-rtd-theme = { version = "^1.3.0rc1", optional = true }



[tool.poetry.extras]
postgresql = ["aiopg"]
mysql = ["aiomysql", "cryptography"]
Expand Down
Loading