Django – Separando Models por arquivo

Filed Under (Desenvolvimento) by Samir on 19-03-2010

Tagged Under :

Uma dúvida muito comum sobre o ORM do Django é se existe a possibilidade de quebrar os models em partes menores, ou seja, separar um grupo de classes específicas e coloca-lás em um módulo Python.

Essa técnica pode ser útil conforme sua necessidade, se você possui uma app com muitos models, por ser interessante separa-lás por arquivo. Eu tive esse problema recentemente, procurei na net e achei uma forma interessante de fazer isso e principalmente, não quebrar a compatibilidade com as ferramentas externas, como o syncdb ou o south que utilizo bastante.

Sem muita enrolação, imagine a seguinte estrutura para um projeto:

Transferências

Tendo a estrutura pronta, temos que editar os models de forma que o Django entenda nossa nova estrutura.
Por exemplo no arquivo financeiro.py da app2:

from django.db import models

class Financeiro(models.Model):
    class Meta:
        app_label = 'app2'

Observe que sou obrigado a informar explicitamente o nome da aplicação para cada model, sem isso o Django não consegue entender que essa classe pertence a aplicação app2.

E por último, no arquivos models.py de cada aplicação temos que importar as classes:

from app2.models_src.financeiro import Financeiro

Uma coisa muito importante que passei entender sobre o Django é que ele lhe dá muita flexibilidade para modificar sua estrutura e sobreescrever qualquer feature padrão, por tanto quanto melhor seu conhecimento em Python, melhores serão suas chances de extrair o máximo do framework.

Desenvolvendo Sistemas com Django

Filed Under (Desenvolvimento) by Samir on 03-12-2009

Tagged Under : ,

Essa é uma questão comum que ja vi lista #django-brasil onde muitos desenvolvedores ficam na dúvida para escolher a melhor opção de criar sistemas usando o Django. Fazer tudo no “braço” mesmo criando suas próprias views, htmls, rotas, etc…tudo para ter a melhor flexibilidade possível. Ou como segunda opção usar o próprio admin e aprender como customizar quando necessário.

Antes de iniciar o projeto que ando trabalhando, testei muitas opções de frameworks. Queria algo que pudesse agilizar ao máximo meu trabalho, porque convenhamos, ficar fazendo tela de CRUD alem de ser um trabalho maçante, propenso a erros, é um verdadeiro pé no saco! Nessa época como ainda estava ligado muito no Rails, tentei algumas opções, mas tudo me levava a fazer o CRUD na mão. Voltei novamente a pesquisar opções em Python, nessa época eu já até conhecia bem o admin do Django, mas tinha um certo receio do tipo, “esse negócio vai me deixar na mão”, mas foi puro engano, vou explicar adiante.

Continuando minha pesquisa, conheci o framework “cola” Pylons, na primeira vez fiquei impressionado, extremamente versátil e muito parecido com Rails, mas após alguns testes percebi que não tinha experiência o suficiente para usar essa ferramenta, acho que esse framework é para quem tem um conhecimento avançado em Python e não é meu caso.

Também testei o web2py, outro framework interessante e ágil para projetos pequenos, mas acho que a forma de trabalhar nele é muito estranha, você edita o código no próprio navegador como se fosse seu próprio IDE e assim por diante. Mas o que realmente me incomodou é que ele segue uma linha contrária do Python onde não existe importação de módulos como é de costume. E como tudo no Python é explícito e sem “mágicas”, deixei essa opção de lado e acabei voltando para o Django novamente usando o Admin.

A primeira coisa que recomendo antes de se aventurar a criar um sistema usando o Admin é, saiba bem como usar a Orientação a Objetos do Python e porque isso? No início tive a sensação do Admin ser aquele código “engessado” onde você fica amarrado e sem ter muito o que fazer. Mas com o tempo fui percebendo que você pode sobreescrever qualquer método da biblioteca padrão e customizar da maneira de achar necessário, vamos a um pequeno exemplo.

O sistema que estou criando, cada cliente possui seu sub-dominio e essa informação não pode ser editada como é por padrão, então imagine o seguinte trecho de código.

# models.py
class Cliente(models.Models):
    dominio = models.CharField(max_length=50)
    nome_fantasia = models.CharField(max_length=100)
    plano_acesso = models.ForeignKey('PlanoAcesso')

# forms.py
class ClienteAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ClienteAdminForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        if instance and instance.id:
            self.fields['dominio'].widget.attrs['readonly'] = True
            self.fields['dominio'].help_text = 'Acesso: http://%s.dominio.com.br:8090' % instance.dominio

# admin.py
class ClienteAdmin(admin.ModelAdmin):
    form = ClienteAdminForm
    fields = ('dominio','nome_fantasia',...,)
register.admin.site(Cliente, ClienteAdmin)

Observando bem o código, o que fiz ali foi sobreescrever o formulário padrão da classe ClienteAdmin pela classe ClienteAdminForm e no construtor dessa classe eu verifico se o objeto está no modo de edição e travo o campo domínio como “readonly”. Isso é apenas uma pequena amostra do que é possível fazer, o Django é flexível o suficiente de acordo com sua necessidade.

Outra coisa muito interessante é que podemos trabalhar com herança nos templates sem ter a necessidade de modificar o arquivo original do admin, basta criar um novo arquivo com o mesmo nome e herdar do padrão, por exemplo. Na minha lista de clientes, eu quero somar o total do valor dos planos de acessos.

Primeiro mudo o comportamento padrão do método changelist_view:

# admin.py
def changelist_view(self, request, extra_context={}):
   soma = PlanoAcesso.objects.all().aggregate(Sum('valor'))
   try:
      extra_context['soma'] = ("R$ %2.2f" % soma['valor__sum']).replace('.',',')
   except:
      extra_context['soma'] = "R$ 0,00"
   return super(ClienteAdmin, self).changelist_view(request, extra_context)

Para criar o template vamos supor que essa aplicação seja chamada de clientes, dentro dessa pasta crie outra pasta chamada templates e dentro dela outra chamada admin, novamente dentro da pasta admin crie a pasta clientes e dentro de clientes cria a última pasta cliente, achou confuso? :D

Nessa última pasta, crie o arquivo change_list.html com o seguinte conteúdo.

{% extends "admin/change_list.html" %}
{% block result_list %}
    {{ block.super }}
    Total: {{ soma }}
{% endblock result_list %}

Se você observar, temos a listagem original porque no html chamamos a variável {{ block.super }} para herdar do template original e logo abaixo nosso conteúdo customizável, muito legal não?

Para finalizar, acho que ficou claro que podemos usar sim o Admin para criação de sistemas complexos e customizá-lo ao máximo, basta saber usar a ferramenta corretamente e sem gambiarras.

ads
ads
ads
ads