diff --git a/flask-40mins.html b/flask-40mins.html index 3aaa80e..0ef4d8c 100644 --- a/flask-40mins.html +++ b/flask-40mins.html @@ -64,7 +64,7 @@
-
+

Flask em 40 Minutos ou Menos

@@ -103,53 +103,53 @@
-
-
-

Motivação

- -
    -
  • Flask é super simples, mas poderoso.
  • -
  • Python é super simples, mas poderoso.
  • -
  • Ninguém fala como é colocar isso em produção.
  • -
- - -
-
- -
-
-

A aplicação

- -

- Um sistema de atas de reunião onde as atas - são arquivos MarkDown, com a data no nome. -

- - -
- -
-

Estrutura de diretórios

- -
├── ata
+                
+
+

Motivação

+ +
    +
  • Flask é super simples, mas poderoso.
  • +
  • Python é super simples, mas poderoso.
  • +
  • Ninguém fala como é colocar isso em produção.
  • +
+ + +
+
+ +
+
+

A aplicação

+ +

+ Um sistema de atas de reunião onde as atas + são arquivos MarkDown, com a data no nome. +

+ + +
+ +
+

Estrutura de diretórios

+ +
├── ata
 │   ├── defaults.py
 │   ├── __init__.py
 │   ├── main.py
@@ -164,116 +164,498 @@
 ├── contents
 │   └── 2017-10-31.md
 └── requirements.txt
-
- -
-

├── ata

- -

Módulo/fontes.

- - -
- -
-

│   ├── defaults.py

- -

Valores default da aplicação.

- - -
- -
-

│   ├── __init__.py

- -

- __init__.py é necessário - para indicar ao Python que o diretório - pode se lido. -

-
- -
-

│   ├── main.py

- -

O arquivo inicial da aplicação.

- - -
- -
-

│   ├── static

- -

- Arquivos estáticos. -

- - -
- -
-

│   └── templates

- -

- Arquivos de template. -

- - -
- -
-

├── contents

- -

- Onde o conteúdo a ser apresentado está. -

- - -
- -
-

└── requirements.txt

- -

- Dependências do projeto. -

- - -
-
+
+ +
+

├── ata

+ +

Módulo/fontes.

+ + +
+ +
+

│   ├── defaults.py

+ +

Valores default da aplicação.

+ + +
+ +
+

│   ├── __init__.py

+ +

+ __init__.py é necessário + para indicar ao Python que o diretório + pode se lido. +

+
+ +
+

│   ├── main.py

+ +

O arquivo inicial da aplicação.

+ + +
+ +
+

│   ├── static

+ +

+ Arquivos estáticos. +

+ + +
+ +
+

│   └── templates

+ +

+ Arquivos de template. +

+ + +
+ +
+

├── contents

+ +

+ Onde o conteúdo a ser apresentado está. +

+ + +
+ +
+

└── requirements.txt

+ +

+ Dependências do projeto. +

+ + +
+
+ +
+
+

requirements.txt

+ +
flask~=0.12.2
+Markdown~=2.6.9
+ + +
+
+ +
+
+

main.py

+

Imports

+ +
import os
+import os.path
+
+import markdown
+
+from flask import Flask
+from flask import render_template
+ + +
+ +
+

main.py

+

A App

+ +
app = Flask(__name__)
+ + +
+ +
+

main.py

+

Configuração

+ +
app.config.from_object('ata.defaults')
+app.config.from_envvar('ATA_SETTINGS', silent=True)
+ + +
+ +
+

main.py

+

A primeira rota.

+ +
@app.route('/')
+def index():
+ + +
+ +
+

main.py

+

O índice

+ +
    content = os.listdir(app.config['STORAGE'])
+    data = []
+    for entry in sorted(content, reverse=True):
+        app.logger.debug('Found %s', entry)
+        if not entry.endswith('.md'):
+            continue
+
+        with open(os.path.join(app.config['STORAGE'], entry)) as origin:
+            content = origin.read()
+            output = markdown.markdown(content)
+            try:
+                first_paragraph_end = output.index('

') + paragraph = output[:first_paragraph_end] + except ValuError: + paragraph = output + + entry_name = entry[:entry.find('.md')] + data.append((entry_name, output)) + + return render_template('index.html', data=data)
+ + +
+ +
+

main.py

+

Entradas específicas

+ +
@app.route('/<entry_name>')
+def show_entry(entry_name):
+    filename = os.path.join(app.config['STORAGE'], entry_name + '.md')
+    with open(filename) as origin:
+        content = origin.read()
+        output = markdown.markdown(content)
+
+    return render_template('entry.html', output=output,
+                           entry=entry_name)
+ + +
+ +
+

main.py

+

Tratamento de erros.

+ +
@app.errorhandler(404)
+def page_not_found():
+    return render_template('page_not_found.html')
+ + +
+ +
+

main.py

+

Tratamento de erros

+ +
@app.errorhandler(FileNotFoundError)
+def entry_not_found(_):
+    return render_template('entry_not_found.html')
+ + +
+
+ +
+
+

defaults.py

+ +
DEBUG=True
+STORAGE='/home/jbiason/src/ata/contents'
+ + +
+
+ +
+
+

style.css

+ +
h1#header {
+    background-color: black;
+    color: white;
+    padding: 10px;
+}
+
+.entry {
+    margin-left: 30px;
+    margin-right: 30px;
+    margin-bottom: 15px;
+}
+ + +
+
+ +
+
+

templates

+

layout.html

+ +
<!doctype html>
+<html>
+    <head>
+        <title>Atas de Reunião</title>
+        <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
+    </head>
+
+    <body>
+        <h1 id='header'>
+            Atas de reuniao
+        </h1>
+        {% block maincontent %}{% endblock %}
+    </body>
+</html>
+ + +
+ +
+

templates

+

index.html

+ +
{% extends "layout.html" %}
+{% block maincontent %}
+    <div class='entry'>
+        {% for entry, text in data %}
+        <a href="{{ url_for('show_entry', entry_name=entry) }}">{{ entry }}</a>
+            {{ text|safe }}
+        {% endfor %}
+    </div>
+{% endblock %}
+ + +
+ +
+

templates

+

entry.html

+ +
{% extends "layout.html" %}
+{% block maincontent %}
+    <div class="entry">
+        <div class="title">{{ entry }}</div>
+        {{ output|safe }}
+    </div>
+{% endblock %}
+ + +
+ +
+

templates

+

page_not_found.html

+ +
{% extends "layout.html" %}
+{% block maincontent %}
+    <h2>Page not found</h2>
+{% endblock %}
+ + +
+ +
+

templates

+

entry_not_found.html

+ +
{% extends "layout.html" %}
+{% block maincontent %}
+    <h2>Entry not found</h2>
+{% endblock %}
+ + +