Skip to content

Commit

Permalink
Config Factory 🐹
Browse files Browse the repository at this point in the history
  • Loading branch information
rochacbruno committed Sep 30, 2017
1 parent dd1b40e commit b515f1a
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 37 deletions.
87 changes: 59 additions & 28 deletions cms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,56 +22,87 @@ cms/ # module root
└── settings.yml # Configurações que serão carregadas
```

O Flask pode ler configurações de objetos, módulos Python e arquivos json
de acordo com o https://12factor.net/pt_br/config devemos ter configurações
default na aplicação mas todas as configurações variáveis deve ficar no ambiente.

Para isto usaremos a extensão `FlaskDynaconf` do módulo `dynaconf` com esta
extensão podemos ler as configurações a partir de arquivos, bancos de dados e
variáveis de ambiente.

Em nosso CMS iremos ler as configurações de um arquivo `settings.yml` e também opcionalmente
de variáveis de ambiente.

```yaml
CMS:
SECRET_KEY: 'real_secret_here'
DB_NAME: cms_db
SITENAME: Flask CMS
HOST: '0.0.0.0'
PORT: 5000
DEBUG: true
RELOADER: true
```
Para começar a implentação do **config factory** no `config/__init__.py`

```py
from dynaconf.contrib.flask_dynaconf import FlaskDynaconf
agora nós temos a implementação de `app/__init__.py` com o application factory.
def configure(app):
"""Configure Dynaconf Flask Extension"""
FlaskDynaconf(
app=app,
DYNACONF_NAMESPACE='CMS',
SETTINGS_MODULE=f'{app.root_path}/settings.yml'
)
```

E então invocaremos essa função no `app factory` em `app/__init__.py`

```py
from flask import Flask
from cms import config
def create_app():
app = Flask(__name__)
# Faça o que quiser com o `app` aqui:
# Iniciar o sistema de configurações dinâmicas
config.configure(app)
return app
```

e então no `cli.py` importamos esse factory
e então no `cli.py` podemos utilizar alguns valores default a partir do
`app.config`

```py
from .app import create_app
Nas mensagens podemos fazer algo como:

app = create_app()
```py
click.echo(f'Iniciando o shell do {app.config.SITENAME}')
```

A partir daqui já podemos executar alguns comandos:

```bash

$ cms shell
>>> app.

e também nas opções dos comandos.

$ cms runserver --port 8000
* Running on http://0.0.0.0:3000/ (Press CTRL+C to quit)
```py
...
@click.option('--debug/--no-debug', default=app.config.DEBUG)
@click.option('--reloader/--no-reloader', default=app.config.RELOADER)
@click.option('--host', default=app.config.HOST)
@click.option('--port', default=app.config.PORT)
def runserver(debug, reloader, host, port):
...
```

No entanto se rodarmos o `cms adduser` teremos mais um erro:
Pronto agora em qualquer momento podemos reescrever as configs no arquivo `settings.yml` ou exportar como variáveis de ambiente

```bash
$ cms adduser
Username:
Password:
Repeat password:
...

AttributeError: 'Flask' object has no attribute 'db'

export CMS_PORT='@int 3000'
export CMS_HOST='127.0.0.1'
export CMS_SITENAME='Meu Flask CMS!'
```

Ainda precisamos terminar de configurar o `app` e adicionar a conexão com um banco de
dados. (falarei mais dos detalhes a respeito em breve)

Mas antes vamos agora criar o `config factory`
O próximo passo é carregar algumas extensões no `extension factory`
11 changes: 8 additions & 3 deletions cms/app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
from flask import Flask
from cms import config


def create_app():
app = Flask(__name__)
def create_app(import_name):
"""import_name tem que ser sempre a raiz do projeto
onde está o cli.py, templates/ e static/"""

# Faça o que quiser com o `app` aqui:
app = Flask(import_name)

# Iniciar o sistema de configurações dinâmicas
config.configure(app)

return app
13 changes: 7 additions & 6 deletions cms/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import click
from .app import create_app

app = create_app()
app = create_app(__name__)


@click.group()
Expand All @@ -16,19 +16,20 @@ def shell():
Se o ipython estiver instalado irá iniciar um shell Ipython
Caso contrário iniciará um shell Python puro.
"""
click.echo(f'Iniciando o shell do {app.config.SITENAME}')
with app.app_context():
try:
from IPython import start_ipython
start_ipython(argv=[], user_ns={'app': app})
except:
code.interact(banner='My Flask APP', local={'app': app})
code.interact(banner=app.config.SITENAME, local={'app': app})


@main.command()
@click.option('--debug/--no-debug', default=True)
@click.option('--reloader/--no-reloader', default=True)
@click.option('--host', default='0.0.0.0')
@click.option('--port', default=5000)
@click.option('--debug/--no-debug', default=app.config.DEBUG)
@click.option('--reloader/--no-reloader', default=app.config.RELOADER)
@click.option('--host', default=app.config.HOST)
@click.option('--port', default=app.config.PORT)
def runserver(debug, reloader, host, port):
"""Inicia o servidor em modo dev/debug"""
app.run(debug=debug, use_reloader=reloader, host=host, port=port)
Expand Down
16 changes: 16 additions & 0 deletions cms/config/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from dynaconf.contrib.flask_dynaconf import FlaskDynaconf


def configure(app):
"""Configure Dynaconf Flask Extension
Dynaconf permite que variaveis sejam carregadas de diversas fontes
e arquivos diferentes.
Como arquivos yaml, ini, json,
bancos de dados como Mongo ou Redis
e variavéis de ambiente
"""
FlaskDynaconf(
app=app,
DYNACONF_NAMESPACE='CMS',
SETTINGS_MODULE=f'{app.root_path}/settings.yml'
)
8 changes: 8 additions & 0 deletions cms/settings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CMS:
SECRET_KEY: 'real_secret_here'
DB_NAME: cms_db
SITENAME: Flask CMS
HOST: '0.0.0.0'
PORT: 5000
DEBUG: true
RELOADER: true

0 comments on commit b515f1a

Please sign in to comment.