---
tags: web,day1
robots: noindex, nofollow
lang: pt-br
---
https://github.com/rochacbruno/python-web-api/tree/main/docs
# 11 Criando seu próprio framework
Você já deve ter ouvido falar do **Flask** ? um dos principais frameworks para desenvolvimento web com Python, agora vamos fazer um exercicio bem simples, vamos criar nosso próprio framework que vai funcionar de maneira similar ao Flask.
A primeira tarefa é escolher qual será o nome do framework, e você pode escolher o nome que você quiser!
Eu por exemplo vou dar ao meu framework o nome do meu filho `Erik` e você ai no seu ambiente pode acompanhar este exercicio dando o nome que você quiser! pode usar o nome de uma pessoa, de um animal de estimação, de um personagem do seu filme favorito.
Precisa de idéias?
- Corleone framework
- Tony framework
- Dwight framework
- SpaceGhost framework
- Banana framework
- Tapioca framework
- Farofa framework
Use sua criatividade.
Por enquanto toda a lógica do nosso programa está em `wsgi.py` vamos então criar um novo arquivo na mesma pasta.
```bash
# use o nome que quiser,
# desde que siga as regras de nomenclatura do Python
# tudo em minusculo, sem espaços.
touch erik.py
```
Agora vamos usar orientação a objetos para transformar o que tinhamos no `wsgi.py` usando apenas funções para um modelo usando orientação a objetos, portanto no arquivo `erik.py` (lembre-se que você pode usar o nome que quiser) nós vamos.
01. Criar uma classe para representar a `app` do nosso framework
00. Inicializar os objetos essenciais de um framework
- Mapa de roteamento de URLs
- Configuração de template
- Ambiente do motor de templates
00. Um decorator para registar novas URLs no estilo do Flask.
00. Um método para renderizar templates.
00. A aplicação `wsgi` implementada em um método `__call__`
00. Um método `run` para executar a aplicação
Um framework web em 60 linhas de código :)
```py
import cgi
import json
import re
from wsgiref.simple_server import make_server
from jinja2 import Environment, FileSystemLoader
class Erik: # Dê o nome que quiser :) ex: `class Banana`
def __init__(self):
self.url_map = []
self.template_folder = "templates"
self.env = Environment(loader=FileSystemLoader("templates"))
def route(self, rule, method="GET", template=None):
def decorator(view):
self.url_map.append((rule, method, view, template))
return view
return decorator
def render_template(self, template_name, **context):
template = self.env.get_template(template_name)
return template.render(**context).encode("utf-8")
def __call__(self, environ, start_response):
path = environ["PATH_INFO"]
request_method = environ["REQUEST_METHOD"]
body = b"Content Not Found"
status = "404 Not Found"
ctype = "text/html"
for rule, method, view, template in self.url_map:
match = re.match(rule, path)
if match:
if method != request_method:
continue
view_args = match.groupdict()
if method == "POST":
view_args["form"] = cgi.FieldStorage(
fp=environ["wsgi.input"],
environ=environ,
keep_blank_values=1,
)
view_result = view(**view_args)
if isinstance(view_result, tuple):
view_result, status, ctype = view_result
else:
status = "200 OK"
if template:
body = self.render_template(template, **view_result)
elif (
isinstance(view_result, dict)
and ctype == "application/json"
):
body = json.dumps(view_result).encode("utf-8")
else:
body = str(view_result).encode("utf-8")
start_response(status, [("Content-type", ctype)])
return [body]
def run(self, host="0.0.0.0", port=8000):
server = make_server(host, port, self)
server.serve_forever()
```
Podemos testar com:
```py
app = Erik()
@app.route("^/$")
def foo():
return "Hello"
@app.route("^/(?P<id>\d{1,})$")
def foo2(id):
return f"Hello {id}", 400, "foo"
# Simular chamadas HTTP
print(
app(
{"PATH_INFO": "/1234", "REQUEST_METHOD": "GET"},
lambda *args: print(args),
)
)
print(
app(
{"PATH_INFO": "/", "REQUEST_METHOD": "GET"},
lambda *args: print(args),
)
)
```
O resultado
```
(400, [('Content-type', 'foo')])
[b'Hello 1234']
('200 OK', [('Content-type', 'text/html')])
[b'Hello']
```
Agora vamos colocar em uso em nosso blog, alteramos o arquivo `wsgi.py` para usar o nosso framework.
```py
from database import conn
from erik import Erik
app = Erik()
@app.route("^/$", template="list.template.html")
def post_list():
posts = get_posts_from_database()
return {"post_list": posts}
@app.route("^/(?P<id>\d{1,})$", template="post.template.html")
def post_detail(id):
post = get_posts_from_database(post_id=id)[0]
return {"post": post}
@app.route("^/new$", template="form.template.html")
def new_post_form():
return {}
@app.route("^/new$", method="POST")
def new_post_add(form):
post = {item.name: item.value for item in form.list}
add_new_post(post)
return "New post Created with Success!", "201 Created", "text/plain"
def get_posts_from_database(post_id=None):
cursor = conn.cursor()
fields = ("id", "title", "content", "author")
if post_id:
results = cursor.execute("SELECT * FROM post WHERE id = ?;", post_id)
else:
results = cursor.execute("SELECT * FROM post;")
return [dict(zip(fields, post)) for post in results]
def add_new_post(post):
cursor = conn.cursor()
cursor.execute(
"""\
INSERT INTO post (title, content, author)
VALUES (:title, :content, :author);
""",
post,
)
conn.commit()
if __name__ == "__main__":
app.run()
```
## Conclusão:
Criar um framework com Python é super divertido, porém tem muito mais coisas que um framework precisa fazer:
- Facilidade no registro de rotas
- Segurança e autenticação
- Sessões e Cookies
- Execução assincrona
Para não ter esse trabalho todo manualmente, vamos deixar nosso framerwork caseiro de lado e começar a conhecer as soluções prontas para Python.
Finalizamos aqui o Day 1 e no próximo daremos inicio ao aprendizado dos frameworks Django, Flask e FastAPI :)
Até o Day 2 :)