Skip to content
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

Refactor demo #981

Merged
merged 2 commits into from
Jul 22, 2016
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
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