Arquitetura
Visão geral de alto nível
O EJ adota uma arquitetura monolítica com o servidor principal que controla a lógica de negócios e alguns serviços adicionais que complementam o aplicativo. A maneira recomendada para implantar o EJ é executar cada serviço em um contêiner separado a fim de proporcionar um bom nível de isolamento. Os serviços acima referidos são organizados em uma arquitetura simples de 3-camadas descrita abaixo:
- Nginx
- O tráfego Web não deve ser tratado diretamente pelo serviço de aplicação. Gunicorn não é eficiente para servir arquivos estáticos, e um proxy reverso adicional também pode ser usado para aplicar políticas de segurança mais rigorosas cache mais eficiente. O EJ adota o Nginx. Ele serve arquivos estáticos e redireciona rotas dinâmicas para o serviço de aplicação descrito abaixo. O container Nginx deve compartilhar alguns volumes com o aplicativo Django para encontrar arquivos estáticos.
- Aplicativo Django
- O EJ é escrito principalmente em Python e usa o framework web Django. O serviço principal de aplicação é responsável por todas as rotas dinâmicas, que são geradas pelo Django usando a linguagem de template Jinja2. O aplicativo Django deve ser executado com um serviço compatível com WSGI como o Gunicorn. Esta é a abordagem padrão adotada no contêiner de aplicativo. A tarefa padrão usa um número de trabalhadores igual ao número de núcleos de CPU, que é geralmente a configuração recomendada.
- Base de dados SQL
- O EJ não usa nenhuma funcionalidade específica de banco de dados ou comandos SQL brutos. Isso significa que ele pode ser executado em qualquer banco de dados suportado pelo Django, como Postgres SQL, MariaDB, Sqlite3, etc. Recomendamos Postgres (v10.0), que é usado na instalação padrão. A conexão de banco de dados é controlada por a variável de ambiente DJANGO_DB_URL no contêiner principal do aplicativo.
Integração com o Rocket.Chat
Instâncias que implantam a integração opcional do Rocket.Chat devem considerar os serviços adicionais.
- Rocket.Chat
- Rocket.Chat é um aplicativo Node.js baseado no framework Meteor que serve arquivos estáticos e as rotas dinâmicas. EJ é compatível com o contêiner Rocket. chat oficial no Docker Hub, que é o recomendado método de implantação.
- Mongo DB
- A camada de persistência de Rocket.Chat utiliza o Mongo. O container Rocket.Chat é compatível com a imagem oficial do Docker Hub e requer configuração mínima.
Frontend
O Frontend do EJ é implementado usando a linguagem de templates Jinja2 e usa o conceito de melhora progressiva para incluir estilos através de CSS personalizado e comportamento com JavaScript. Os pontos a seguir apresentam uma breve visão geral das tecnologias usadas em cada uma dessas camadas:
- CSS
- CSS é implementado com Sass usando uma arquitetura inspirada em ITCSS (Inverse Triangle CSS). O módulo CSS é implementado usando o framework para CSS atómico Mendeleev.css e pode ser facilmente personalizado usando temas. Os arquivos CSS são estatisticamente compilados e servidos pelo Nginx. A compilação requer libsass, que é declarada nas dependências Python do aplicativo.
- Javascript / Typescript
- O EJ não adota nenhum framework JavaScript tradicional, mas depende de mecanismos de melhora progressiva para adicionar funcionalidades opcionais. O EJ usa Unpoly em conjunto com jQuery para fornecer a funcionalidade do núcleo. Componentes específicos do EJ são criados usando TypeScript e melhoram as tags anotadas com o atributo "is-component" com comportamentos e funcionalidades extras. A compilação de TypeScript requer o Gerenciador de Pacotes do Node (NPM) e Parcel.
Aplicação Django
Django divide um sistema web em módulos chamados "apps" que implementam modelos de banco de dados reusáveis, rotas e funcionalidades. Esta seção descreve todos os "apps" implementados em EJ.
Projeto EJ
O módulo ej não é propriamente um aplicativo, mas sim um pacote Python regular usado para coordenar apps definindo configurações, funcionalidades comuns e carregando arquivos estáticos como Javascript, CSS, imagens, temas etc. Segue uma visão geral dos principais sub-pacotes e módulos:
ej.all
- Namespace útil para ser usado em uma seção interativa em
from ej.all import *
. Importa modelos e managers de todos os apps ej e exemplos no namespace global. ej.components
- Da mesma forma que
ej.roles
, este módulo define renderizadores para reutilização de elementos de UI. A diferença entre os dois módulos é que os componentes podem ter uma estrutura mais complicada e pode não estar diretamente associada a tipo de dados Python conhecidos. ej.contrib
- Local para incluir migrações ad-hoc. A maioria dos usuários e desenvolvedores nunca deve modificar isto.
ej.fixes
- Módulos que realizam "mokey patch" para consertar problemas com EJ ou qualquer uma de suas dependências.
ej.forms
- Classes base de formulário que são usadas em outros aplicativos EJ. Formulários são derivados de django.forms.
ej.jinja2
- O EJ usa o Jinja2 como linguagem de template padrão. Este módulo configura o ambiente Jinja2 e define funções e filtros globais.
ej.roles
- Funções que definem papéis Hyperpython. Os papéis são mapeamentos de
(tipo, nome) -> HTML
que definem como um determinado objeto deve ser renderizado em um determinado contexto ou papel. Este módulo define muitos elementos de interface reutilizáveis como funções Python. ej.routes
- Defina algumas funções de "view" global (como a página inicial) que não tem funcionalidade vinculada a qualquer app.
ej.services
- Funções do Helper para inicializar conexões com serviços externos, como o banco de dados SQL do Postgres e redimensiona (se habilitado).
ej.settings
- Módulo de configurações do Django. Define a configuração usando o framework de configuração do Django Boogie, no qual a configuração é definida em classes reutilizáveis em vez de um módulo Python.
ej/templates/jinja2
- Contém modelos disponíveis globalmente. O modelo global
base.jinja2
define a estrutura HTML da página base (barras de navegação, meta informações, etc) que é compartilhada entre a maioria das páginas do site. ej.testing
- Ferramentas de ajuda usadas em testes.
ej.tests
- Testes globais. A maioria dos testes são implementados em pastas de teste específicas para cada app.
ej.urls
- Mapeamento de URL para o projeto. A maioria das URLs está incluída no módulo
routes.py
do respectivo aplicativo. ej.utils
- Módulo de funções de úteis.
ej.wsgi
- Django wrapper para a interface WSGI.
Aplicações
A listagem abaixo descreve todos os aplicativos implementados dentro da base de código do EJ.
ej_conversations
-
Este é o aplicativo principal e define modelos para conversas, comentários, e votos. O aplicativo ej_applications implementa a interface de usuário para criar, configurar e interagir com conversas.
ej_users
-
Este aplicativo define o modelo de usuário principal para EJ e todas as rotas relacionadas a autenticação e gerenciamento de conta (por exemplo, redefinir senhas, cancelar conta, etc.). O EJ pode ser usado com os usuários regulares do Django, embora isso não seja encorajado.
ej_profiles
-
Implementa interface de gerenciamento de perfil e define um modelo que armazena informações do perfil. Este app pode ser facilmente modificado para incluir campos de perfil extra ou para remover campos indesejados para alguma instalação específica.
ej_clusters
-
Implementa as rotinas matemáticas para classificar os usuários em grupos de opinião. O módulo ej_clusters.math implementa nosso algoritmo de K-means modificado que leva em conta "estereótipos de opinião" e também fornece interfaces para gerenciar esses estereótipos e os clusters resultantes.
ej_dataviz
-
Implementa rotinas para visualizar dados sobre conversas. Gera relatórios estruturados e exporta dados para formatos compatíveis com planilhas. Este módulo também implementa técnicas de visualização como Word Cloud e Mapas de Pontos a partir das opiniões dos usuários.
ej_gamification
-
O aplicativo de gamificação implementa o sistema de pontos e medalhas no EJ. A maioria das interações na plataforma são recompensadas com pontos. Usuários que conseguem níveis pré-definidos de participação recebem medalhas que reconhecem diferentes tipos de interações, como a votação de comentários, a criação de conversas, etc.
ej_boards
-
O aplicativo de quadros permite que usuários regulares tenham seu próprio "quadro" ou "linha do tempo" de conversas. O feed de conversas padrão em "/conversations/" pode somente ser gerenciado por usuários com permissões especiais.
ej_experiments
- Este app opcional é responsável por criar e salvar dados de teste no banco de dados. É útil para o desenvolvimento, mas não está habilitado em instalações de produção.
Apps de terceiros
boogie.apps.fragments
- O aplicativo de fragmentos do Boogie implementa textos configuráveis ou fragmentos HTML salvos em banco. Isto permite um maior nível de configuração permitindo que os usuários administrativos personalizem partes da plataforma sem precisar alterar código.
rules
- Django-rules implementa um mecanismo para definir regras de negócio registrando funções de predicado simples. Este pacote integra-se com os próprios mecanismos de permissão do Django. As regras de negócio relevantes para cada aplicativo EJ são implementadas no respectivo módulo "rules.py de cada app Django e podem ser substituídas por aplicativos ou módulos de terceiros.
Django taggit
- Django-taggit é um aplicativo Django que implementa tags para modelos arbitrários. É utilizado para adicionar tags às conversas do EJ.
rest_framework
- O Django-Rest-Framework (DRF) é um poderoso conjunto de ferramentas para desenvolver APIs REST Web. O EJ usa DRF através do módulo rest_api do Django-Boogie.
allauth, allauth.account, allauth.socialaccount
- O projeto allauth implementa fluxos de trabalho de autenticação e autorização e integração com provedores OAuth de terceiros como Google, Twitter e Facebook.
Estrutura dos apps
O EJ usa Django Boogie adopta uma arquitetura que pode ser ligeiramente diferente de um aplicativo Django típico. Um objetivo importante da arquitetura é fazer funções e views menos repetitivas. Isto é realizado movendo funcionalidade para a própria estrutura do Boogie ou criando mecanismos para dividir a funcionalidade em módulos separados.
Um aplicativo EJ típico tem a seguinte estrutura:
<app>.admin
- Classes e funções do Django admin.
<app>.api
- Define os campos e rotas API para os modelos definidos pelo app. Normalmente,
funcionalidade implementada neste módulo simplesmente complementa as declarações principais da API
que são criadas usando o decorador
@rest_api
diretamente nos modelos. <app>.apps
- Mecanismo AppConfig do Django. Apps do EJ geralmente devem substituir o método
ready()
da configuração do aplicativo e importar os módulos api, roles e rules. <app>.enums
- Este módulo define qualquer tipo de enum que eventualmente seja usado por modelos. Enums geralmente são importados para o namespace do app. Por isso, eles não devem depender de modelos.
<app>.forms
- Formulários Django definidos para o aplicativo. Formulários normalmente herdam do ej.forms em vez de usar django.forms diretamente.
<app>.math
- Todas as funções matemáticas devem ser definidas neste módulo. As transformações matemáticas complexas devem ser implementadas como transformações de ScikitLearn ou pipelines.
<app>.managers
- No Django, classes de modelo define lógica de linha e gerentes e consultas implementa a lógica da tabela. Todos os métodos que consultam, criam instâncias ou filtram consultas devem ser implementados no módulo "managers"
<app>.models
- Tal como em aplicativos Django padrão, este módulo define os modelos para o aplicativo. Modelos devem evitar implementar a lógica de negócios dentro deles e idealmente deve restringir as ações de banco de dados, como consultas, validação, etc.
<app>.mommy_recipes
- O EJ usa o Model Mommy para criar recursos aleatórios para testes. Este módulo deve
definir uma classe que derive de
ej.testing.EjRecipes
e implementa fixtures para cada modelo definido no aplicativo. Isto é usado apenas em testes. <app>.routes
- Os aplicativos regulares do Django têm um views.py e arquivos urls.py. Django Boogies incentiva a unir ambos os arquivos em um único routes.py que define o modo de exibição funções e mapeia-los para rotas usando decoradores.
<app>.rules
- As regras de negócios são implementadas como funções regulares dentro deste módulo. Isto ajuda a evitar o anti-padrão "fat-models" que é comum em projetos Django. O módulo de regras pode definir tanto permissões (que são funções de predicado centradas no usuário) e "valores" regulares, que podem retornar valores não-booleanos (por exemplo, o número de comentários que o usuário ainda tem em conversa).
<app>.roles
Papéis Hyperpython são funções simples que renderizam objetos em contextos determinados. Por exemplo, podemos registrar um papel de “cartão” na classe Conversation que processa a conversa de entrada como um cartão em uma visualização de lista. Funções de papel devem ser associadas com um tipo e um nome e devem retornar uma estrutura Html Hyperpython.
Nos casos em que o Jinja2 é mais conveniente do que o Hyperpython, o
ej.roles.com_template
pode ser usado para associar o papel com um modelo Jinja.<app>.tests
- Testes unitários do aplicativo.
<app>.validators
- Implementa as funções de validação usadas em campos de modelo ou campos de formulário dentro do aplicativo.
Templates¶
Os templates residem dentro da pasta <app>/jinja2/1>
. Utilizamos a melhor prática do Django
de salvar modelos específicos do aplicativo dentro de jinja2/<app-name>/<template-name>.jinja2
.
Os nomes dos templates geralmente espelham os nomes das funções de visualização no arquivo routes.py
. Por exemplo, uma view de edição para alguma conversa seria declarada como:
urlpatterns = Router(template='ej_conversations/{name}.jinja2')
@urlpatterns.route("/<model:conversation>/edit/")
def edit(request, conversation):
... # Implementation
Essa função de exibição é automaticamente associada com o ej_conversations/edit. jinja2
modelo, a menos que especificado de outra forma.
A maioria dos modelos herda de um modelo base em src/ej/templates/jinja2/base. jinja2
.
Este template importa elementos de navegação, como menus e barras de ferramentas.