Gosto sempre de relembrar no início dos tópicos que esta é uma série de criação de uma página dinâmica usando Python e Flask. O site é um site informativo sobre a pandemia de Covid-19. Todo o código feito até agora está neste repositório:
QuarantineDaysOfCode/covid at master · ThiagoDiasV/QuarantineDaysOfCode · GitHubNosso site já começa a tomar forma. Hoje vamos incrementar um pouco mais nosso index.html. E ao final vou lançar um desafio pra vocês.
No site que já está no ar (
Covid-19), no index, temos algumas informações que não temos ainda em nosso projeto local:

Uma é a imagem de um desenho de vírus no que seria a logo, e a outra são os dados confirmados, recuperados e mortes no mundo. Além disso, nosso título na aba também tem uma imagem de um vírus

Vamos adicionar essas três informações hoje.
Eu peguei esta imagem abaixo para ser a imagem que iria pra logo:

Não se preocupem com ela, vou mandar pro repositório do Github as imagens.
Mas a imagem é muito grande. Eu poderia diminuí-la usando CSS, ou usando algum programa de edição de imagens, mas nesses casos, como é uma imagem para a logo e outra imagem de tamanho inferior para ser o ícone que vai aparecer na página, eu prefiro usar serviços de terceiros que já criam todas as imagens que eu possa precisar usar de forma bem rápida. Para o caso deste projeto, eu usei este serviço:
Favicon & App Icon GeneratorNele você faz upload da imagem que quer editar os tamanhos e pode gerar ícones de diversos tamanhos. Lá no repositório eu vou jogar todas as imagens que estou usando no projeto.
Agora eu preciso criar uma pasta para os arquivos estáticos.
Por que estáticos? Porque são arquivos que o Python, por meio do Flask, não tem poder algum de alterá-los. Diferentemente dos templates, que o Python "injeta" dados nos templates, os arquivos estáticos não podem ser alterados. Aqui nós iremos inserir arquivos CSS, JavaScript e imagens.
Então vamos criar essa pasta chamada "static" e dentro dela adicionar 3 novas pastas, "img", "css" e "js", e jogar todas as imagens criadas dentro da pasta img:

A lista de imagens criadas inclui todas estas aqui:

Vamos criar um ícone para nossa página. Vamos lá no base.html e adicionar uma tag link com o atributo "rel" com valor "icon":
<link
rel="icon"
type="image/png"
sizes="32x32"
href="{{ url_for('static', filename='img/favicon-32x32.png') }}"
/>
Aqui eu devo usar a imagem dentro das chaves duplas e usar novamente a função "url_for", só que passo como atributos uma string indicando que estou usando a pasta static e o nome do arquivo.
O <head> do meu base.html agora fica assim:
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="{{ url_for('static', filename='img/favicon.ico') }}"
/>
<title>Covid-19</title>
</head>
Salvando, já podemos ver um ícone na nossa aba;

Vamos adicionar a mesma imagem agora ao lado da logo:
<a href="{{ url_for('index') }}" class="navbar-brand">
<img
src="{{ url_for('static', filename='img/favicon-32x32.png') }}"
alt="Imagem de um vírus"
/>
Covid-19</a
>
O início da nossa barra de navegação agora fica assim:
<div class="container">
<a href="{{ url_for('index') }}" class="navbar-brand">
<img
src="{{ url_for('static', filename='img/favicon-32x32.png') }}"
alt="Imagem de um vírus"
/>
Covid-19</a
>
<button
class="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbar-content"
>
E nosso site já tem uma imagem ao lado da logo:

Tudo certo com essa parte mais relacionada a estilos.
Agora vamos fazer uma nova chamada à nossa API, em um endpoint diferente, e obter os dados de casos confirmados, mortes e recuperados ao redor do mundo.
Observando a doc da API, o endpoint que eu quero acessar agora é /covid19/total.
A URL total será
https://api.covid19.finspect.me/covid19/totalUm GET nesse endpoint me retorna um JSON assim:
[
{
"ID": 438,
"CreatedAt": "2020-04-02T14:30:10Z",
"UpdatedAt": "2020-04-02T14:30:10Z",
"DeletedAt": null,
"confirmed": 931893,
"deaths": 46798,
"recovered": 193177
}
]
Então agora vamos lá no nosso routes.py e fazer uma chamada à API:
@app.route("/")
def index():
request = requests.get('h t t p s : / / a p i.covid19.finspect.me/covid19/total')
world_total_data = request.json()
print(world_total_data)
return render_template("index.html")
Resolvi printar antes de tudo. Vamos rodar nosso projeto e acessar o index. Basta dar um f5 na página inicial.
O console vai mostrar isto aqui:
[{'ID': 1118, 'CreatedAt': '2020-04-16T18:30:10Z', 'UpdatedAt': '2020-04-16T18:30:10Z', 'DeletedAt': None, 'confirmed': 2055342, 'deaths': 134165, 'recovered': 511019}]
Observem que isso é uma lista de um dicionário só. Eu quero só o dicionário, então vou ter que alterar meu world_total_data para me mostrar somente o dicionário:
world_total_data = request.json()[0]
Agora o console mostra só o dicionário:
{'ID': 1118, 'CreatedAt': '2020-04-16T18:30:10Z', 'UpdatedAt': '2020-04-16T18:30:10Z', 'DeletedAt': None, 'confirmed': 2055342, 'deaths': 134165, 'recovered': 511019}
Mas aí tem dados que eu posso até usar como a data de atualização, etc. Mas eu vou filtrar esse dicionário para me dar só os 3 dados acima. Confirmados, mortes e recuperados.
Para isso vou criar um dict comprehension, assim:
ipdb> world_total_data
{'ID': 1119, 'CreatedAt': '2020-04-16T19:00:14Z', 'UpdatedAt': '2020-04-16T19:00:14Z', 'DeletedAt': None, 'confirmed': 2055342, 'deaths': 134165, 'recovered': 511019}
ipdb> dic = {k: v for k, v in world_total_data.items() if k == 'confirmed' or k == 'deaths' or k == 'recovered'}
ipdb> dic
{'confirmed': 2055342, 'deaths': 134165, 'recovered': 511019}
A chave tá aqui
dic = {k: v for k, v in world_total_data.items() if k == 'confirmed' or k == 'deaths' or k == 'recovered'}
Isso é um dict comprehension, ou compreensão de dicionários. É uma forma de filtrar o dicionário principal obtendo só os valores que eu quero. E obtivemos como retorno o dicionário da forma que pedi.
Dúvida sobre dict comprehensions? Dá uma olhada aqui
2.7 - Python - Dicionários - Tecnologia - Bastter.comEntão vamos fazer isso no nosso routes.py, filtrar os valores:
# Criando nossa primeira rota
@app.route("/")
def index():
request = requests.get('https://api.covid19.finspect.me/covid19/total')
world_total_data = request.json()[0]
world_data = {
key: value for key, value in world_total_data.items()
if key == "confirmed" or key == "deaths" or key == "recovered"
}
return render_template("index.html", world_data=world_data)
Vejam que já passei os resultados para nosso template no render_template.
Vamos mudar o template para mostrar esses dados. Só ir no index.html:
<ul class="list-group">
<li class="list-group-item">
Confirmados:
<span>{{ world_data["confirmed"] }}</span>
</li>
<li class="list-group-item">
Recuperados: <span>{{ world_data["recovered"] }}</span>
</li>
<li class="list-group-item">
Mortes: <span>{{ world_data["deaths"] }}</span>
</li>
</ul>
Atualizando nossa página inicial, temos:

Tá, ok, mas fica meio estranho ver números grandes sem os pontos a cada 3 dígitos, né?
É muito mais legível ler 511.019 recuperados do que 511019.
Aqui deve ter formas mais fácil inclusive usando extensões do Flask para templates. Já vi uma em Django, talvez sirva pra Flask, que torne esses números mais facilmente visualizáveis.
Mas no nosso projeto eu decidi fazer isso à mão, até porque não é algo que dá trabalho, é um algoritmo simples.
Mas hoje vou fazer diferente. Até o momento só vocês me observaram digitar e digitar e digitar e colar imagens e códigos aqui. Hoje eu quero que quem tá acompanhando o projeto crie um algoritmo que vá enviar os dados para o front-end de forma que eles fiquem apresentados dessa forma:

Em vez desta forma:

Não vale usar libs externas. Só vale usar Python puro. Não vale sair procurando no Stack OverFlow logo de cara. É um exercício, deve ser tentado antes de se buscar uma resposta. Espero ver alguém tentando rs
Amanhã eu posto a solução que eu implementei mas queria ver alguém tentando e postando a resposta abaixo. Boa sorte pra quem tentar e continuaremos nosso projeto amanhã. Amanhã começaremos a implementar gráficos com os dados.