Django Clean Architecture Helper é uma aplicação
que permite que os desenvolvedores Django
criem aplicações escaláveis
.
Motivação para a construção do aplicativo:
Obs: Para o melhor entendimento desse projeto, recomendo fortemente a leitura dos artigos acima.
Vantagens na utilização desta aplicação:
- Exclusão lógica no modelos;
- Baixo acoplamento e alta coesão de cada camada;
- CRUD simples já implementado;
Antes de começar, verifique se você atendeu aos seguintes requisitos:
- Você instalou o
python 3
?; - Você instalou uma compatível do
virtualenv
?; - Você instalou a compatível do
virtualenvwrapper
?; - Você instalou o
Django 3.x
?;
Para instalar o Django Clean Architecture Helper, siga estes passos:
- Adicione a dependência no seu arquivo requirements.txt:
git+git://github.com/herlanassis/django-clean-architecture-helper.git@master#egg=v0.3
- Instale as dependências:
pip install -r requirements.txt
Para usar o Django Clean Architecture Helper, siga estes passos:
INSTALLED_APPS = [
...
django_clean_architecture_helper,
]
A seguir será mostrado um exemplo de como utilizar a aplicação para estruturar o seu projeto.
Para este exemplo utilizaremos uma aplicação chamada Post
.
No arquivo models.py
insira:
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django_clean_architecture_helper.models import BaseModel
class ORMPost(BaseModel):
class Meta:
verbose_name: _("Post")
verbose_name_plural: _("Posts")
title = models.CharField(
verbose_name=_("Título"),
max_length=64
)
content = models.TextField(
verbose_name=_("Conteúdo")
)
def __str__(self):
return self.title
A herança do classe BaseModel
permite que o modelo tenha a funcionalidade de exclusão lógica.
É importante utilizar uma entity
como como retorno para não entregar o objeto ORM como resposta a
solicitação de uma camada mais exterior e viole a regra de acesso a camadas.
from django_clean_architecture_helper.entities import BaseEntity
class Post(BaseEntity):
def __init__(self, title, content, **kwargs):
if kwargs:
super().__init__(**kwargs)
self._title = title
self._content = content
@property
def title(self):
return self._title
@property
def content(self):
return self._content
Crie o arquivo databases.py
e adicione o seguinte código:
from django_clean_architecture_helper.databases import BaseDatabase
from .models import ORMPost
from .entities import Post
class PostDatabaseRepo(BaseDatabase):
def __init__(self):
super().__init__(ORMPost, Post)
Por padrão o PostDatabase
vai ter acesso aos métodos existentes no arquivo BaseDatabaseRepo
(CRUD básico para um modelo).
Crie o arquivo caches.py
com o conteúdo:
from django_clean_architecture_helper.caches import BaseCache
class PostCacheRepo(BaseCache):
pass
Para este exemplo não é necessário implementar nenhum método na camada de cache, o BaseCache
vai atender as necessidades.
Crie o arquivo repositories.py
com o código:
from django_clean_architecture_helper.repositories import BaseRepo
class PostEntityRepo(BaseRepo):
def __init__(self, db_repo, cache_repo):
super().__init__(db_repo, cache_repo)
Por padrão o PostEntityRepo
vai ter acesso aos métodos existentes no arquivo BaseRepo
(CRUD básico).
Crie um arquivo chamado interactors.py
e crie os seguintes casos de uso:
from django_clean_architecture_helper.interactors import BaseGetInteractor, BaseDeleteInteractor, BaseCreateInteractor, BaseAllInteractor, BaseUpdateInteractor
class GetPostInteractor(BaseGetInteractor):
pass
class CreatePostInteractor(BaseCreateInteractor):
pass
class UpdatePostInteractor(BaseUpdateInteractor):
pass
class FilterPostsInteractor(BaseFilterInteractor):
pass
class DeletePostsInteractor(BaseDeleteInteractor):
pass
Crie um arquivo chamado presentations.py
e adicione o código:
from django_clean_architecture_helper.presentations import BasePresentation
from .serializers import PostSerializer
class PostPresentation(BasePresentation):
def __init__(self, operations):
super().__init__(serializer=PostSerializer, operations=operations)
Repare que para este exemplo não é necessário criar nenhum método adicional, os métodos referente ao CRUD já foram implementados. Mas, é necessário criar um serializer para conseguir apresentar os dados ao seu solicitante.
from rest_framework import serializers
from django_clean_architecture_helper.serializers import BaseSerializer
class PostSerializer(BaseSerializer):
'''
Post serializer
'''
title = serializers.CharField(required=True)
content = serializers.CharField(required=False)
Para conectar todos os elementos anteriores é necessário criar uma fábríca de dependências e injetar nas instâncias que desejar obter.
from .repositories import PostEntityRepo
from .databases import PostDatabaseRepo
from .caches import PostCacheRepo
from .interactors import GetPostInteractor, CreatePostInteractor, UpdatePostInteractor, FilterPostsInteractor, DeletePostsInteractor
from .presentation import PostPresentation
# Repositories
class PostDatabaseRepoFactory:
@staticmethod
def get():
return PostDatabaseRepo()
class PostCacheRepoFactory:
@staticmethod
def get():
return PostCacheRepo()
# Entities
class PostEntityRepoFactory:
@staticmethod
def get():
db_repo = PostDatabaseRepoFactory.get()
cache_repo = PostCacheRepoFactory.get()
return PostEntityRepo(db_repo, cache_repo)
# Interactors (User Cases)
class GetPostInteractorFactory:
@staticmethod
def get():
post_repo = PostEntityRepoFactory.get()
return GetPostInteractor(post_repo)
class CreatePostInteractorFactory:
@staticmethod
def get():
post_repo = PostEntityRepoFactory.get()
return CreatePostInteractor(post_repo)
class UpdatePostInteractorFactory:
@staticmethod
def get():
post_repo = PostEntityRepoFactory.get()
return UpdatePostInteractor(post_repo)
class DeletePostInteractorFactory:
@staticmethod
def get():
post_repo = PostEntityRepoFactory.get()
return DeletePostsInteractor(post_repo)
class FilterPostsInteractorFactory:
@staticmethod
def get():
post_repo = PostEntityRepoFactory.get()
return FilterPostsInteractor(post_repo)
# Presentations
class PostPresentationFactory:
@staticmethod
def create():
create_post_interactor = CreatePostInteractorFactory.get()
get_post_interactor = GetPostInteractorFactory.get()
update_post_interactor = UpdatePostInteractorFactory.get()
delete_post_interactor = DeletePostInteractorFactory.get()
filter_posts_interactor = FilterPostsInteractorFactory.get()
operations = {
'create': create_post_interactor,
'get': get_post_interactor,
'update': update_post_interactor,
'delete': delete_post_interactor,
'filter': filter_posts_interactor,
}
return PostPresentation(operations=operations)
Repare que cada fábrica gera os seus objetos e passa para eles uma "injeção de dependências".
Neste ponto já temos o necessário para retornar uma resposta a uma request
de um usuário,
para exemplificar isso, vamos continuar o processo utilizando o graphql
como a
camada de iteração entre as requisições e a nossa apresentação. Vale lembrar que
também é possível utilizar endpoints rest
para isso.
As próximas ações para o projeto são:
-
Escrever README - Escrever Documentação
- Escrever Testes
Para contribuir com Django Clean Architecture Helper, siga estes passos:
- Fork esse repositório.
- Crie uma branch:
git checkout -b <branch_name>
. - Faça suas mudanças e comite para:
git commit -m '<commit_message>'
- Push para a branch de origem:
git push origin Django Clean Architecture Helper/<location>
- crie um pull request.
Como alternativa, consulte a documentação do GitHub em criando uma pull request.
Agradeço às seguintes pessoas que contribuíram para este projeto:
Se você quiser entrar em contato comigo, entre em contato com herlanassis@gmail.com.
Este projeto usa a seguinte licença: Apache 2.0.