Construindo uma aplicação simples usando Nuxt.js/Vue.js e Django — Parte I

Eduardo da Silva
9 min readMay 19, 2020

--

Photo by Fabian Grohs on Unsplash

Django é o framework de desenvolvimento web Python mais popular. Recentemente, ele tem sido amplamente utilizado para desenvolver plataformas de backend, fornecendo acesso a dados via REST, GraphQL ou tecnologias similares. Embora muitos artigos tenham sido escrito com o objetivo de mostrar a integração do Django como backend com frameworks de frontend Javascript, como o React, Angular, VueJS, eu não encontrei um artigo completo que apresente a integração do Django com o NuxtJS, incluindo o gerenciamento de requisições autenticadas.

Eu gostaria de frisar que muitas outras estratégias poderiam ser empregadas para desenvolver tal integração, mas eu apresento a que se parece, ao meu ver, uma das mais adequadas. Eu implemento o backend usando Django 3 com Django REST framework para construir as APIs. O frontend é implementado com NuxtJS consumindo e renderizando as respostas JSON oriundas da API Django REST.

O problema

Nesta nossa primeira parte, nós criamos um backend usando Django com o Django REST Framework( DRF). Tal backend fornece apenas o módulo de autenticação, usando o pacote simple JWT. O frontend, construído usando NuxtJS, consome tal API, sendo que os usuários são capazes the acessar a API usando seus respectivos ‘usuário’ e ‘senha’.

Photo by Faisal M on Unsplash

A implementação do Backend

Eu sugiro usar o Poetry para gerenciar os pacotes Python na solução backend. Uma forma de instalar o poetry é usando o pip, embora outras formas podem ser encontradas na página do projeto.

Inicialmente, vamos instalar o poetry:

$ pip install --user poetry
$ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc

Criando o ambiente virtual

No restante do artigo, eu considero que você esteja desenvolvendo a solução em um diretório chamado django-nuxt-project. Qualquer outro nome de diretório e caminho pode ser usado. No diretório do projeto,é necessário criar o arquivo de projeto do poetry.

$ poetry init

O comando ‘init’ criará o arquivo pyproject.toml, que contém as dependências do projeto. A caixa a seguir apresenta uma lista-exemplo de respostas:

Package name: projeto-django-nuxt
Version: 1.0.0
Description: Um projeto simples de integração Django-Nuxt .
Author: Eduardo da Silva
License:
Compatible Python versions [^3.6]:
Would you like to define your main dependencies interactively: no
Would you like to define your dev dependencies (require-dev) interactively: no
Do you confirm generation: yes

Após criar o arquivo pyproject.toml, é necessário criar o ambiente virtual para esse projeto.

$ poetry install

O comando ‘install’ cria o novo ambiente no diretório ~/.cache/pypoetry/virtualenvs. Em seguida, você pode ativar o ambiente virtual executando o seguinte comando no diretório do projeto:

$ poetry shell

Instalando o Django

Agora, é necessário adicionar o Django ao projeto Poetry.

É importante enfatizar que os próximos comandos são executados dentro do ambiente do poetry, criado anteriormente.

$ poetry add django

O comando ‘add’, como se supõe, adiciona a última versão do Django ao ambiente poetry corrente. Agora, vamos criar nosso projeto Django de backend, com o seguinte comando:

$ django-admin startproject backend .

Observe que o último ponto (.) do comando apresentado garante que o Django não crie um novo diretório para o novo projeto. Então, o arquivo manage.py estará localizado no diretório raiz do projeto.

Em nosso ambiente, usaremos o SQLite como gerenciador de banco de dados. Assim, nenhum modificação adicional será necessária, por enquanto, no arquivosettings.py. Em seguida, nós devemos gerar o arquivo de banco de dados e criar um novo superusuário para gerenciar o projeto backend.

$ ./manage.py migrate
$ ./manage.py createsuperuser
Username (leave blank to use 'seu usuário'): admin
Email address: admin@exemplo.com
Password: ********
Password (again): ********

Para testar nossa nova instalação, nós podemos executar o projeto Django atual:

$ ./manage.py runserver

Assim, nós podemos acessar via um navegador a URL http://localhost:8000. A seguinte página padrão do Django será apresentada.

Django’s default page
Página padrão do Django

Finalmente, nós inicializaremos uma aplicação em nosso projeto. Consideraremos apenas uma aplicação, chamado ‘core’, que gerenciará os models, serializers, e views. Os comandos a seguir criam a nossa aplicação:

$ mkdir backend/core
$ ./manage.py startapp core backend/core

Instalação dos pacotes necessários

Em geral, um sistema crescerá passo-a-passo, e novos pacotes serão adicionados ao projeto sempre que necessário. Em nosso exemplo, decidimos adicionar todos os pacotes necessários no início, a fim de evitar grandes alterações nos arquivos de configurações.

Em nosso exemplo, os seguintes pacotes serão utilizados no ambiente de backend:

+ djangorestframework
+ djangorestframework-simplejwt
+ django-environ
+ django-cors-headers

Quando eu criei esse tutorial, o pacote djangorestframework-simplejwt requer o Python ≥ 3.6 e ≤ 3.9. Ao criar o arquivo pyproject.toml (o arquivo de projeto do Poetry) você será questionado pela versão do Python. Se você escolher a versão padrão, a versão do Python será configurada como ^3.8.

Dessa forma, é necessário alterar o arquivo pyproject.toml, como mostra o código a seguir, e alterar essa informação (linha 8):

pyproject.toml — Arquivo de projeto Poetry (versão inicial)

Por fim, para adicionar tais pacotes, nós executamos os seguintes comandos no diretório do projeto:

$ poetry add djangorestframework
$ poetry add djangorestframework-simplejwt
$ poetry add django-cors-headers

O arquivo settings.py

Agora, alteraremos o arquivo settings.py, que contém as configurações gerais do projeto Django. Aqui, colocamos a versão final desse arquivo. Também, foram adicionadas as novas informações, mantendo o conteúdo padrão do arquivo, excluindo os comentários.

As principais alterações são listadas abaixo:

  • linhas 18–19: novos apps instalados, respectivamente, o rest_framework e o core.
  • linha 23: adicionar o middleware corsheaders, que permite que os recursos sejam acessados em outros hospedeiros ou domínios.
  • linhas 60–65: configurações relacionadas ao simplejwt, o JSON Web Token authentication plugin para o Django REST Framework.
  • linha 67: também relacionada com o middleware corsheader.
  • linhas 78–83: correspondente às configurações do rest_framework. Também incluem o modelo de permissões considerado no projeto, que é o DjangoModelPermissions (linha 82).

A autenticação

Agora, nós configuramos o projeto backend para gerenciar as autenticações. Como nós já temos o pacote restframework_simplejwt, nós precisamos apenas adicionar o caminho das URLs no projeto.

Para isso, editamos o arquivo backend/urls.py como segue:

Observe que as linhas 7–8 correspondem às rotas de autenticação. A URL api/token requer os campos username e password, e é responsável por autenticar os usuários. Se o usuário e senha estão corretos, o usuário será autenticado e um token será enviado via JSON. Porém, se o usuário ou a senha estiverem errados, uma mensagem de erro será retornada.

A URL api/refresh_token é responsável por atualizar o token do usuário, quando o atual estiver expirado.

Photo by Caspar Camille Rubin on Unsplash

A implementação do frontend

Para instalar o nuxtJS, o pacote npx é necessário. Se você já tem o npm instalado, apenas execute o seguinte comando:

$ npm install -g npx

Criando o projeto

Para criar um novo projeto Nuxt, use o seguinte comando, considerando que ‘frontend’ é o nome do seu novo projeto:

$ npx create-nuxt-app frontend

As seguintes questões serão perguntadas. Os valores em parênteses são os padrões:

Project name: frontend
Project Description: Uma integração Django-Nuxt - frontend.
Author Name: Eduardo da Silva
Choose programming language: JavaScript
Choose the package manager: Npm
Choose UI framework: Buefy
Choose custom server framework: None
Choose Nuxt.js modules: Axios
Choose linting tools: ESLint, Prettier
Choose test framework: None
Choose rendering mode: Universal (SSR)
Choose development tools: jsconfig.json

Com isso, a versão inicial do projeto estará disponível no diretório frontend/. Para executar, digite:

$ cd frontend
$ npm run dev

A versão frontend estará escutando no endereço http://localhost:3000, como apresentado a seguir:

Nuxt with Buefy default page
Página padrão do Nuxt com Buefy

Alterações iniciais

A primeira coisa a fazer é remover os cartões de exemplo da página inicial e o item ‘Inspire’ do menu lateral. Para remover os cartões da página inicial, edite o arquivo frontend/pages/index.vue:

Conteúdo inicial do arquivo frontend/pages/index.vue

Então, para remover o item ‘Inspire’ do menu lateral, edite o arquivo frontend/layouts/default.vue(alterações após a linha 49):

Removendo itens do menu lateral

Obs: no meu ambiente de desenvolvimento, eu modifiquei o arquivo de configuração do prettier, para considerar linhas com 80 caracteres. Assim, eu precisei alterar o frontend/.prettierc (adicionada a linha 5):

Arquivo de configuração do Prettier

Adicionando autenticação ao frontend

Inicialmente, adicionamos o módulo nuxt-auth ao projeto. Mas, antes disso, é necessário ativar o módulo vuex-store. Como o nosso projeto ainda não tem o vuex-store ativado, é necessário criar um arquivo vazio frontend/store/index.js. Então, instale o módulo nuxt-auth, como segue:

$ npm install @nuxtjs/auth

Também, sugiro usar o pacote toast, para mostrar mensagens de informações ao usuário. O seguinte comando pode ser utilizado:

$ npm install @nuxtjs/toast

Em seguida, nós devemos editar o arquivo frontend/nuxt.config.js, adicionando o seguinte:

...
modules: [
‘nuxt-buefy’,
‘@nuxtjs/axios’,
‘@nuxtjs/auth’,
‘@nuxtjs/toast’
],
auth: {
strategies: {
local: {
endpoints: {
login: {
url: '/api/token/',
method: 'post',
propertyName: 'access',
altProperty: 'refresh'
},
logout: {},
user: false
}
}
},
redirect: {
login: '/login',
},
},
router: {
middleware: ['auth']
},
axios: {
baseURL: 'http://localhost:8000'
},
toast: {
position: 'top-center',
iconPack: 'fontawesome',
duration: 3000,
register: [
{
name: 'defaultSuccess',
message: (payload) =>
!payload.msg ? 'Operação bem sucedida' : payload.msg,
options: {
type: 'success',
icon: 'check'
}
},
{
name: 'defaultError',
message: (payload) =>
!payload.msg ? 'Oops.. Erro inesperado' : payload.msg,
options: {
type: 'error',
icon: 'times'
}
}
]
},
...

A versão final do arquivo nuxt.config.js está apresentada abaixo:

Arquivo fronted/nuxt.config.js

A autenticação é configurada nas linhas 25 e 26–47.

  • Linha 25: corresponde ao módulo nuxtjs-auth.
  • Linhas 26–44: as configurações do módulo auth. Primeiro definimos como ‘local’ a estratégia de autenticação, informando que a página de login estará localizada na rota /login. Observe que a linha 31 é relativa a baseURL do axios (definida na linha 49).
  • Linha 46: garante que todas as páginas acessadas devem estar autenticadas. Se um usuário não está autenticado, ele será redirecionado à página de login (linha 40).
  • Lines 46–48: correspondem às informações básicas do módulo Axios.

Também, as linhas 49–73 são relacionadas ao módulo toast, responsável por mostrar mensagens aos usuários. Configuramos dois tipos de mensagens: defaultSuccess e defaultError.

Agora, devemos criar as páginas de login e logout. Ambas estarão localizadas no diretório frontend/pages.

Primeiramente, a página de login:

Componente frontend/page/login.vue

As linhas 1–14 apresentam o código correspondente ao formulário de login, que contém dois campos, username e password. Ambos os campos são armazenados em um objeto chamado user. Finalmente, os formulário tem um botão Login, cujo evento onclick será direcionado ao método login().

O método login() é apresentado nas linhas lines 24–37, em que o método loginWith() (do pacote nuxtjs-auth) é invocado com as informações do objeto user.

Agora, para finalizar nosso exemplo, a página de logout (frontend/pages/logout.vue).

Componente frontend/pages/logout.vue

Nesse componente Vue, nós definimos apenas o método created que executa o logout usando um método predefinido do pacote nuxt-auth (linha 8). Após o logout, o usuário será direcionado para a página raiz (/).

Para testar o método de logout, nós podemos adicionar um item logout ao menu lateral, que será apresentado quando o usuário estiver autenticado. Para isso, edite o arquivo frontend/layout/default.vue:

Componente frontend/layout/default.vue com itens autenticados.

Quando comparado com a versão anterior do arquivo default.vue, algumas alterações foram realizadas. Inicialmente, criamos duas listas (linhas 54–97), chamadas globalItems e authenticatedItems. Essas listas contém itens que são apresentados no menu lateral. A primeira lista, globalItems, contém os itens apresentados a todos os usuários (autenticados ou não). Por outro lado, a lista authenticatedItems contém apenas os itens apresentados aos usuários autenticados.

A interpolação dessas listas na página é implementada nas linhas 25–38. Observe que o código possui dois laços v-for. O primeiro percorre globalItems, enquanto que o segundo percorre authenticatedItems. Contudo, o segundo laço v-for está dentro de uma tag <span>, que é visível apenas quando a variável loggedIn for verdadeira.

Mas quem controla essa variável loggedIn? Ela é fornecida via o módulo vuex-store. Na linha 50, importamos o método mapState do módulo vuex. Então, nas linhas 70–72, definimos um dado computado, que mapeia a variável loggedIn do módulo de armazenamento ‘auth’ para o dado computado local loggedIn.

Na parte dois, nós implementaremos os models, serializers, e views no Django, e como consumir tais dados usando o NuxtJS.

Bom proveito!

--

--

Eduardo da Silva

Professor at Catarinense Federal Institute (Brazil), PhD on Computer Science.