Back-End

3 jun, 2013

O “objeto” models de um app

Publicidade

Em um artigo anterior eu falei de forma geral sobre os “objetos” do Django e um deles é o models. Como prometido, irei falar sobre cada “objeto” individualmente e trarei algumas dicas sobre cada um deles.

Nesse artigo irei tratar do “objeto” models.py, que na minha maneira de entender o Django é o elemento mais importante de todos, pois os outros dependem diretamente dele, e sem esse não poderemos criar nossa estrutura de persistência. No models de cada app definimos as classes e os tipos de dados que iremos tratar na app. Para exemplificar de forma bem didática, iremos imaginar que nossa app tratará informações sobre clientes, seus dados de endereço e seus perfis nas redes sociais.

from django.db import models

class Cliente(models.Model):
    """docstring for Cliente"""
    CHOICES_SEXO = (('M', 'Masculino'), ('F', 'Feminino'))
    nome = models.CharField(max_length=30)
    sobrenome = models.CharField(max_length=30)
    sexo = models.CharField(u'Sexo', max_length=1, choices=CHOICES_SEXO)
    nascimento = models.DateField(u'Data de nascimento')

class Social(models.Model):
    """docstring for Social"""
    cliente = models.ForeignKey(Cliente, verbose_name=u'Cliente')
    rede_social = models.ForeignKey('RedeSocial', vernose_name='Rede Social')
    email = models.CharField(u'Login', max_length=50)

class DadosContato(models.Model):
    """docstring for DadosContato"""
    cliente = models.ForeignKey(Cliente)
    logradouro = models.CharField(u'Logradouro', max_length=100)
    cidade = models.CharField(u'Cidade', max_length=50)
    email = models.EmailField(u'Email de contato', null=True, blank=True)                

class RedeSocial(models.Model):
    """docstring for RedeSocial"""
    titulo = models.CharField(u'Nome da rede social', max_length=100)
    url = models.URLField(u'Endereço da rede social')

Explicação: antes de qualquer coisa, informo que codifiquei dessa forma para poder dar o máximo de exemplos possíveis sobre os tipos de dados que temos disponíveis.

A estrutura é bem simples e temos as classes do model herdado por padrão do models.Model, logo em seguida temos o comentário, docstring, e as declarações do atributos das nossas classes. Aqui tem um detalhe bem importante, pois dependendo da escolha do tipo do campo, poderemos ter benefícios ou grandes problemas. Percebam que não declarei um campo para chave primária, assim o Django cria “automaticamente” um campo identificador para cada uma das classes.

As atributos do tipo models.CharField são campos para tratar informação do tipo texto simples e possuem um parâmetro obrigatório na definição, que é o max_length. Esse parâmetro determina a quantidade de caracteres que teremos armazenada nesse atributo e esse valor é utilizado tanto na criação do campo na tabela do banco de dados, como para validar os dados no template.

Os atributos do tipo models.URLField e models.EmailField são tipos textos especiais, pois quando o usuário está trabalhando a informação no template, o Django faz uma validação para esses campos, mas no banco de dados são tipos varchar normais, o campo URLField deve ser utilizado quando precisamos tratar uma URL, e o tipo EmailField deve ser utilizado quando precisarmos tratar um dado do tipo e-mail.

Já os atributos do tipo models.ForeignKey são utilizados para realizar a “ligação” entre as classe, e aqui entra o conceito de relacionamento entre classe. Esse campo para o Django é do tipo Integer e faz internamente uma referência à classe que especificarmos como primeiro parâmetro do atributo. Veja que nas classes Social e DadosContato eu tenho atributos do tipo ForeignKey que fazem referência à Cliente e RedeSocial.

Esse atributos, quando exibidos nos templates do Admin, são transformados em campos do tipo select do HTML e trazem nos options valores das classes as quais fazem referência. No nosso exemplo, o campo cliente da classe Social, será mostrado como um select e trará por padrão os valores Cliente objects – nesse ponto temos um pequeno “problema”, que é como identificar qual cliente, pois todos os valores serão no padrão NomeClasse objects. Isso ocorre até que configuremos o método def __unicode__(self): esse método é o responsável por retornar um valor, determinado por nós, para todos os momentos em que o Django fizer referência à nossa classe, seja num relacionamento ou mesmo nas mensagens enviadas aos usuários do sistema.

Aplicando o método Unicode na classe Cliente:

class Cliente(models.Model):
    """docstring for Cliente"""
    CHOICES_SEXO = (('M', 'Masculino'), ('F', 'Feminino'))
    nome = models.CharField(max_length=30)
    sobrenome = models.CharField(max_length=30)
    sexo = models.CharField(u'Sexo', max_length=1, choices=CHOICES_SEXO)
    nascimento = models.DateField(u'Data de nascimento')

    def __unicode__(self):
        return u'%s' % (self.nome)

Percebam que o método deve ser bem simples, pois os valores que colocarmos nele serão mostrados nos campos ForeignKey das classes que o referenciam. A partir do momento que configuramos nosso método, o atributo cliente das classes Social e DadosContato não mostraram mais o valor Cliente objects e sim o nome de cada cliente, que foi o campo que configuramos para retornar.

Uma coisa que muitas pessoas que estão começando no Django não fazem, e é de muita importância, principalmente pelo conceito de orientação à objeto, é trabalhar com os método no models. Imaginem que precisamos, num determinado momento da nossa aplicação, exibir o nome do cliente, trazendo primeiro o último nome e depois o primeiro nome. Para resolver esse problema criaremos um método dentro da classe Cliente no models mesmo, e assim depois poderemos utilizar em qualquer instância da classe Cliente. A criação de um método segue a mesma estrutura do método __unicode__, ficando assim nossa classe Cliente.

class Cliente(models.Model):
    """docstring for Cliente"""
    CHOICES_SEXO = (('M', 'Masculino'), ('F', 'Feminino'))
    nome = models.CharField(max_length=30)
    sobrenome = models.CharField(max_length=30)
    sexo = models.CharField(u'Sexo', max_length=1, choices=CHOICES_SEXO)
    nascimento = models.DateField(u'Data de nascimento')

    def __unicode__(self):
        return u'%s' % (self.nome)

    def retornar_sobrenome_nome(self):
        return u'%s %s' % (self.sobrenome, self.nome)

    retornar_sobrenome_nome.short_description = u'Nome curto do nosso método'

Esse novo método da classe cliente pode ser utilizado nos demais elementos da nossa aplicação, tipo num list_display do nosso admin, como também numa views. É muito importante que nós fiquemos atentos nesse ponto.

Por fim, falarei da classe Meta, que também deve ser configurada, apesar de ser opcional, pois assim poderemos determinar como irão aparecer os nomes das nossas classes no template do admin. E mais uma vez a configuração é bem simples, ficando assim nossa classe Cliente.

class Cliente(models.Model):
    """docstring for Cliente"""
    CHOICES_SEXO = (('M', 'Masculino'), ('F', 'Feminino'))
    nome = models.CharField(max_length=30)
    sobrenome = models.CharField(max_length=30)
    sexo = models.CharField(u'Sexo', max_length=1, choices=CHOICES_SEXO)
    nascimento = models.DateField(u'Data de nascimento')

    def __unicode__(self):
        return u'%s' % (self.nome)

    def retornar_sobrenome_nome(self):
        return u'%s %s' % (self.sobrenome, self.nome)

    retornar_sobrenome_nome.short_description = u'Nome curto do nosso método'

    class Meta:
        verbose_name = u'Nome da nossa classe no singular'
        verbose_name_plural = u'Noome da nossa classe no plural'

Para não deixar o artigo ainda maior, preferi apenas disponibilizar o link para os tipos de campos possíveis de serem utilizados em nossos models: http://goo.gl/dHRCe