Use dois identificadores no seu modelo do Django

19/02/2020 - 3 min de leitura

DJANGO OFF-TOPIC

O Django é um framework que é uma verdadeira mãe para os desenvolvedores. Ele facilita muuiittoo nosso trabalho na hora de desenvolver as aplicações web.

Hoje, venho compartilhar uma dica que aprendi com a pessoa mais inteligente que conheço no nosso ramo de tecnologia: Dann Luciano - meu professor, amigo e parceiro.

Nós deveríamos usar dois identificadores nos nossos models.  Um identificador privado e um identificador público.

Explicando o porquê:

O Django já nos dá um identificador por padrão como chave primária para cada modelo que criamos. Trata-se do id.

Assim como eu, muita gente deixa o id como chave primária padrão e, outras vezes, manipulamos a lógica da nossa aplicacão através desse campo da tabela.

Por exemplo:

Vamos supor que temos um modelo de Turma de uma escola, representado abaixo:

from django.db import models

class Turma(models.Model):
    nome = models.CharField(max_length=255)
    alunos = models.ManyToManyField(Aluno)
    disciplinas = models.ManyToManyField(Disciplina)
    
    def __str__(self):
        return self.nome

No nosso modelo de representação, uma turma pode ter vários alunos, várias disciplnas vinculadas e um nome.

O problema é que quando vamos fazer manipulações nos dados desse objeto, é muito comum a gente fazer algo assim:

from django.urls import path
from . import views

urlpatterns = [
    path('editar/<int:id>/', views.editar, name="editar"),
    path('excluir/<int:id>/', views.excluir, name="excluir")
]

Perceba que muitas vezes passamos o id na rota da nossa aplicação. Isso pode resultar em uma falha de segurança gigantesca!

E se o usuário digitar o id 7 na url, acontece o quê? Ele pode manipular aquela informação? E se tivessse uma chave estrangeira para uma escola dona da turma? Qualquer escola poderia ver essa acessar as turmas das outras escolas?

Essas são algumas perguntas que devemos resolver e tomar as devidas precauções.

A grande sacada

Poderíamos adicionar mais um campo de identificador (campo único) no nosso modelo, para funcionar como um identificador público.

Uma Slug é um campo identificador, mas para este exemplo, um UUID se encaixa melhor.

Adicionando o UUID no nosso modelo de turma:

import uuid
from django.db import models

class Turma(models.Model):
    uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    # o valor gerado pode ser algo parecido com 6e198d60-497c-4251-90ef-b839bab40d67
    nome = models.CharField(max_length=255)
    alunos = models.ManyToManyField(Aluno)
    disciplinas = models.ManyToManyField(Disciplina)
    
    def __str__(self):
        return self.nome

Perceba que o campo uuid, apesar de ser elegível para chave primária da tabela, não se torna uma, neste exemplo.

Por que acho melhor assim?

O campo uuid será usado nas rotas públicas da aplicação, pois devido ser uma combinação de caracteres com números, torna difícil do usuários poder mexer na aplicação por curiosidade (isso já elimina a pergunta "e se eu digitar o id 7?"), além de trazer uma segurança maior para a nossa aplicação.

Conclusão

O Django nos traz várias ferramentas e técnicas capazes de desenvolver a mesma aplicação de formas diferentes. No entanto, devemos sempre nos preocupar com a segurança e integridade dos nossos dados, além de manter uma política de permissões de acesso caso necessário.

Uma técnica que eu acho bastante interesante é a de usar dois campos como identificadores no modelo de objeto. Onde, podemos utilizar valores de uuid e slug para as rotas públicas da aplicação e internamente, dentro da view, podemos trabalhar com o id.

Compartilhe

Twitter