Skip to content

Commit

Permalink
Refactor demo (#981)
Browse files Browse the repository at this point in the history
* Refactor demo code

* Update docs
  • Loading branch information
asvetlov authored Jul 22, 2016
1 parent 80d1d1c commit a5b75e0
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 87 deletions.
64 changes: 38 additions & 26 deletions demos/polls/aiohttpdemo_polls/db.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import aiopg.sa
import sqlalchemy as sa


Expand Down Expand Up @@ -34,32 +35,43 @@ class RecordNotFound(Exception):
"""Requested record in database was not found"""


async def get_question(postgres, question_id):
async with postgres.acquire() as conn:
cursor = await conn.execute(
question.select()
.where(question.c.id == question_id))
question_record = await cursor.first()
if not question_record:
msg = "Question with id: {} does not exists"
raise RecordNotFound(msg.format(question_id))
cursor = await conn.execute(
choice.select()
.where(choice.c.question_id == question_id)
.order_by(choice.c.id))
choice_recoreds = await cursor.fetchall()
async def init_postgres(conf, loop):
engine = await aiopg.sa.create_engine(
database=conf['database'],
user=conf['user'],
password=conf['password'],
host=conf['host'],
port=conf['port'],
minsize=conf['minsize'],
maxsize=conf['maxsize'],
loop=loop)
return engine


async def get_question(conn, question_id):
result = await conn.execute(
question.select()
.where(question.c.id == question_id))
question_record = await result.first()
if not question_record:
msg = "Question with id: {} does not exists"
raise RecordNotFound(msg.format(question_id))
result = await conn.execute(
choice.select()
.where(choice.c.question_id == question_id)
.order_by(choice.c.id))
choice_recoreds = await result.fetchall()
return question_record, choice_recoreds


async def vote(postgres, question_id, choice_id):
async with postgres.acquire() as conn:
resp = await conn.execute(
choice.update()
.returning(*choice.c)
.where(choice.c.question_id == question_id)
.where(choice.c.id == choice_id)
.values(votes=choice.c.votes + 1))
record = await resp.fetchone()
if not record:
msg = "Question with id: {} or choice id: {} does not exists"
raise RecordNotFound(msg.format(question_id), choice_id)
async def vote(conn, question_id, choice_id):
result = await conn.execute(
choice.update()
.returning(*choice.c)
.where(choice.c.question_id == question_id)
.where(choice.c.id == choice_id)
.values(votes=choice.c.votes+1))
record = await result.fetchone()
if not record:
msg = "Question with id: {} or choice id: {} does not exists"
raise RecordNotFound(msg.format(question_id), choice_id)
14 changes: 8 additions & 6 deletions demos/polls/aiohttpdemo_polls/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
PROJ_ROOT = pathlib.Path(__file__).parent.parent


async def close_pg(app):
app['db'].close()
await app['db'].wait_closed()


async def init(loop):
# setup application and extensions
app = web.Application(loop=loop)
Expand All @@ -24,16 +29,13 @@ async def init(loop):
conf = load_config(str(PROJ_ROOT / 'config' / 'polls.yaml'))

# create connection to the database
pg = await init_postgres(conf['postgres'], loop)

async def close_pg(app):
pg.close()
await pg.wait_closed()
db = await init_postgres(conf['postgres'], loop)
app['db'] = db

app.on_cleanup.append(close_pg)

# setup views and routes
handler = SiteHandler(pg)
handler = SiteHandler(db)
setup_routes(app, handler, PROJ_ROOT)
setup_middlewares(app)

Expand Down
15 changes: 8 additions & 7 deletions demos/polls/aiohttpdemo_polls/routes.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from .views import index, poll, results, vote

def setup_routes(app, handler, project_root):
add_route = app.router.add_route
add_route('GET', '/', handler.index)
add_route('GET', '/poll/{question_id}', handler.poll, name='poll')
add_route('GET', '/poll/{question_id}/results',
handler.results, name='results')
add_route('POST', '/poll/{question_id}/vote', handler.vote, name='vote')

def setup_routes(app, project_root):
app.router.add_route('GET', '/', index)
app.router.add_route('GET', '/poll/{question_id}', poll, name='poll')
app.router.add_route('GET', '/poll/{question_id}/results',
results, name='results')
app.router.add_route('POST', '/poll/{question_id}/vote', vote, name='vote')
app.router.add_static('/static/',
path=str(project_root / 'static'),
name='static')
14 changes: 0 additions & 14 deletions demos/polls/aiohttpdemo_polls/utils.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,8 @@
import yaml
import aiopg.sa


def load_config(fname):
with open(fname, 'rt') as f:
data = yaml.load(f)
# TODO: add config validation
return data


async def init_postgres(conf, loop):
engine = await aiopg.sa.create_engine(
database=conf['database'],
user=conf['user'],
password=conf['password'],
host=conf['host'],
port=conf['port'],
minsize=conf['minsize'],
maxsize=conf['maxsize'],
loop=loop)
return engine
36 changes: 19 additions & 17 deletions demos/polls/aiohttpdemo_polls/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,22 @@
from . import db


class SiteHandler:
@aiohttp_jinja2.template('index.html')
async def index(request):
async with request['db'].acquire() as conn:
cursor = await conn.execute(db.question.select())
records = await cursor.fetchall()

def __init__(self, pg):
self.postgres = pg

@aiohttp_jinja2.template('index.html')
async def index(self, request):
async with self.postgres.acquire() as conn:
cursor = await conn.execute(db.question.select())
records = await cursor.fetchall()
questions = [dict(q) for q in records]
return {'questions': questions}

@aiohttp_jinja2.template('detail.html')
async def poll(self, request):

@aiohttp_jinja2.template('detail.html')
async def poll(request):
async with request['db'].acquire() as conn:
question_id = request.match_info['question_id']
try:
question, choices = await db.get_question(self.postgres,
question, choices = await db.get_question(conn,
question_id)
except db.RecordNotFound as e:
raise web.HTTPNotFound(text=str(e))
Expand All @@ -29,12 +27,14 @@ async def poll(self, request):
'choices': choices
}

@aiohttp_jinja2.template('results.html')
async def results(self, request):

@aiohttp_jinja2.template('results.html')
async def results(request):
async with request['db'].acquire() as conn:
question_id = request.match_info['question_id']

try:
question, choices = await db.get_question(self.postgres,
question, choices = await db.get_question(conn,
question_id)
except db.RecordNotFound as e:
raise web.HTTPNotFound(text=str(e))
Expand All @@ -44,7 +44,9 @@ async def results(self, request):
'choices': choices
}

async def vote(self, request):

async def vote(request):
async with request['db'].acquire() as conn:
question_id = int(request.match_info['question_id'])
data = await request.post()
try:
Expand All @@ -53,7 +55,7 @@ async def vote(self, request):
raise web.HTTPBadRequest(
text='You have not specified choice value') from e
try:
await db.vote(self.postgres, question_id, choice_id)
await db.vote(conn, question_id, choice_id)
except db.RecordNotFound as e:
raise web.HTTPNotFound(text=str(e))
router = request.app.router
Expand Down
46 changes: 29 additions & 17 deletions docs/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ and second table is choice table:
| question_id |
+---------------+

TBD: aiopg.sa.create_engine and pushing it into app's storage

TBD: graceful cleanup


.. _aiohttp-tutorial-views:

Expand All @@ -156,16 +160,17 @@ next Python code inside file (``polls/aiohttpdemo_polls/views.py``)::
from aiohttp import web


class SiteHandler:
async def index(self, request):
return web.Response(text='Hello Aiohttp!')
async def index(self, request):
return web.Response(text='Hello Aiohttp!')

This is the simplest view possible in Aiohttp. Now we should add ``index`` view
to ``polls/aiohttpdemo_polls/routes.py``::

def setup_routes(app, handler, project_root):
add_route = app.router.add_route
add_route('GET', '/', handler.index)
from .views import index


def setup_routes(app, project_root):
app.router.add_route('GET', '/', index)

Now if we open browser we can see::

Expand All @@ -181,17 +186,18 @@ Templates
Let's add more useful views::

@aiohttp_jinja2.template('detail.html')
async def poll(self, request):
question_id = request.match_info['question_id']
try:
question, choices = await db.get_question(self.postgres,
question_id)
except db.RecordNotFound as e:
raise web.HTTPNotFound(text=str(e))
return {
'question': question,
'choices': choices
}
async def poll(request):
async with request['db'].acquire() as conn:
question_id = request.match_info['question_id']
try:
question, choices = await db.get_question(conn,
question_id)
except db.RecordNotFound as e:
raise web.HTTPNotFound(text=str(e))
return {
'question': question,
'choices': choices
}

Templates are very convinient way forweb page writing. We return a
dict with page content, ``aiohttp_jinja2.template`` decorator
Expand Down Expand Up @@ -235,3 +241,9 @@ Fortunatelly it can be done easy by single call::


where ``project_root`` is the path to root folder.


Middlewares
-----------

TBD

0 comments on commit a5b75e0

Please sign in to comment.