Programando Do Zero – DebugEverything https://blog.debugeverything.com Uma nova maneira de aprender programação Sun, 18 Apr 2021 05:18:59 +0000 pt-BR hourly 1 https://wordpress.org/?v=7.1.4 https://blog.debugeverything.com/wp-content/uploads/2021/04/cropped-DE_white-32x32.png Programando Do Zero – DebugEverything https://blog.debugeverything.com 32 32 [Do Zero] Construindo um app com React Hooks – Versão estendida e detalhada https://blog.debugeverything.com/pt/do-zero-construindo-um-app-com-react-js/ https://blog.debugeverything.com/pt/do-zero-construindo-um-app-com-react-js/#comments Mon, 25 May 2020 07:01:16 +0000 https://debugeverything.com/?p=1283 React é uma biblioteca JavaScript front-end que pode ser usada para criar interfaces interativas de usuário para sua aplicação. Neste tutorial, você vai criar um aplicativo do tipo “ToDo List” que cobre todos os quatro aspectos de um CRUD: Criar, Ler, Atualizar e Excluir.

Este tipo de projeto é frequentemente feito com componentes de Classe, mas este aplicativo irá integrar React Hooks. Os React Hooks permitem que os componentes funcionais tenham um estado e utilizem métodos de ciclo de vida, permitindo que você evite usar componentes de classe e tenha código mais modular e legível.

Sem mais demora, vamos começar!

Primeiro Passo 1 — Iniciar um novo React App

Instalando npm

Para instalar o React, precisamos do npm que é um gerenciador de pacotes para o JavaScript.

npm é instalado junto com Node.js. Isto significa que você tem que instalar o Node.js para ter o npm instalado no seu computador.

Baixe o Node.js do site oficial: https://nodejs.org

Criando um novo app

Vamos rodar o comando create-react-app dentro do terminal, na pasta onde você quer criar o seu projeto, seguido do nome do nosso projeto, que vai ser react-to-do, vai ficar assim:

$ npx create-react-app react-to-do

npx é uma ferramenta para rodar pacotes npm que vivem dentro da pasta de node_modules local ou não são instalados globalmente, essa ferramenta já vem na instalação do Node.js.

E o comando create-react-app instala as dependências necessárias para construir seu projeto React, e gera a estrutura inicial que veremos a seguir.

Uma vez finalizada a instalação, vamos testar a aplicação, basta rodar esses dois comandos, no mesmo terminal:

$ cd react-to-do
$ npm run start

Com o primeiro comando você vai entrar na pasta que o o comando create-react-app criou, se você trocou o nome do projeto, você precisa mudar aqui também.

O segundo comando roda um serviço do Node.js para hospedar a sua aplicação. Ele vai hospedar a sua aplicação em um serviço local na rota http://localhost:3000/.

O browser deve abrir automaticamente e você vai ver algo parecido com isso:

Se caso o browser não abrir direto, você pode digitar localhost:3000 no seu navegador para abrir a sua aplicação, provavelmente esse símbolo vai estar rodando.

Passo 2 – Criando uma lista de items

Com a sua aplicação em execução, vamos começar na parte de leitura do CRUD. Vamos fazer uma lista de coisas para que possamos Ler/visualizar.

Mas antes disso vamos remover todo o código desnecessário do nosso src/App.js, seu arquivo deve ficar igual a esse:

import React from 'react';
import './App.css';

function App() {
  return (
    <div className="App">

    </div>
  );
}

export default App;

Criando um novo componente

Agora vamos criar uma nova pasta chamada components e dentro dessa pasta criar um arquivo com o nome TodoList.js

Esse componente vai ser responsável por exibir a lista de items na nossa tela.

Na declaração do nosso componente nós vamos incluir dois parâmetros: todos e updateTodos.

function TodoList({ todos, updateTodos }) {
...
}

Nesse momento vamos prestar atenção apenas ao primeiro parâmetro, todos. O segundo parâmetro nós vamos tratar mais na frente.

Esse parâmetro, é a lista com todos os items da nossa lista. Nós vamos receber a lista do componente principal, sempre atualizada, para exibir para o usuário.

Então com poucas linhas, já conseguimos mostrar a nossa lista, a parte principal do nosso componente fica assim:

<div className="todo-list">
  {todos.map((todo, index) => (
    <div
      key={index}
      className="todo">
      Item {index + 1}: {todo.task}
    </div>
  ))}
</div>

Repare que todo o código está dentro de uma <div>, que contém uma propriedade, className="todo-list". Essa propriedade insere uma nova classe CSS nesse componente, no caso a classe CSS todo-list, que vou mostrar mais pra frente.

Repare que, React usa className="" e não apenas class="" como fazemos normalmente com HTML, o motivo por trás disso é que React usa JSX, vou criar um post dedicado pra explicar mais sobre JSX.

Mas por hora entende que é apenas uma maneira de escrever HTML em arquivos Javascript.

Então, assim que o componente recebe a lista, o que precisamos fazer é apenas iterar sobre a lista e exibir para o usuário. Estou fazendo isso utilizando a função Array.map() do Javascript.

todos.map((todo, index) => (
  ...
))

Para exibir então as tarefas, utilizei mais uma <div>, dentro do Array.map(), com duas propriedades muito importantes.

Uma delas, className="todo", eu já comentei lá trás, vai aplicar um classe CSS no nosso elemento.

A segunda propriedade key={index} ajudam React a identificar quais itens foram alterados, adicionados ou removidos.

As chaves(keys) devem ser incluídas no seu array, mas nesse caso, como os items da nossa lista não tem ids, vamos usar o index referente a posição dele no array.

Na última linha, como você deve imaginar, é onde exibimos todos os itens da lista, juntamente com um contador.

<div
  key={index}
  className="todo">
  Item {index + 1}: {todo.task}
</div>

O código completo do componente TodoList do nosso React App, ficou assim até agora:

//TodoList
import React from 'react';

function TodoList({ todos, updateTodos }) {
  return (
    <div className="todo-list">
      {todos.map((todo, index) => (
        <div
          key={index}
          className="todo">
          Item {index + 1}: {todo.task}
        </div>
      ))}
    </div>
  );
};

export default TodoList;

Adicionando estilo ao App

Antes de exibir a nossa lista, vou criar as classes CSS que comentei, assim nossa lista vai ficar mais apresentável. Foi por isso que não removi a chamada ./App.css do nosso App.js, você vai inserir o código lá.

/* App.css */
.App {
  background: #27292d;
  padding: 30px;
  height: 100vh;
}

.todo-list {
  margin: auto;
  background: rgb(112, 111, 111);
  border-radius: 4px;
  padding: 5px;
  max-width: 400px;
}

.todo {
  background: #fff;
  box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.15);
  padding: 10px 10px;
  font-size: 20px;
  border-radius: 3px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  cursor: pointer;
}

O layout aqui não é o foco do nosso projeto, então vou pular as explicações.

Adicionando um novo state

De volta ao nosso App.js, nós vamos usar React Hooks, então o estado vai parecer um pouco diferente do que se usássemos classes.

Antes de mais nada, precisamos importar o nosso Hook useState da biblioteca react, assim:

import React, { useState } from 'react';

Agora já podemos criar o nosso primeiro state usando Hooks, ele vai ficar assim:

const [todos, setTodos] = useState();

React Hooks são uma nova adição no React 16.8. Eles permitem que você use recursos de estado e outros sem precisar de uma class.

  • O primeiro parâmetro, todos, é o nome do nosso estado.
  • O segundo parâmetro, setTodos, é o que vamos usar para definir o estado.

O hook useState() é o que o React usa para conectar ao estado ou ciclo de vida do componente. Nós então criamos um array de objetos e definimos como valor inicial do nosso state.

Definindo um estado inicial

O nosso state consiste de um array de objetos. Onde nós vamos definir 3 tarefas, seguindo esse formato:

[
  { complete: false, task: "Read about MongoDb" },
  { complete: false, task: "Create a React ToDo App" },
  { complete: false, task: "Find my key" }
]

O primeiro atributo complete vai indicar se a tarefa já foi concluída ou não. Já o segundo atributo, task, é a descrição da tarefa.

Portanto, toda nova tarefa vai ser inserida na lista já existente. No “mundo real”, essa lista viria provavelmente do seu banco de dados.

Nosso state, vai ficar assim

const [todos, setTodos] = useState([
  { complete: false, task: "Read about MongoDb" },
  { complete: false, task: "Create a React ToDo App" },
  { complete: false, task: "Find my key" }
]);

Por último, precisamos importar e declarar o nosso novo componente, TodoList, dentro do nosso App.js.

import TodoList from './components/TodoForm';

E precisamos também passar para ele, a lista de tarefas inicial através da propriedade todos, que definimos lá no nosso componente TodoList.

<TodoList todos={todos}></TodoList>

O código completo do componente App do nosso React App, ficou assim até agora:

import React from 'react';
import './App.css';
import TodoList from './components/TodoForm';

function App() {
    const [todos, setTodos] = useState([
        { complete: false, task: "Read about MongoDb" },
        { complete: false, task: "Create a React ToDo App" },
        { complete: false, task: "Find my key" }
      ]);
  return (
    <div className="App">
      <TodoList todos={todos}></TodoList>
    </div>
  );
}

export default App;

O seu todo app deve estar com essa cara no momento:

Passo 3 – Criando novos items na lista

Agora, vamos dar ao nosso aplicativo o poder de criar um novo item para a nossa lista.

Vamos criar mais um componente.

Na mesma pasta do TodoList, crie um componente chamado TodoForm, esse vai ser o componente responsável por criar e submeter novos items para a lista.

Nesse componente nós vamos definir um segundo state, que vai receber a entrada do usuário, vindas do formulário. Nesse state vamos iniciar passando uma string vazia apenas, (isso vai fazer sentido logo mais).

const [userInput, setUserInput] = useState("");

Parâmetros do componente

Assim como variáveis e constantes, nós também podemos enviar funções entre componentes. E é exatamente o que estamos fazendo aqui.

...
function TodoForm({ addTodo }) {
...
}

O parâmetro addTodo é na verdade um método. O método addTodo()não é declarado no componente TodoForm e sim recebido com um dos parâmetros durante a declaração do componente.

Com esse método, nós vamos enviar todos os dados que recebermos do usuário, para o nosso componente principal App.js onde o nosso state principal mora.

Criando o Formulário

Podemos agora criar nosso formulário para receber os dados. A declaração do formulário recebe duas propriedades, a primeira onSubmit={handleSubmit} é onde fazemos a chamada da função que vai manipular os dados do usuário.

A segunda, className="todo-form" é a inclusão de uma classe CSS nesse elemento.

<form onSubmit={handleSubmit} className="todo-form">

E dentro do nosso formulário o nosso único input, responsável por receber os dados do usuário.

<input
    placeholder="New Task"
    type="text"
    value={userInput}
    onChange={e => setUserInput(e.target.value)}
/>

Nós definimos a propriedade value={userInput} para apagar do formulário, após a submissão, o que o usuário escreveu. Se a propriedade value não estiver presente e recebendo o valor do estado, toda vez que o usuário inserir e submeter uma nova tarefa, o texto não vai ser apagado do input.

A nossa última propriedade, é a cereja do bolo. onChange é uma propriedade padrão da tag <input />, o que ela faz é bem simples, toda vez que o input é modificado (quando o usuário digita alguma coisa por exemplo) a propriedade dispara um evento indicando que o componente foi atualizado.

Nós então, vamos aproveitar esse evento para atualizar o valor atual do nosso state. Passando para o nosso método setUserInput() o valor e.target.value que é o último valor que usuário digitou.

Repare que estou utilizando arrow function para receber o valor do evento.

Manipulando os valores do formulário

Para receber os valores do usuário, vamos criar uma função chamada handleSubmit, ela é acionada assim que o usuário pressiona enter para escreve uma nova tarefa.

Na primeira linha temos que fazer e.preventDefault(), e é o evento que o formulário emite após ser submetido. E o comportamento padrão de uma formulário é recarregar a página, o que não é interessante para nós.
E se caso o valor for uma string vazia "" o código não faz nada. Pois uma string vazia é falsy.

Repare que nós estamos passando um objeto com duas propriedades (que segue o padrão definido no App.js), para o método, addTodo({ complete: false, task: userInput }).

E por fim, na última linha do método, eu passo uma string vazia para o state, para limpar o valor do input, como expliquei lá em cima.

const handleSubmit = e => {
    e.preventDefault();
    if (!userInput) return;
    addTodo({ complete: false, task: userInput, });
    setUserInput("");
};

O código completo do componente TodoForm do nosso Todo App, ficou assim até agora:

//TodoForm.js
import React, { useState } from 'react';

function TodoForm({ addTodo }) {
    const [userInput, setUserInput] = useState("");

    const handleSubmit = e => {
        e.preventDefault();
        if (!userInput) return;
        addTodo({ complete: false, task: userInput, });
        setUserInput("");
    };

    return (
        <form onSubmit={handleSubmit} className="todo-form">
            <input
                placeholder="New Task"
                type="text"
                className="input"
                value={userInput}
                onChange={e => setUserInput(e.target.value)}
            />
        </form>
    );
};
export default TodoForm;

E esse é o código da class CSS, todo-form que comentei lá trás para o nosso formulário, repare que também estou aplicando CSS no nosso input através dos seletores CSS.

/* 
App.css
*/
.todo-form{
  margin: auto;
  background: rgb(112, 111, 111);
  padding: 5px;
  max-width: 400px;
}

.todo-form input {
  width: 100%;
  padding: 5px;
  box-sizing: border-box;
  font-size: 18px;
}

Importando o formulário

Certo, agora precisamos importar esse componente no App.js, assim como fizemos como o TodoList.

A ideia é que o App.js sirva como intermediador entre o nosso formulário(TodoForm) e a lista de exibição(TodoList).

Para ficar mais claro o que vamos fazer, desenhei esse esquema da estrutura do projeto pra facilitar o entendimento.

Recebendo valores do formulário no componente principal

Utilizando o parâmetro addTodo nós criamos a conexão entre os dois componentes TodoForm e App, assim que o usuário pressiona Enter no formulário, nós recebemos os valores no nosso App.js.

O parâmetro addTodo, na verdade representa uma função, que avalia o dado recebido do componente TodoForm e inclui na lista existente de tarefas.

O método trim() é apenas remover possivéis espaços em brancos antes e depois da uma String.

(todo) => {
  if (todo.task.trim().length > 0) {
    setTodos([...todos, todo]);
  }
}

E para aqueles que não são familiarizados com o operador spread ... (os três pontos). Ele está “expandindo” o objeto que recebemos do TodoForm, dentro da nossa lista de tarefas. Para ficar mais claro, é isso que está acontecendo.

const todo = [{complete: false, task: "New task"}]
const todos = [...todo,{complete: false, task: "Read about MongoDb"}]; 
console.log(todos);
/*[{complete: false, task: "New task"},{complete: false, task: "Read about MongoDb"}]*/

Estou apenas pulando essas etapas intermediárias e inserindo diretamente na lista todos usando o método setTodos do nosso estado.

Essa função nós vamos passar para o componente TodoForm através do parâmetro addTodo, dessa maneira:

<TodoForm addTodo={(todo) => {
  if (todo.task.trim().length > 0) {
    setTodos([...todos, todo]);
  }
}} />

O código completo do componente App do nosso Todo App, ficou assim até agora:

import React, { useState } from 'react';
import './App.css';
import TodoList from './components/TodoList';
import TodoForm from './components/TodoForm';

function App() {
  const [todos, setTodos] = useState([
    { complete: false, task: "Read about MongoDb" },
    { complete: false, task: "Create a React ToDo App" },
    { complete: false, task: "Find my key" }
  ]);
  return (
    <div className="App">
      <TodoForm addTodo={(todo) => {
        if (todo.task.trim().length > 0) {
          setTodos([...todos, todo]);
        }
      }} />
      <TodoList todos={todos} ></TodoList>
    </div>
  );
}

export default App;

Nosso App React vai estar funcionando assim até agora:

Passo 4 – Atualizando a lista

Certo, agora vamos voltar a trabalhar no nosso componente TodoList. O que precisamos agora é uma função que marque as tarefas já concluídas. A idéia é fazer algo assim, quando clicarmos na tarefa, ela é riscada, bem simples.

O que nós precisamos, é uma maneira de identificar o item que está sendo clicado e aplicar uma classe CSS que contém o efeito que nós queremos.

Para fazer isso, nós vamos criar uma função chamada markComplete.

const markComplete = (id) => {
    const updatedList = todos.map((item, index) => {
        if (id !== index) return item;
        return { ...item, complete: !(item.complete) };
    });
    uodateTodos(updatedList);
}

Essa função é bem simples, ela recebe um parâmetro chamado id que vai ser o index referente a posição daquele item no array.

O que a função vai fazer é iterar sobre a lista de itens, utilizando mais uma vez o Array.map(), comparando o index e o parâmetro id que a função recebe para poder atualizar a propriedade complete do objeto que coincide os dois valores.

Assim que o objeto é encontrado, eu apenas troco o valor original pelo inverso dele mesmo. Essa é uma outra grande utilidade do Spread Operator, você pode usar ele para atualizar os valores de um objeto, perceba como está sendo feito na nossa função com esse exemplo:

const task = {complete: false, b: "Your task"};
const updatedTask = {...task, complete: true};
console.log(updatedTask);
// { complete: true, b: "Your task" }

Um problema é que React não reconhece essa “mudança interna” de valores dos atributos, se você apenas alterar um atributo, de um objeto contido no Array, isso não faz React renderizar o componente.

Apenas se você remover, incluir ou alterar um elemento do array, React vai renderizar novamente o componente.

Por isso, estamos utilizando Array.map(), porque ele cria um novo array. E com isso React é capaz de renderizar a nossa lista.

E você se lembra do nosso segundo parâmetro updateTodos que passamos para o TodoList, logo no começo:

function TodoList({ todos, updateTodos }) {
...
}

Se você voltar lá na imagem onde tem o esquemático do projeto, você vai ver que esse método, updateTodos, é responsável por levar os dados do componente TodoList para o componente App.

Então vamos voltar lá no nosso App.js e alterar a linha onde o TodoList é chamado para incluir esse parâmetro.

<TodoList todos={todos} updateTodos={(list) => { setTodos(list) }}></TodoList>

Então assim que o método Array.map() termina de criar o novo array, já com os valor do item atualizado, eu uso o método updateTodos para enviar a lista atualizada para o nosso componente principal.

E com o método setTodos eu atualizo o nosso state com uma nova lista de items que formam marcados como concluídos/não concluídos.

Riscando uma tarefa concluída com CSS

Certo, o que precisamos agora é usar um método para reconhecer o click em algum dos itens da lista. O método onClick vai nos servir bem. Ele vai executar a função markComplete().

onClick={() => markComplete(index)}>

Esse parâmetro index vem do Array.map() que estamos utilizando para iterar e exibir os itens da lista para o usuário.

E por fim, precisamos declarar uma condição na nossa propriedade className, se caso a tarefa for marcada como feita ou complete:true vamos aplicar a classe taskDone, caso contrário a classe é removida.

className={`todo ${todo.complete ? "taskDone" : ""}`}

O código completo fica assim:

//TodoList
import React from 'react';

function TodoList({ todos, updateTodos }) {

    const markComplete = (id) => {
        const updatedList = todos.map((item, index) => {
            if (id !== index) return item;
            return { ...item, complete: !(item.complete) };
        });
        updateTodos(updatedList);
    }
    return (
        <div className="todo-list">
            {todos.map((todo, index) => (
                <div
                    key={index}
                    className={`todo ${todo.complete ? "taskDone" : ""}`}
                    onClick={() => markComplete(index)}>
                    Item {index + 1}: {todo.task}
                </div>
            ))}
        </div>
    );
};

export default TodoList;

A classe CSS que nós estamos aplicando é a taskDone, então no nosso arquivo App.css você deve incluir:

.taskDone{
  text-decoration: line-through;
}

Nossa Todo List vai estar funcionando assim até agora:

Passo 5 – Removendo items da lista

Pensando que podemos sem querer adicionar uma tarefa errada ou que temos uma tarefa na lista que não precisamos mais fazer, ou porque ela já foi concluída e não precisa ficar mais lá, vamos criar uma função para remover esses items indesejados.

Dentro do nosso componente TodoList, vamos incluir um botão em cada item para executar a ação de excluir e também, criar a função para remover o item.

Vou adicionar uma função chamada removeTask() que vai receber o index da tarefa na lista, e utilizando o método filter, vou criar uma nova lista sem o elemento que acabamos de remover para atualizar o state com o método updateTodos() que estamos recebendo do App.js. Um processo parecido com aquele que fizemos na função markComplete().

const removeTask = (index) => {
    const updatedList = todos.filter((task, taskIndex) => {
        return taskIndex !== index;
    });
    updateTodos(updatedList);
}

E abaixo de cada item, nós vamos incluir o nosso botão. Nosso botão tem apenas duas propriedades, className para adicionar uma classe CSS e a função onClick que vai disparar o nosso método removeTask().

Perceba que já passo o index para dentro do método.

<div>
    <button className="button" onClick={() => removeTask(index)}>Delete</button>
</div>

O código completo do nosso componente TodoList vai ficar assim:

//TodoList
import React from 'react';

function TodoList({ todos, updateTodos }) {

    const removeTask = (index) => {
        const updatedList = todos.filter((task, taskIndex) => {
            return taskIndex !== index;
        });
        updateTodos(updatedList);
    }

    const markComplete = (id) => {
        return todos.map((item, index) => {
            if (id !== index) return item;
            return { ...item, complete: !(item.complete) };
        });
    }
    return (

        <div className="todo-list">
            {todos.map((todo, index) => (
                <div key={index}>
                    <div
                        className={`todo ${todo.complete ? "taskDone" : ""}`}
                        onClick={() => setTodos(markComplete(index))}>
                        Item {index + 1}: {todo.task}
                    </div>
                    <div><button className="button" onClick={() => removeTask(index)}>Delete</button>  </div>

                </div>

            ))}
        </div>
    );
};

export default TodoList;

Vamos adicionar o estilo do nosso botão ao nosso arquivo CSS:

.button{
  background-color: #f44336; /* red */
  border: none;
  color: white;
  padding: 10px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  width: 100%;
  margin-bottom: 10px;
}

E é isso, nosso app está pronto Todo app está pronto!

Vamos testar:

Conclusão

Esse aplicativo usa React Hooks, que foi apresentado na versão 16.8. É uma funcionalidade relativamente nova, mas bastante poderosa e eficiente. Você consegue trabalhar da mesma forma com Classes, mas Hooks tornam o código bem mais limpo e simples de entender.

Criar um app que implementas as funções de básica de CRUD é uma ótima maneira de entender os life cycles do React.

Espero que tenha sido útil.

Até a próxima.

]]>
https://blog.debugeverything.com/pt/do-zero-construindo-um-app-com-react-js/feed/ 2
[Do Zero] Como construir uma página de login usando Python – parte 3 https://blog.debugeverything.com/pt/do-zero-como-construir-uma-pagina-de-login-parte-3/ https://blog.debugeverything.com/pt/do-zero-como-construir-uma-pagina-de-login-parte-3/#comments Thu, 09 Apr 2020 07:00:17 +0000 https://debugeverything.com/?p=707 Mas uma etapa do nosso projeto, depois de criar toda a estrutura da página com CSS e HTML na parte 1 e adicionar Javascript para enviar os a dados para o servidor na parte 2. Chegou a hora de falar do lado do servidor. E dessa vez a nossa página de login está usando Python.

Na parte 2, criei um exemplo de um arquivo em PHP para representar o nosso servidor. Mas devido a aclamação popular, vamo fazer a mudança agora para Python.

Para quem nunca teve contato com a linguagem talvez não seja a maneira certa de começar. Nesse artigo não vou mostrar como instalar o Python ou como começar na linguagem, apenas vou citar algumas das ferramentas e procedimentos.

Ambientes virtuais com Python

Grande maioria do projetos, se não todos, tem dependências, seja em uma biblioteca, framework ou API.

Pra isso cada linguagem de programação tem as suas próprias ferramentas de gestão de dependência.

Como Python resolve esse problema? Criando ambientes virtuais.

Os ambientes virtuais são grupos independentes de bibliotecas Python. Os pacotes instalados para um projeto não afetarão outros projetos ou os pacotes do sistema operacional.

Python 3 vem em conjunto com o módulo venv para criar ambientes virtuais. Mas se estiver usando Python 2, é bom você dar uma olhada de como instalar o virtualenv primeiro.

Você pode verificar a versão usando o comando python --version no terminal.

Flask

Flask é um micro web framework escrito em Python. É classificado como um microframework porque não requer ferramentas ou bibliotecas específicas.

E o infeliz é muito simples de usar!

Se está tudo certo com o Python no seu computador, você só precisa usar o comando pip install flask para instalar a última versão do Flask.

Esse código abaixo você encontra em praticamente qualquer lugar quando você busca por Flask no Google. E ele demonstra o quanto é simples criar e rodar uma aplicação.

Abre o seu editor de texto e cola esse código e salva o arquivo como main.py.

from flask import Flask							
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"
if __name__ == "__main__":
    app.run()

Feito isso, abre uma janela do seu terminal na pasta onde você salvou o seu arquivo e digita o comando python main.py e aperta enter.

Sim é só isso, e você já tem uma aplicação rodando na porta localhost:5000, que é a porta padrão que o Flask usa.

Se você abrir o browser nessa rota você vai ver um resultado possivelmente parecido com esse:

Flask Debug Mode

Pra evitar aquela chatice de ficar reiniciando o servidor toda vez que você faz uma alteração no arquivo da página de login, usando Python, você pode fazer o seguinte:

  • Mude a linha app.run() para app.run(debug=True)
  • Pare e reinicie o servidor

Pronto!

Agora toda vez que você alterar e salvar o servidor é reiniciado automaticamente.

Nova estrutura da página de login usando Python

Pra usar o nosso microframework Flask na nossa página de login usando python nós vamos precisar fazer algumas pequenas mudanças no nosso HTML e na nossa estrutura de pastas.

Arquivos CSS e Javascript

Os arquivos CSS e Javascript que criamos na primeira parte ainda permanecem o mesmo ????. Mas a maneira de incluir eles muda um pouco.

Agora, nós vamos incluir os arquivos usando esse template:

{{ url_for('static', filename='css/style.css') }}
{{ url_for('static', filename='js/script.js') }}

Agora o nosso código vai ficar assim:

<!-- Including CSS file-->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">

<!-- Including Javascript file-->
<script src="{{ url_for('static', filename='js/script.js') }}"></script>

Um pouco a mais de código, mas não é o fim do mundo também. A função url_for() gera pra gente uma URL para a rota final dado um parâmetro.

Estrutura de pastas

O Flask pede (gentilmente) para que nós criemos duas pastas uma chamada static onde vamos colocar os nossos arquivos CSS e Javascript. E uma segunda pasta chamada templates, onde vão os nossos arquivos HTML.

Por sinal, static naquele código ali em cima, referencia essa pasta que estamos acabando de criar.

Para separar ainda melhor, dentro da pasta static criei uma pasta para cada tipo de arquivo, a estrutura final das pastas ficou assim:

/static
---css
---javascript
/templates
---login.html
main.py

Python em ação

Já fizemos todos os ajustes necessários para partir pro Python. Eu vou usar aquele código que vimos lá em cima no primeiro exemplo, e vamos dar uma incrementada.

from flask import Flask, render_template, request						
app = Flask(__name__)

@app.route("/login")
def screen():
    return render_template('login.html')

if __name__ == "__main__":
    app.run(debug=True)

O que foi que mudou?

Bom, na primeira linha , além do Flask, estou importando também o Objeto request, que vem por padrão com o Flask, e a função render_template.

request é o Objeto utilizado para fazer e também receber requisições HTTP. Olho nesse objeto que vamos usar ele mais pra frente.

render_template para renderizar nosso HTML, tive que importar essa função que vem com a estrutura do Flask chamada render_template().

A função render_template() invoca o motor de templates do Jinja2 que vem com o framework Flask (lembra o que eu falei das dependências).

Também alterei o nome da rota principal para "/login" e o nome da função para screen(). E ao invés de retornar apenas uma String estou retornando o nosso arquivo HTML, login.html.

Fazendo Conexão

Se tudo correu bem até aqui, quando você roda o seu arquivo Python main.py e acessa a rota localhost:5000/login você deve ver a sua página de login só que usando python dessa vez.

Certo, chegou a hora então de enviar os dados que recebemos no formulário para o nosso servidor recém criado.

Lembra do nosso arquivo Javascript, o mesmo da parte 2. Precisamos fazer uma ligeira alteração. É eu sei que disse que não iriamos mexer nesse arquivo. Mas na parte 2 usamos PHP, então precisamos remover aquela url e passar a nova rota.

Precisamos mudar a penas uma linha.
antes:
xml.open("POST", "login.php");
depois:
xml.open("POST", "/login");

Para o código ficar mais legível, eu criei uma segunda rota, com o mesmo nome, mas que aceita a requisição POST.
Só colocar esse segundo parâmetro methods = ['POST'] na função @app.route().

@app.route('/login',methods = ['POST'])
def login():
   if request.method == 'POST':
      email = request.form['email']
      password = request.form['password']
      return "Email: " + email + " <br> " + "Password: " + password

Nessa rota estou usando o nosso Objeto request. Com ele eu consigo acessar os dados que estão vindo da requisição do lado do cliente.
Para acessar os dados, assim como no PHP vamos utilizar o nome do campo que definimos no nosso formulário na parte 1.

Nosso arquivo final main.py vai ficar assim:

from flask import Flask, render_template, request						
app = Flask(__name__)

@app.route("/login")
def screen():
    return render_template('login.html')

@app.route('/login',methods = ['POST'])
def login():
   if request.method == 'POST':
      email = request.form['email']
      password = request.form['password']
      return "Email: " + email + " <br> " + "Password: " + password


if __name__ == "__main__":
    app.run(debug=True)

Testando a conexão

Chegou a hora de testar. O nosso arquivo main.py está apenas retornando os dados que ele recebe, assim como fiz no exemplo da parte 2.

O resultado final deve ser também muito parecido. Só que agora usando Python.

Então é isso ai, o fim de mais uma parte da série. E agora é mais do que oficial. Python também vai ser utilizado nos nosso tutoriais daqui pra frente.

Se você gostou dessa novidade, e quer ser notificado quando tiver conteúdo novo, basta se inscrever para receber as notificações no formulário logo abaixo.

Te vejo na próxima.

]]>
https://blog.debugeverything.com/pt/do-zero-como-construir-uma-pagina-de-login-parte-3/feed/ 3
[Do Zero] Como criar uma página de login – parte 2 https://blog.debugeverything.com/pt/do-zero-como-criar-uma-pagina-de-login-parte-2/ https://blog.debugeverything.com/pt/do-zero-como-criar-uma-pagina-de-login-parte-2/#comments Fri, 03 Apr 2020 04:00:00 +0000 https://debugeverything.com/?p=665 Na primeira parte de como criar uma página de login do zero, nós definimos todos os elementos e criamos toda a estrutura da página.

Se você não viu a primeira parte, volta lá e da uma conferida pra você não ficar perdido aqui.

Se quiser acompanhar e ser notificado, clique aqui e se inscreva para receber as notificações.

Próximos passos

Beleza, já temos nossa página de login, bem simples até então, apenas 5 elementos. E esse foi o resultado final aqui.

Bom o que está faltando na nossa página então? Ação!

Ela não tem nenhuma função até o momento, é uma página estática. Nessa segunda parte vamos começar a trabalhar com Javascript.

A idéia aqui é criar uma função chamada:

  • userLogin() – Essa função vai receber e enviar o dados do formulário para o servidor.

Antes disso precisamos fazer pequenos mudanças no código.

Ajustando o formulário

Para receber os dados da nossa página precisamos incluir mais alguns coisa no nosso formulário HTML.

A primeira delas é definir um id para o nosso formulário, assim o javascript consegue encontrar facilmente o formulário. Podemos fazer isso de forma bem simples, dentro da nossa tag <form> nós adicionamos id="login-form".

Segundo precisamos colocar uma ação de clique no botão de login. Dentro da tag <button> vamos incluir um novo atributo para especificar essa ação.

O atributo com nome da função (a ação que queremos executar) já atribuído fica assim, onclick="userLogin()", bem simples também.
O código do nosso formulário vai ficar desse jeito após essa pequenas inserções.

<div class="row align-items-center h-100 ">
   <div class="col-8 col-md-3 col-xs-8 mx-auto l-form">
     <form id="login-form">
       <img class="row mx-auto" src="https://i.imgur.com/RhJpe7c.png" width="150">
       <div class="form-group ">
         <input type="text" name="email" placeholder="Email" class="form-control i-form">
       </div>
       <div class="form-group">
         <input type="password" name="password" placeholder="Password" class="form-control i-form">
       </div>
       <div class="form-group">
         <button type="button" onclick="userLogin()" class="btn btn-dark btn-md btn-block">Login</button>
       </div>
     </form>
   </div>
</div>

Capturando dados do formulário

Essa é a função que vai receber os dados do usuário assim que ele clicar no botão de login.

Tem diversas formas de fazer isso, aqui resolvi usar Javascript puro para simplificar. O que estou fazendo é buscando nosso formulário na nossa página de login pelo id que definimos ali em cima, utilizando a função document.getElementById() do javascript para isso.

let userLogin = function () {
    let form = document.getElementById("login-form");
    let email = form.elements.namedItem("email").value;
    let password = form.elements.namedItem("password").value;
};

Com nosso formulário nas mãos, precisamos agora buscar os nossos campos de email e senha. O javascript também já oferece uma forma rápida de fazer isso, buscando o campo pelo atributo name="", que também ja foi definido nas etapas anteriores.

Enviando os dados para o servidor com XMLHttpRequest

Já temos toda a informação que precisamos, agora é enviar para o nosso servidor através de uma requisição HTTP.

Para isso nós vamos usar a Api XMLHttpRequest, que apesar do nome, nós podemos usar para obter qualquer tipo de dados, não só XML.

Esse é o código que vou utilizar para enviar os dados para o servidor. Não se preocupa, vou passar a limpo, e explicar o que esta acontecendo aqui.

let userLogin = function () {
    let form = document.getElementById("login-form");
    let email = form.elements.namedItem("email").value;
    let password = form.elements.namedItem("password").value;
    let credentials = "email=" + email + "&password=" + password;
    const xml = new XMLHttpRequest();

    xml.onreadystatechange = function () {
        if (xml.status == 200) {
            console.log(xml.response);
        }
    };

    xml.open("POST", "login.php");
    xml.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xml.send(credentials);
};

XMLHttpRequest() é o construtor da API. Ele deve ser chamado antes que qualquer outro método da API.

xml.onreadystatechange essa propriedade contém o gerenciador de eventos a ser chamado quando o evento readystatechange for disparado, ou seja, sempre que a propriedade readyState do XMLHttpRequest mudar.

xml.status é a propriedade que retorna o código HTTP da resposta da chamada.

xml.response essa propriedade retorna o conteúdo do corpo da resposta vinda do servidor em diferentes formatos, dependendo do responseType.

xml.open() o método inicializa uma request, ou reinicia uma request já existente.

xml.setRequestHeader() define o valor do cabeçalho de uma requisição HTTP.

xml.send() esse é o método que envia a request para o servidor.

Detalhes da função

Na função xml.open(), defini dois parâmetros, o primeiro define o tipo da requisição, nesse caso, como queremos enviar dados para o servidor, estou usando o método POST. O segundo parâmetro representa a url a qual nós vamos enviar a requisição.

Também inclui dois parâmetros na função, xml.setRequestHeader(). O primeiro parâmetro cria um cabeçalho para a request que define o tipo de conteúdo enviado na requisição e o segundo identifica que tipo de conteúdo é esse.

1, 2, 3… Testando

Para testar a função, criei um arquivo PHP para receber esse dados dentro do localhost. Como você pode ver no código abaixo, bem simples, apenas para testes.

<?php
echo 'Resposta do servidor:';
echo '<br>';
echo 'Email: ' . ($_POST["email"]);
echo '<br>';
echo 'Password: ' . ($_POST["password"]);

Assim que o usuário clica no botão de login, o servidor responde com os dados que foram enviados.

Bom por enquanto é isso, eu convido você a fazer parte do projeto colaborativo, onde você pode colocar as suas idéias e praticar o o que você aprendeu. Basta clicar aqui para contribuir no projeto.

Mas o projeto ainda não terminou, próximo passo agora é conectar com o banco de dados. E podemos também fazer uma mudança para o JAVA.

Deixe nos comentários o que você quer ver no próximo conteúdo da série.
E não deixe de se inscrever, assine a newsletter aqui a baixo, que você vai ser informado assim que sair conteúdo novo.

]]>
https://blog.debugeverything.com/pt/do-zero-como-criar-uma-pagina-de-login-parte-2/feed/ 1
[Do zero] Como criar uma página de login – parte 1 https://blog.debugeverything.com/pt/do-zero-como-criar-uma-pagina-de-login/ https://blog.debugeverything.com/pt/do-zero-como-criar-uma-pagina-de-login/#comments Thu, 26 Mar 2020 19:00:00 +0000 https://debugeverything.com/?p=593 Em uma nova série de posts, “Do Zero”, vou mostrar como construir aplicações simples e complexas mostrando todo o código e ferramentas utilizadas para o desenvolvimento. No primeiro post da série vou mostrar como criar uma página de login, utilizando apenas o básico do HTML e CSS e Javascript.

Essa será a primeira parte, onde vamos definir o layout e a estrutura da página, vamos deixar o Javascript para segunda parte.

Se quiser acompanhar e ser notificado, clique aqui e se inscreva para receber as notificações.

Sem mais demora, vamos colocar a mão na massa.

Estrutura HTML básica

Partindo do básico, a estrutura de qualquer página HTML será bastante similar a essa.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login Page</title>
</head>

  <body>

  </body>

</html>

Algumas informações sobre essa estrutura.

Uma tag do tipo <meta> fornece metadados sobre o documento HTML.

<meta charset="UTF-8"> especifica a codificação de caracteres para o documento HTML.

O atributo viewport dá ao navegador instruções sobre como controlar as dimensões e escalas da página.

width=device-width define que a largura da página deve seguir a largura da tela do dispositivo (que irá variar dependendo do dispositivo).

initial-scale=1.0 define o nível de zoom inicial quando a página é carregada pela primeira vez pelo navegador.

Estrutura da Página de Login

Certo, definida a estrutura básica, vamos partir para como começar a criar nossa página de login, agora é hora de começar a colocar os elementos na tela.

São apenas 5 elementos, nada muito complexo.

  • Logo do página
  • Campo de formulário para email
  • Campo de formulário para senha
  • Botão de login
  • Imagem para o background

Vamos trabalhar primeiramente com o nosso formulário. Pra ajudar na estrutura e na aparência da página, vou utilizar o Bootstrap 4.4, que é bem simples de utilizar e tem uma documentação excelente. Para incluir o arquivo CSS do bootstrap na página, não tem mistério, basta copiar e colar o código com o link logo abaixo da tag <meta>.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
    <title>Login Page</title>
</head>

  <body>

  </body>

</html>

Formulário de Login

Eu quero construir o formulário centralizado na página, e independente do tamanho da tela, quero que ele siga as mesmas proporções.

O Bootstrap tem um monte de ferramentas e classes úteis para ajustar a na responsividade. Bom sem perder tempo, esse aqui é o código do formulário.

<div class="row align-items-center h-100 ">
    <div class="col-8 col-md-3 col-xs-8 mx-auto l-form">
        <form class="form" method="post">
            <img class="row mx-auto" src="https://i.imgur.com/RhJpe7c.png" width="150">
            <div class="form-group ">
                <input type="text" placeholder="Email" class="form-control i-form">
            </div>
            <div class="form-group">
                <input type="password" placeholder="Password" class="form-control i-form">
            </div>
            <div class="form-group">
                <button type="submit" class="btn btn-dark btn-md btn-block">Login</button>
            </div>
        </form>
    </div>
</div>

Nesse código já coloquei 4 dos elementos que tínhamos definido anteriormente. A logo da página está ali, acredite, só que ela é branca, então só vai aparecer quando mudarmos o background.

O que estou criando com esse código é uma estrutura, utilizando o Grid System do Bootstrap, para alinhar o nosso formulário horizontalmente e verticalmente no centro da tela.

Também utilizei as classes: col-8 col-md-3 col-xs-8 para manter as proporções em diferentes tipos de tela.

Provavelmente existem diversas outras maneiras e classes que eu poderia utilizar para criar o mesmo formulário com as mesmas características. Mas esse código tem a intenção de ser bem simples, não precisamos de soluções extremamente elaboradas, ainda.

Sugestões são sempre bem vindas, deixe seu comentário.

A sua página deve estar parecida com isso no momento.

Melhorando a aparência

Para melhorar aparência geral da página, criei um arquivo CSS bem simples. Que especifica as classes l-form e i-form, e alguns outros atributos para as tags <body> e <html>.

body,html{
  height: 100%; 
  overflow: hidden;
  background-image: url(https://i.imgur.com/X97iVv1.jpg);
  background-size: cover;
}

.l-form{
  background-color:rgba(39, 41, 45, 0.5);
  border-radius:12px;
  padding: 12px;
}

.i-form{
  border-radius:12px;
  padding: 12px;
}

Para as tags <body> e <html> defini 5 atributos

heigh:100% assim conseguimos aproveitar toda a área util da tela.

overflow: hidden remove as barras de rolagem da página.

background-image e background-size define uma imagem para o fundo da sua página e o comportamento dessa imagem, respectivamente.

Finalizando

Esse é o nosso arquivo HTML final, após juntarmos todas as peças:

<!doctype html>
<html lang="en">

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
    <link rel="stylesheet" href="../css/login-style.css">
    <title>Login Page</title>
</head>

<body>
  <div class="row align-items-center h-100 ">
      <div class="col-8 col-md-3 col-xs-8 mx-auto l-form">
          <form>
              <img class="row mx-auto" src="https://i.imgur.com/RhJpe7c.png" width="150">
              <div class="form-group">
                  <input type="text" name="email" placeholder="Email" class="form-control i-form">
              </div>
              <div class="form-group">
                  <input type="password" name="password" placeholder="Password" class="form-control i-form">
              </div>
              <div class="form-group">
                  <button type="button" class="btn btn-dark btn-md btn-block">Login</button>
              </div>
          </form>
      </div>
  </div>
</body>

</html>

Se você seguiu tudo até aqui como foi ensinado a sua página de login deve se parecer com isso:

Esse foi um tutorial bem fácil, mas uma página de login é como a porta de entrada, um cartão de visitas e acredito que a primeira impressão é muito importante. Espero que tenha gostado. Até a parte 2.

]]>
https://blog.debugeverything.com/pt/do-zero-como-criar-uma-pagina-de-login/feed/ 6