Skip to content

Commit

Permalink
moving message return to ajax view
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelcolvin committed Sep 23, 2016
1 parent 6c1104b commit a10ed93
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 45 deletions.
6 changes: 5 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ root = true
end_of_line = lf
insert_final_newline = true

[*.txt,*.js,*.css,*.jinja]
indent_style = space
indent_size = 2

[*.py]
indent_style = space
indent_size = 4
line_length=120
line_length = 120

[Makefile]
indent_style = tab
Expand Down
4 changes: 2 additions & 2 deletions aiohttp_devtools/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ def runserver(**config):
@click.argument('path', type=_path_type, required=True)
@click.argument('name', required=False)
@click.option('--template-engine', type=click.Choice(Options.TEMPLATE_ENG_CHOICES), default=Options.TEMPLATE_ENG_JINJA2)
@click.option('--session', type=click.Choice(Options.SESSION_CHOICES), default=Options.SESSION_SECURE)
@click.option('--database', type=click.Choice(Options.DB_CHOICES), default=Options.DB_PG_SA)
@click.option('--session', type=click.Choice(Options.SESSION_CHOICES), default=Options.NONE)
@click.option('--database', type=click.Choice(Options.DB_CHOICES), default=Options.NONE)
def start(*, path, name, template_engine, session, database):
"""
Create a new aiohttp app.
Expand Down
13 changes: 8 additions & 5 deletions aiohttp_devtools/start/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,12 @@ def __init__(self, *, path: str, name: str, template_engine: str, session: str,
self.files_created = 0
self.ctx = {
'name': name,
'template_engine': {'is_' + o: template_engine == o for o in Options.TEMPLATE_ENG_CHOICES},
'session': {'is_' + o: session == o for o in Options.SESSION_CHOICES},
'database': {'is_' + o: database == o for o in Options.DB_CHOICES},
'template_engine': {'is_' + o.replace('-', '_'): template_engine == o
for o in Options.TEMPLATE_ENG_CHOICES},
'session': {'is_' + o.replace('-', '_'): session == o
for o in Options.SESSION_CHOICES},
'database': {'is_' + o.replace('-', '_'): database == o
for o in Options.DB_CHOICES},
}
self.generate_directory(TEMPLATE_DIR)
display_path = self.project_root.relative_to(Path('.').resolve())
Expand All @@ -74,8 +77,8 @@ def generate_file(self, p: Path):
return

if p.name == 'requirements.txt':
lines = set(filter(bool, text.split('\n')))
text = '\n'.join(sorted(lines))
packages = {p.strip() for p in text.split('\n') if p.strip()}
text = '\n'.join(sorted(packages))
elif p.suffix == '.py':
# helpful when debugging: print(text.replace(' ', '·').replace('\n', '⏎\n'))
for regex, repl in PY_REGEXES:
Expand Down
3 changes: 2 additions & 1 deletion aiohttp_devtools/start/template/app/routes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .views import index, messages
from .views import index, messages, message_data


def setup_routes(app):
app.router.add_get('/', index, name='index')
app.router.add_route('*', '/messages', messages, name='messages')
app.router.add_get('/messages/data', message_data, name='message-data')
9 changes: 2 additions & 7 deletions aiohttp_devtools/start/template/app/templates/messages.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,8 @@
</form>

<h2>Messages:</h2>
<ul>
{% for message in messages %}
<li><b>{{ message.username }}:</b> {{ message.message }}, ({{ message.timestamp }})</li>
{% else %}
<li>No messages found.</li>
{% endfor %}
</ul>
<div id="messages" data-url="{{ 'message-data'|url }}"></div>
<script src="{{ 'message_display.js'|static }}"></script>
{% endblock %}
{% endraw %}
{% endif %}
94 changes: 71 additions & 23 deletions aiohttp_devtools/start/template/app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@

from aiohttp import web
from aiohttp.hdrs import METH_POST
# {% if template_engine.is_jinja2 %}
from aiohttp.web_exceptions import HTTPFound
from aiohttp.web_reqrep import json_response
# {% if template_engine.is_jinja2 %}
from aiohttp_jinja2 import template
# {% endif %}

Expand All @@ -26,27 +27,41 @@ async def index(request):
'message': "Success! you've setup a basic aiohttp app.",
}


# {% else %}

BASE_PAGE = """\
<title>{title}</title>
<link href="{styles_css_url}" rel="stylesheet">
<body>
<main>
<h1>{title}</h1>
{content}
</main>
</body>"""

async def index(request):
"""
This is the view handler for the "/" url.
**Note: returning html without a template engine like jinja2 is ugly, no way round that.**
:param request: the request object see http://aiohttp.readthedocs.io/en/stable/web_reference.html#request
:return: aiohttp.web.Response object
"""
content = """\
<!DOCTYPE html>
<head>
<title>{title}</title>
<link href="{styles_css}" rel="stylesheet">
</head>
<body>
<h1>{title}</h1>
<p>{message}</p>
</body>"""
return web.Response(text='<body>hello</body>', content_type='text/html')
# Note: in the name of brevity we return stripped down html,
# this works fine on chrome but shouldn't be used in production,
# the <body> tag is required to activate aiohttp-debugtoolbar
ctx = dict(
title=request.app['name'],
styles_css_url=request.app['static_url'] + '/styles.css',
content="""\
<p>Success! you've setup a basic aiohttp app.</p>
<p>To demonstrate a little of the functionality of aiohttp this app implements a very simple message board.</p>
<b>
<a href="{message_url}">View and add messages</a>
</b>""".format(message_url=request.app.router['messages'].url())
)
return web.Response(text=BASE_PAGE.format(**ctx), content_type='text/html')
# {% endif %}


Expand All @@ -66,7 +81,7 @@ async def process_form(request):
new_message['username'] = new_message['username'].replace('|', '')
with MESSAGE_FILE.open('a') as f:
now = datetime.now().isoformat()
f.write('{username}|{timestamp:%Y-%m-%d %H:%M}|{message}'.format(timestamp=now, **new_message))
f.write('{username}|{timestamp}|{message}'.format(timestamp=now, **new_message))
raise HTTPFound(request.app.router['messages'].url())


Expand All @@ -80,6 +95,47 @@ async def messages(request):
else:
form_errors = None

# {% if template_engine.is_jinja2 %}
return {
'title': 'Message board',
'form_errors': form_errors,
'messages': messages,
}
# {% else %}
ctx = dict(
title=request.app['name'],
styles_css_url=request.app['static_url'] + '/styles.css',
content="""\
<h2>Add a new message:</h2>
<form method="post" action="{message_url}">
{form_errors}
<p>
<label for="username">Your name:</label>
<input type="text" name="username" id="username" placeholder="fred blogs">
<label for="message">Message:</label>
<input type="text" name="message" id="message" placeholder="hello there">
</p>
<button type="submit">Post Message</button>
</form>
<h2>Messages:</h2>
<div id="messages" data-url="{message_data_url}"></div>
<script src="{message_display_js_url}"></script>""".format(
message_url=request.app.router['messages'].url(),
message_data_url=request.app.router['message-data'].url(),
message_display_js_url=request.app['static_url'] + '/message_display.js',
form_errors=form_errors and '<div class="form-errors">{}</div>'.format(form_errors)
)
)
return web.Response(text=BASE_PAGE.format(**ctx), content_type='text/html')
# {% endif %}


async def message_data(request):
"""
As an example of aiohttp providing a non-html response, we load the actual messages for the "message" above
via ajax using this endpoint to get data. see static/message_display.js for details of rendering.
"""
messages = []
if MESSAGE_FILE.exists():
lines = MESSAGE_FILE.read_text().split('\n')
Expand All @@ -89,12 +145,4 @@ async def messages(request):
username, ts, message = line.split('|', 2)
ts = '{:%Y-%m-%d %H:%M:%S}'.format(datetime.strptime(ts, '%Y-%m-%dT%H:%M:%S.%f'))
messages.append({'username': username, 'timestamp': ts, 'message': message})
# {% if template_engine.is_jinja2 %}
return {
'title': 'Message board',
'form_errors': form_errors,
'messages': messages,
}
# {% else %}
raise NotImplementedError()
# {% endif %}
return json_response(messages)
20 changes: 14 additions & 6 deletions aiohttp_devtools/start/template/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
{# This file is special: lines are made unique and sorted before the new requirements.tzt file is created #}
{# This file is special: lines are made unique, stripped and sorted before the new requirements.txt file is created #}

aiohttp==1.0.2

{% if template_engine.is_jinja2 %}
aiohttp-jinja2==0.8.0
aiohttp-jinja2==0.8.0
{% endif %}

{% if session.is_vanilla %}
aiohttp-session==0.5.0
aiohttp-session==0.5.0
{% elif session.is_secure %}
aiohttp-session[secure]==0.5.0
aiohttp-session[secure]==0.5.0
{% elif session.is_redis %}
aiohttp-session[aioredis]==0.5.0
aiohttp-session[aioredis]==0.5.0
{% endif %}

{# TODO: others #}
{% if database.is_postgres_sqlalchemy or database.is_postgres_raw %}
aiopg==0.11.0
{% if database.is_postgres_sqlalchemy %}
SQLAlchemy==1.0.15
{% endif %}
{% endif %}
30 changes: 30 additions & 0 deletions aiohttp_devtools/start/template/static/message_display.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// some very basic javascript to populate the message board
// for simplicity this has not external requirements

var messages = document.getElementById('messages');

function request_state_changed() {
if (this.readyState != 4) {
return;
}
if (this.status != 200) {
console.warn('error getting messages:', r);
alert('error getting messages, response:' + this.status);
return;
}
var data = JSON.parse(this.responseText);
if (data.length == 0) {
messages.innerHTML = 'No messages available.'
} else {
messages.innerHTML = '<ul>';
data.forEach(function (m) {
messages.innerHTML += '<li>' + m.username + ': <b>' + m.message + '</b>, (' + m.timestamp + ')</li>'
});
messages.innerHTML += '</ul>';
}
}

var r = new XMLHttpRequest();
r.open('GET', messages.getAttribute('data-url'), true);
r.onreadystatechange = request_state_changed;
r.send('');

0 comments on commit a10ed93

Please sign in to comment.