Django TileStache

Nesta postagem iremos falar sobre mais um trabalho da SIGMA que disponibilizamos de maneira open-source. Desta vez iremos falar sobre o Django TileStache.

O TileStache é um servidor de tiles, escrito em Python. É um servidor bastante flexível, bastando uma configuração em JSON para que o mesmo funcione.

Ele é perfomático, mas a limitação dele de funcionar apenas com um arquivo de configuração estava nos incomodando.

O problema

Em algumas de nossas soluções, nossas camadas a serem servidas pelo TileStache são dinâmicas. Isto significa, que depois de determinado evento, precisarei servir novos dados através do TileStache.

Um exemplo claro: dentro do Geoadmin, quando um cliente novo se registra, precisamos servir as camadas que são dele. E isto necessita de uma nova configuração.

A solução

A solução para este problema tem duas partes. A primeira delas foi desenvolver um cadastro de camadas. Este cadastro de camadas já é preparado para funcionar com o Django REST Framework e nos permite cadastrar layers de forma arbitrária. Todos os tipos de providers suportados pelo TileStache são suportados, mas via REST, apenas quatro tipos, por agora:

  • External (classes externas);
  • Vector (qualquer fonte, PostGIS, Shapefile, Spatialite e JSON);
  • Mapnik;
  • Proxy;

Usar o cadastro de layers é bastante simples, veja só:

from django_tilestache.models import Layer

layer = Layer.objects.create(
    **{
        'name': 'foolayer'  # this is the tilestache layer name
        'provider': {

        },  # tilestache provider options
        '...' : 'foo' # all other options
    }
)

No exemplo acima, criamos uma layer com o nome de foolayer, mas não demonstramos as opções de provedor. Se você seguir o TileStache, qualquer layer será válida.

A outra parte da solução, consiste num servidor customizado do TileStache. Pegamos o servidor WSGI original e extendemos o mesmo para que de, tempos em tempos, ele faça um request para o servidor de comando e controle (neste caso, a aplicação Django que contém o django-tilestache instalado), que retorna a nova configuração.

Você pode, e deve, inclusive, estabelecer credenciais para isto. A configuração do TileStache contém informações sigilosas e não deve ser exposta diretamente para internet.

Views

Duas views iniciais foram desenvolvidas para suportar algumas questões de desenvolvimento aqui na SIGMA, são elas:

  1. TileStacheConfiguration – esta view específica retorna a configuração registrada do TileStache, em formato JSON. Este é o endpoint utilizado para que o TileStache remoto, consiga se atualizar.
  2. TileStacheTile – esta view renderiza tiles das camadas registradas, ou seja, caso você não queira, você pode usar esta view para servir seus tiles em seus projetos Django.

Instalação

pip install django-tilestache

Configuração

  1. Vá em seu settings.py do Django. Adicione django_tilestache nas INSTALLED_APPS.
  2. Rode o comando migrate para criar os modelos no seu banco de dados;
  3. Adicione as urls do django-tilestache dentro do das suas URLS. Este passo é opcional. Se você fizer isto, terá de usar a estrutura de URLS definida pelo app. Caso queira alterar esta estrutura, registre suas views manualmente;

Gostou?

O repositório está disponível em: https://gitlab.sigmageosistemas.com.br/dev/django-tilestache. Seja bem vindo e nos ajude na construção deste pacote.

Abraços

Django Workflow

Você, desenvolvedor, já se deparou com cenários específicos em que você precisa controlar um fluxo de informações, mas, suportando diversos status, com diversos efeitos colaterais diferentes, entre cada mudança desses status?

Criar e manter este tipo de estrutura, manualmente, é bem complicado. Formalmente, este tipo de estrutura é chamada de máquina de estado finita ou finite state machines e para os íntimos, FSM.

Inspirados em outros pacotes disponíveis para o Django, construímos nosso próprio gerenciador de máquinas de estados. Este é mais um pacote open-source que disponibilizamos para a comunidade.

Aplicações das FSM

As aplicações das FSMs são diversas. Elas podem controlar como compoenentes internos de uma aplicação reagem a estímulos externos (usuário informa determinada informação) ou mesmo serem editadas pelo próprio usuário. Um exemplo disso são os famigerados BPM (Bussiness Process Management**) onde os próprios usuários definem até certo ponto, o fluxo da informação e por quais verificações esta deve passar antes de permitir a troca de um estado para outro.

Outro exemplo interessante é que algumas AIs são escritas usando os conceitos de FSM para determinar comportamentos de seus agentes, portanto, te garanto, FSMs são bastante flexíveis.

Na realidade, a ideia desta aplicação Django surgiu para atender uma demanda, onde os usuários mais graduados, deveriam poder escolher como a informação fluiria numa aplicação geográfica.

Instalação

Para instalar este pacote é bem simples e você pode usar o pip:

pip install django-workflow-fsm

Agora adicione este pacote ao seu INSTALLED_APPS:

INSTALLED_APPS = (
    # outras apps,
    'workflow',
    # outras apps,
)

Execute suas migrações com ./manage.py migrate

Getting Started

Terminado isto, você precisa definir qual é o modelo que você deseja controlar o status. Basta você herdar de um MixIn para obter a funcionalidade de máquina de status:

# models.py
class Projeto(StateControllerMixIn):
    nome = models.CharField(max_length=128)

Pronto. A configuração básica está pronta!

Depois disso, com toda a certeza, você deve querer editar quais status e como a informação flui entre estes status. Isto é bem fácil.

Nós controlamos o fluxo de informações utilizando três modelos:

  • StateMachine;
  • State
  • Transition;

Vamos construir isso em um passo a passo rápido:

# shell ou fixture ou migração de dados
status_aberto = State.objects.create(code='aberto')
status_em_andamento = State.objects.create(code='em-andamento')
status_fechado = State.objects.create(code='fechado')

# nossos status estão criados. Vamos criar nossa máquina de estado

fsm = StateMachine.objects.create(name='projetos-simples', initial_state=status_aberto)
# na linha acima definimos nossa máquina e o status inicial dela, aberto.

# agora vamos definir as transicoes
aberto_andamento = Transition.objects.create(name='iniciando-projeto',
    machine=fsm,
    from_state=status_aberto,
    to_state=status_em_andamento)

andamento_fechado = Transition.objects.create(name='finalizando-projeto',
    machine=fsm,
    from_state=status_em_andamento,
    to_state=status_fechado)

Agora que nossas transições estão prontas, você pode definir qualquer projeto, com diferentes tipos de máquinas de estado, basta escolher a máquina de estado apropriada, veja só:

projeto = Projeto()
projeto.nome = 'projeto legal'
projeto.save(state_machine=fsm)

Neste momento, todas as ações da máquina de estado estão disponíveis através do mixin que você herdou na construção do modelo Projeto.

Exemplo:

projeto.current_state
# imprime "aberto"
projeto.next
# imprime "em andamento"
projeto.change_to(state_em_andamento)
# projeto será enviado para o estado "em andamento"
projeto.next
# imprime 'fechado'

Não é só isso, existem diversos ganchos que você pode usar, como tarefas específicas a serem disparadas e ações, nas quais você pode associar a um estado, para indicar que esta ação está disponível. Exemplo: no status em andamento do projeto, vocẽ pode criar comentários e apenas neste estado. Portanto, você pode criar uma Action e associá-la ao estado em-andamento.

No seu código, vocẽ pode checar qual action está disponível e renderizar o template como você achar melhor.

Outras coisas legais:

  • Você pode associar permissões a cada estado, ou seja, apenas usuários com determinadas permissões podem trocar o estado da máquina;
  • Você pode associar tasks (ou tarefas) que serão executadas quando um estado da máquina é alterado. Por exemplo, quando a máquina de estado mudar de estado, quero disparar um email para um usuário, informando do ocorrido. Você pode criar isso como uma Task e associar esta task a transição específica.
  • Suporte para tarefas assíncronas. Por padrão, as tarefas são executadas usando o Celery, que é uma dependência do projeto. Caso você não queira executar estas tarefas de forma assícrona, basta desabilitar o Celery.
  • Suporte completo para API REST, usando django-rest-framework

Repositório

Disponível no Github: https://github.com/sigma-geosistemas/django-workflow

Roadmap

  • Suporte completo para tarefas assíncronas e síncronas (hoje só suportamos um modo, queriamos suportar os dois);
  • Melhorar a infraestrutura de testes;
  • Melhor/criar um help/ajuda/getting started;
  • Outras coisitas;

Este é um pacote bem completo para gestão de máquinas de estado. Caso você tenha interesse, dê uma conferida. Estamos a disposição!

Integrar software livre com software proprietário

Antes de falar sobre as diferenças de software livre e proprietário vamos imaginar o seguinte cenário: A empresa X trabalha com gestão de imóveis. Sua carta de clientes soma mais de 10 mil propriedades. Para gerir todos os clientes a empresa usa um software (vamos batizá-lo de “SISTEMA Y”). Para usar esse software a empresa gasta mensalmente 2000 reais. Ao longo do tempo, o “SISTEMA Y” é assimilado e todos os funcionários detém domínio do sistema.

A empresa X vai bem, mas precisa integrar novos serviços ou melhorar aqueles que já oferece. Nesse cenário o software SISTEMA Y desempenha muito bem suas atividades mas não oferece suporte, por exemplo, para gestão de fundiária. Nesse momento a empresa X tem duas opções:

  1. Instalar um novo software proprietário que atenda sua demanda, ou
  2. Integrar um software livre ao seu programa de gestão.

A questão é controversa. Mas entre prós e contras, a integração de softwares proprietários e livres é possível e apresenta benefícios singulares para construir sistemas especialistas de forma rápida e eficiente. Antes de prosseguir vamos falar rapidamente sobre sobre a diferença entre duas classificações:

Como o próprio nome diz o software proprietário é de propriedade de alguém (ou alguma empresa). Isso significa que ele tem um estrutura fechada que, em geral não pode ser modificada nem redistribuída. Os direitos sobre o software são exclusivos de quem o desenvolveu e para utilizá-lo é necessário o pagamento de uma licença. No cenário hipotético com a empresa X, o “SISTEMA Y” seria um software dessa natureza

O software livre, por sua vez, é de natureza oposta. Ele pode ser copiado, alterado e redistribuído livremente. Para utilizá-lo o usuário pode ou não pagar por uma licença, mas independente disso, o código- fonte do software livre está sempre aberto para modificações.

Quebrando barreiras

A integração de softwares livres à softwares proprietários é uma discussão antiga. Nesse artigo, além de explicar a diferença entre os dois modelos de software, vamos discorrer sobre os benefícios dessa integração de softwares livre para empresas que utilizam o um sistema proprietários.

Vamos retomar o exemplo da empresa X. Ao integrar o novo software ao sistema que já opera (SISTEMA Y) a empresa tira a burocracia de acesso. Ou seja, não é necessário outro login. Isso simplifica sutilmente a vida dos colaboradores (que diminuem um procedimento de acesso) e favorece drasticamente o trabalho da equipe de TI (que não vão gerenciar o dobro de cadastros no sistema). No fim estamos falando de economia de desenvolvimento, tempo e dinheiro.

Para o operador do sistema os benefícios dizem respeito a adaptabilidade à uma nova ferramenta de gestão. O software integrado não muda o ambiente tecnológico do colaborador, na verdade ele adiciona uma nova ferramenta nesse universo, a partir da mesma interface. Na prática a integração otimiza a implantação e uso do novo software, a fase de treinamento é menor.

Os usuários, portanto, são mais positivos ao uso de novas ferramentas quando elas estão inseridas no próprio software com o qual já estão seguros. A integração de softwares livres em softwares proprietários promove assim maior eficiência a todo conjunto administrativo da empresa..

Como escrever bons relatórios de bugs

Escrever software é dificil. Manter um software atualizado e em funcionamento
sem defeitos, é ainda mais dificil.

Uma das ferramentas mais importantes para que isso ocorra, isto é, a criação
e manutenção de um bom software, com o mínimo de defeitos (nenhum software é perfeito), é sem dúvida, os relatórios de
defeitos, ou bug reports.

Eles podem ser criados por qualquer pessoa que use de fato o software, qualquer
que ele seja. Alguns relatórios de bugs (chamaremos apenas de bugs, daqui por)
diante serão escritos por desenvolvedores, que notarão comportamentos estranhos
ainda na etapa de desenvolvimento. Outros serão escritos por testadores profissionais,
que ganham o pão procurando a desgraça alheia. E outros bugs, serão encontrados
apenas quando o nosso software estiver em produção – pelo usuário final.

Não importando quem escreveu, todo e qualquer bug merece um relatório e uma
investigação formal. O quanto antes, melhor. Bugs tendem a ficar cada vez mais
caros, conforme o tempo passa. Estima-se que um bug descoberto em produção custa 10 vezes mais o valor do que se ele tivesse sido encontrado antes – durante o desenvolvimento.

A conta é simples: se o bug tivesse sido encontrado durante a etapa de desenvolvimento, o desenvolvedor gastaria 2 horas para resolvê-lo e adicionar
um teste de unidade, afim de garantir que o mesmo não retorne para assombrar ninguém,
anos depois.

Se o bug é encontrado em produção, serão gastos, aproximadamente, 20 horas para
resolvê-lo. Senão mais. Tudo em produção é mais difícil.

Certo, bugs são caros, mas e daí? Bem, se podemos resolver o bug em desenvolvimento
e uma das principais formas de se resolver um bug é criando um bug report,
bons relatórios de bugs facilitam a vida dos desenvolvedores, na hora de encontrar
o danado e resolvê-lo de uma vez por todas.

Maus relatórios de bugs deixarão os desenvolvedores e usuários irritados. Bugs
com títulos e descrições inadequadas serão muito mais difíceis de serem resolvidos,
pois são mais difíceis de serem encontrados, terem o comportamento exato reproduzido,
assim por diante.

Uma máxima importante é:

Um bom relatório de bug descreve o problema de forma que o desenvolvedor familiarizado com o projeto pode entender e resolvê-lo, sem falar com a pessoa que o escreveu.

Esta é uma tradução generalizada de uma [postagem do martiancraft][martincraft-bug-report]. Realmente, devo concordar com o título.

Pequena estória: uma certa vez, trabalhando com um cliente – sem expertise técnica, decidiu que gostaria de escrever seus próprios relatórios de bugs. Ótimo, pensei, uma coisa a menos que terei de fazer. Este cliente nunca havia utilizado ou mesmo visto um relatório de bug.

Quando ele começou a escrevê-los, ele colocava títulos estranhos, descrições que não mencionavam como reproduzir o mesmo e tentava explicar problemas de desenho da tela, utilizando palavras – sem um simples screenshot se quer. Tudo bem, pensei, ele apenas precisa aprender a escrever melhores relatórios de erros e nossa vida será muito mais fácil. Enviei alguns links para ele e a situação melhorou.

Os bugs eram corrigidos mais rapidamente, pois gastávamos menos tempo tentando entender o que ele quis dizer com aquilo. Facilitou a comunicação sobre outras funcionalidades que ele queria para seu produto. Entre diversas outras coisas.

Então, confiem em mim: um bom relatório de erros é essencial para a vida do desenvolvedor e do maior interessado, o cliente.

Então, o que todo bom relatório de bugs deve conter?

Apenas um problema por relatório

Apenas um problema por relatório de defeito. Apenas. Um. Problema. Por. Relatório.

Não existe forma de deixar isto mais claro. Quando você tem um ou mais defeitos em um mesmo relatório de bugs, isto confunde o desenvolvedor, dificulta a correção e dificulta principalmente o teste da correção.

Outra: os dois problemas andam juntos, são corrigidos juntos e aprovados juntos. Em uma equipe, estes problemas poderiam ter sido resolvidos em paralelo, fechados com timelines distintas (um bug era fácil, o outro difícil) e com maior qualidade.

Nunca reporte mais de um bug em um único relatório. Nunca. Mesmo se eles forem relacionados. Cada bug é importante o suficiente para merecer seu próprio relatório.

Título e Descrição

Um bom título é essencial para avaliação rápida do problema. Títulos que não esclarem a situação, ou mascaram o problema real, são as formas erradas de começar a escrever um relatório de erros.

Um bom título ajuda o desenvolvedor a realizar a triagem do bug, algo como: “ah é só um texto na tela”, “faltou uma validação aqui e ali” e “rapaz…tenho menor ideia do que diabos é isso”. Não só ajuda a identificar a criticidade do bug, mas também mais ou menos de onde vem o problema, facilitando a delegação da resolução para um ou outro desenvolvedor ou time.

Já as descrições são os lugares para se dar detalhes sobre o bug. Contexto, informações do ambiente, passos para reprodução do bug, dados para reprodução do bug, temperatura do ar, pressão atmosférica e humor do chefe no dia.

Sem essas informações cruciais, fica muito mais difícil reproduzir o bug, tornando o mais caro para a empresa e para o cliente.

Exemplos:

  • RUIM: “A aplicação não responde”;
  • BOM: “A aplicação não responde após a carga do arquivo XPTO na tela FOO”;

  • RUIM: “Texto fora do padrão”;

  • BOM: “Texto do título ‘Pesquisa’ está desformatado”;

  • RUIM: “Não consigo salvar imagens”;

  • BOM: “Dentro da tela de redimensionar imagens, ao tentar salvar a mesma após cortar 30% da largura da imagem, não consigo salvar as imagens”;

Acho que deu para entender.

Passos detalhados e comportamento esperado

Certo, temos nossos bugs, mas como recriar a situação? A primeira coisa que um desenvolvedor fará, é tentar recriar a situação para ver se o erro encontrado não é esporádico, se tem relação com as marés ou a lua, ou se é realmente um defeito encontrado consistentemente.

Defeitos esporádicos, como, “relatório não pode ser gerado durante os meses que possuem 31 dias” existem e são legítimos, mas o desenvolvedor primeiro irá procurar se ele não vem de uma má configuração ou algum passo errado que o usuário possa ter executado no momento de usar a aplicação.
Defeitos consistentes são rapidamente avaliados pois temos certeza de quais passos realizar para reproduzir o erro. Sem os passos, o desenvolvedor deverá contar com a sorte para reproduzir o danado – tarefa tediosa e que pode não resolver o problema.

Vamos dizer que um erro é encontrado em apenas 1/10 das vezes em que se executam uma tarefa, aleatoriamente. O desenvolvedor testou 9 vezes, mas o erro não se apresentou. O que ele irá pensar? Que não existe erro algum e talvez o usuário estivesse em uma versão antiga, ou o conjunto de dados mudou.

Mesmo que o responsável por reportar o defeito não saiba exatamente quais ações foram realizadas, em detalhes, para incluir no relatório, um conjunto mínimo de passos ajuda muito.

Exemplo:

  • RUIM: “Loguei no sistema e cliquei em imprimir no relatório.”;
  • BOM:
    • Logar no sistema com usuário que tenha permissão para gerar relatórios;
    • Clicar na seção de relatórios;
    • Escolher o relatório de faturamento;
    • Agrupar por mês e filial;
    • Clicar em gerar relatório;
    • Sistema apresenta uma tela azul;
    • Sistema deveria apresentar uma tela com um relatório em PDF, contendo o relatório de faturamento mensal, agrupado por filial;

A diferença entre os dois é gritante.

Quanto ao comportamento esperado, ele também é fundamental para quem for testar o bug e confirmar que o mesmo está resolvido. Além dos passos de testes, o comportamento esperado é o prego no caixão do defunto – ele tratá a certeza para o desenvolvedor de que o problema morreu.

Contexto

Informações de contexto são cada vez mais importantes, conforme os mesmos são distribuídos por uma gama muito maior de clientes – a web, por exemplo.

Um bom contexto contém:

  • Sistema operacional e versão;
  • Navegador utilizado e versão (em aplicações web);
  • Versão do software que está sendo utilizado;
  • Informações relevantes ao uso do sistema (dados, usuários, grupos e permissões, etc);
  • Condições especiais (com GPS do celular ligado, com pouca bateria no notebook, com a rede ligada, etc);

Em casos extremos, como aplicações gráficas ou desktops, qual placa de vídeo, qual resolução utilizada, etc. Quanto maior o número de detalhes, mais fácil.

Prioridade

Não confunda prioridade com criticidade. Prioridade é o quanto um bug impacta no dia a dia do usuário. Um bug crítico em uma funcionalidade usada apenas uma vez no ano, é muito importante, mas um bug de severidade média em uma ferramenta utilizada todos os dias tem prioridade muito maior de resolução.

Screenshots

Ah, os screenshots. Eles são muito úteis para provar que o usuário não está ~~louco~~ sonhando. Brincadeiras à parte, os screenshots colocam o desenvolvedor numa máquina do tempo e na máquina do usuário. Principalmente se o bug envolver qualquer tipo de tela ou interface de usuário.

Não é tão difícil, então, sempre que possível, tire um screenshot, desenhe em cima dele, aponte uma seta para o problema. O desenvolvedor será muito grato.

Quando fechar um bug

Existe ciclo de vida natural de um bug, que varia de empresa para empresa, mas o mais simples geralmente acontece assim:

  1. Defeito é encontrado;
  2. Bug é relatado;
  3. Desenvolvedor faz uma triagem do bug;
  4. Desenvolvedor resolve o bug;
  5. Desenvolvedor altera o status do bug para o relator conferir se o problema realmente foi resolvido;
  6. Relator fecha o bug (ou reabre, caso o conserto não tenha sido muito bom – neste caso, volte para item 3);

Este é o fluxo mínimo que temos de trabalho. Quando o bug resolvido chegar na “mesa” do relator, ele deve separar um tempo para fazer o teste da resolução, o quanto antes melhor e dar andamento nos processos.

Se outro defeito foi encontrado, crie outro bug. A maior parte das ferramentas atuais permitem que você referencie bugs e/ou tarefas, facilitando o desenvolvedor a acompanhar o histórico.

Pensamentos finais

Escrever relatórios de erros não é difícil. É um processo em que se colabora com a construção do software, então deve ser minimamente organizado e coerente. Desenvolvedores não tem bolas de cristal e não são hackers do tipo Matrix, onde vem tudo em código o tempo todo.

Um bom relatório de bugs é certamente apreciado e muito mais legal de ser resolvido do que um mau relatório. Seja bonzinho e nos ajude a te ajudar :D.

Links interessantes

Integrando o Django com o AD Microsoft

Em um projeto novo da SIGMA, nos foi solicitado que utilizássemos
os usuários registrados no Active Directory do cliente, significando
que teríamos de integrar toda a funcionalidade de login do nosso projeto
Django com este camarada.

Existem diversas razões para esta integração, principalmente no nosso
caso, em que o cliente final é uma grande empresa, com toda uma infraestrutura
de Tecnologia da Informação bastante sólida e madura.

Entre estas razões, se encontram, em ordem de prioridade:

  1. Cliente não quer mais um usuário/senha para usar um sistema especialista;
  2. Equipe de TI não quer gerenciar os cadastros dos usuários em mais um sistema;
  3. Economia no desenvolvimento, de tempo e dinheiro;

Como funciona?

O Django, como um framework, já possui toda um maquinário importante para
criação e manutenção de permissões e grupos. Mas existe uma “pegadinha”:
o usuário em questão precisa existir no banco de dados que estamos usando.

Isto porque as permissões e grupos estão armazenadas em um banco de dados
relacional e existem relações com chaves estrangeiras entre usuários, permissões
e grupos.

O fluxo mais simples, portanto é:

  1. Usuário se autentica com a senha do Active Directory;
  2. Usuário está inativo no AD? Caso esteja, impeça o login e inative o usuário local;
  3. Usuário não está inativo, confira a senha;
  4. Sistema confere se o usuário já existe na base local;
  5. Caso ele já exista, ok, não faça mais nada;
  6. Caso ele não exista, copie os dados do usuário e crie um novo usuário na base local;
  7. Associe permissões/grupos;
  8. Vitória;

Seguindo este fluxo, todos os componentes do Django continuam a funcionar e não
precisamos criar permissões remotas no AD (ou LDAP) o que tornaria tudo
mais complicado de administrar (pense nas migrações do Django).

Outro ponto importante, delimitador deste fluxo, é a necessidade das sessões HTTP
no Django. Sem existir um usuário na base, não conseguiremos manter as sessões. Teríamos
de adaptar também o componente que registra e valida as sessões ativas.

Portanto esta arquitetura de cópia de usuários é a mais comum para integração
em bases de usuários “remotas” (este fluxo também é usado em pacotes que realizam
autenticação e integração com outros provedores de login, como OAuth2, por exemplo).

Como realizar a integração?

Felizmente, o Django é um projeto bastante modular. Neste caso em específico,
o Django aceita a configuração de settings de autenticação, permitindo
inclusive a autenticação em múltiplos backends, em cascata. Caso a autenticação
do usuário não funcione em um backend, ele tenta no próximo.

A arquitetura do Django facilitou bastante nossa vida neste sentido.

Quais são os passos:

Configurar o AUTHENTICATION_BACKENDS em seus settings.py

Desenvolver ou reutilizar um pacote open-source que já faz a conexão
e validação do usuário no Active Directory. No nosso caso, utilizamos o
django-python3-ldap.

Configurar as variáveis do django-python3-ldap:

# settings.py
LDAP_AUTH_USER_FIELDS = {
  "username": "uid",
  "first_name": "givenName",
  "last_name": "sn",
  "email": "mail",
}
LDAP_AUTH_USER_LOOKUP_FIELDS = ("username",)
LDAP_AUTH_CLEAN_USER_DATA = "django_python3_ldap.utils.clean_user_data"
LDAP_AUTH_SYNC_USER_RELATIONS = "jango_python3_ldap.utils.sync_user_relation"
"  LDAP_AUTH_FORMAT_SEARCH_FILTERS = "django_python3_ldap.utils.format_search_filters"
# Atenção neste ponto, pois ele é necessário para funcionar com o AD
LDAP_AUTH_FORMAT_USERNAME = "django_python3_ldap.utils.format_username_active_directory"```

Para a url indique conforme abaixo substituindo <ip_ou_dominio>
por seu ip ou dominio:

# settings.py
LDAP_AUTH_URL='ldap://<ip_ou_dominio>:389'

Utilize o comando dsquery user no ms-dos para obter a seguinte informação informação:

C:\Users\csantos>dsquery user
"CN=Claudio Santos,CN=Users,DC=server,DC=local"
"CN=Guest,CN=Users,DC=server,DC=local"

Utilize os três critérios de pesquisa, resultando em: LDAP_AUTH_SEARCH_BASE = 'CN=Users,DC=server,DC=local'

Comumente temos dois tipos de usuários: InetOrgPerson ou Users. Nós utilizamos o Users,
configurando LDAP_AUTH_OBJECT_CLASS = 'Users'

Configure este settings com uma variável que podemos pegar na
tela de criação de usuário no campo em destaque na imagem,
ela representa o Pre-Windows 2000 Domain Name do Active Directory:

attribute-editor-uid

# settings.py
LDAP_AUTH_ACTIVE_DIRECTORY_DOMAIN = 'SERVER'

Por fim vá em Active Directory Users and Computer, vá na pasta Users,
em seguida, clique com o botão direito, propriedades e por fim na aba Atributte Editor
informe o login do usuário no atributo uid, como mostrado na imagem abaixo;

attribute-editor-uid

Conclusões

Não vou discorrer aqui sobre os benefícios técnicos de usar open-source ou
coisa do tipo, mas sim dos benefícios gerados por uma integração deste nível.

As vantagens auferidas tem um profundo impacto psicológico sobre o usuário final
e sobre o retorno sobre investimento.

Em primeiro lugar, o sistema parece ter sido construído e fazer parte de fato
de toda a organização. O usuário não tem a impressão de sair de seu ambiente tecnológico,
confortável e seguro, para trabalhar em um sistema externo.

Como segundo ponto, o usuário tem uma barreira menor para utilizar o sistema.
A adoção de novos sistemas em organizações grandes sempre foi e sempre será
uma dificuldade, pelo próprio fator humano. Como a barreria de início é menor,
maior será a adoção dos usuários.

Em terceiro lugar, mas consequência do segundo ponto, quanto maior a adoção
dos usuários, maior o impacto que o novo sistema terá na organização, trazendo
um retorno maior para os stakeholders do projeto.