Quem sou eu

Minha foto

Formado em Computação, desenvolvedor web, interessado em tecnologia, metaleiro e um gamer inveterado.

Pesquisar

sexta-feira, 16 de janeiro de 2009

Parte 3 - Criação da primeira APP

Dentro da pasta do projeto iremos criar a primeira aplicação deste projeto. Começarei por CD. Navegue até a pasta do projetop via prompt e execute o comando:

python manage.py startapp cd

Este comando irá criar uma pasta com 3 arquivos:

  • __init__.py
  • models.py
    Neste arquivo será colocado todos os modelos da aplicaçã
  • views.py
    Aqui ficam as views que utilizaremos no front. Voltaremos a falar delas mais a frente.

Por hora abra o models.py.

Acima da importação do pacote models, coloque a codificação a ser utilizada:

# -*- coding: utf-8 -*-
from django.db import models


Deixando tudo em UTF-8, problemas de acentuação tanto no banco quanto nos templates serão evitados.
Mantenha essa string sempre na primeira linha de todos os models.py e views.py.


CRIANDO O PRIMEIRO MODELO


Nesta aplicação, defini que os cds serão divididos por categoria, intérprete e conterão algumas informações espefíficas do album tais como: foto, ano e faixas. Vamos ao código:




A classe categoria:

class Categoria(models.Model):

nome = models.CharField(max_length=100)
slug = models.SlugField(max_length=100)

class Meta:

ordering = ['nome']

def __unicode__(self):

return self.nome



A classe categoria herda as propriedades da classe Model, por isso o import nas primeiras linhas.

Os atributos:

nome = models.CharField(max_length=100)
slug = models.SlugField(max_length=100)


Ambos serão renderizados como um INPUT TEXT no admin, porém o campo slug gera uma melhor indexação no banco, além de ser o grande responsável pelas urls elegantes que criaremos para as views.
Em ambos os casos o parâmetro max_length é obrigatório.

O campo slug será utlizado de forma a identificar um registro nos banco de forma única no banco, e será preenchido de uma forma interessante quando chegarmos na administração desse modelo.

A classe Meta, que está definida dentro de da classe recém criada possui muitos recursos interessantes. Para categoria, estou utilizando apenas a ordenação padrão quando os objetos da mesma forem listados:

ordering = ['nome']

Com o ordering posso colocar a ordenação por quaisquer atributos pertencentes a minha classe, e utilizar o sinal "-" (menos) para ordenação decrescente, como por exemplo:

ordering = ['-id']


O método __unicode__ é o responsável por retornar uma string contendo o conteudo de qualquer campo da instância do objeto em questão. Caso ele não esteja defindo, ocorre a seguinte diferença para um objeto c pertencente a esta classe:

c - retornaria: OBJECT
c.nome - retornaria o valor do atributo nome

Já com o __unicode__, ambos os casos retornariam diretamente o valor, o que poupa trabalho.





A classe Interprete:

class Interprete(models.Model):

nome = models.CharField(max_length=100)
slug = models.SlugField(max_length=100)

def __unicode__(self):

return self.nome



class Meta:

ordering = ['-id']
verbose_name = u'Intérprete'
verbose_name_plural = u'Intérpretes'



Aqui temos dois novos recursos da classe meta. É possivel setar qual será o nome no singular e no plural através do verbose_name, de forma a deixar correto (com acento) no admin.




A classe Album:

class Album(models.Model):


categoria = models.ForeignKey(Categoria)
interprete = models.ForeignKey(Interprete)
titulo = models.CharField(max_length=255,verbose_name=u'Título')
cover = models.ImageField(upload_to='albuns/%Y/', null=True, blank=True)
ano = models.IntegerField()
slug = models.SlugField(max_length=255)

def __unicode__(self):

return self.titulo


class Meta:

ordering = ['-id']
verbose_name = u'Album'
verbose_name_plural = u'Albuns'




Aqui temos algumas novidades em relação as anteriores:

- É possivel utilizar o verbose_name para atributos de forma a corrigir o nome mostrado no admin, conforme visto no título;

- Para nomes com acentos, se faz necessário colocar a letra "u" antes da string com o mesmo, para ficar correto com a codificação;

- um campo do tipo Imagem para fazer o upload da capa do álbum. O parâmetro upload_to é obrigatório e deve ser a string do caminho onde ficarão as imagens. Também é possivel organizar os uploads por datas. Neste exemplo, será gerada a pasta albuns dentro do media, e dentro dela, uma pasta com o ano que fez o upload defindo pelo caracter "%Y". Observação: o ano do álbum não está relacionado com o caminho do upload;

- Para o campo cover, temos dois parâmetros opcionais que permitem ao usuário criar um álbum sem a necessidade de preencher este campo. Colocando ambos campos em um atributo, o django exclui o mesmo da validação automática.

- Temos duas chaves estrangeiras para a classe album: categoria e interprete. Previmente definidos;


- E por fim, o campo do tipo inteiro ano, que também será renderizado como um INPUT TEXT no admin.




A classe Faixa:

class Faixa(models.Model):

album = models.ForeignKey(Album)
nro = models.IntegerField(verbose_name = u'Número')
nome = models.CharField(max_length=200)
tempo = models.CharField(max_length=10, help_text='Formato MM:SS',blank=True,null=True)

def __unicode__(self):

return self.nome




A novidade na classe faixa é uma dica dada ao usuário sobre o correto preenchimento para um campo na administração. Utilizando o atributo opcional help_text, a mensagem desejada aparece ao lado do campo escolhido.


CRIANDO O ADMIN PARA O MODELO

Crie dentro da pasta da sua aplicação um arquivo com o nome de admin.py. Dentro dele precisaremos de dois imports:

from django.contrib import admin
from app.cd.models import *

O primeiro para as funcionalidades do admin em si, e o segundo para as informações do modelo criado.

Logo abaixo, será criado as classes do administrativo:





O admin de Categoria:

class CategoriaAdmin(admin.ModelAdmin):

search_fields = ('nome',)
list_display = ('nome',)
prepopulated_fields = {'slug': ('nome',)}
save_on_top = True



search_fields - recebe uma tupla com os campos em que será realizada uma busca por quaisquer ocorrências do que for digitado.

list_display - recebe uma tupla com os campos que aparecerão na listagem

prepopulated_fields - aqui um recurso interssante do django para o campo slug. O preenchimento automático do campo slug com o texto do quer for inserido no campo nome, com excessão de algumas palavras reservadas, espaços e acentuação.

save_on_top - útil para formulários grandes. Esta opção replica a barra de controle para salvar/apagar registros acima do form.




O admin de Interprete:


class InterpreteAdmin(admin.ModelAdmin):

search_fields = ('nome',)
list_display = ('nome',)
prepopulated_fields = {'slug': ('nome',)}
save_on_top = True


Vamos utilizar um recurso muito interessante para as duas classes que faltam. Imagine se tivesse que inserir primeiro álbum com todas as informações, depois ir até o administrativo de faixas para inserir uma a uma tendo que escolher o álbum. Trabalhoso demais. O Django possui uma solução para isso.

É possível utilizar um recurso chamado INLINE, para adicionar uma ou várias faixas durante a inserção do álbum. Vejamos como:




O admin inline de Faixa:

class FaixasInline(admin.TabularInline):

model = Faixa
extra = 15


Esta classe herda de uma classe diferente das outras extamente por possuir esse recurso. Apenas precisamos definir a qual modelo ela se refere:

model = Faixa


E a quantidade de itens que serão exibidas além dos preenchidos:

extra = 15




O admin de Album:

class AlbumAdmin(admin.ModelAdmin):

inlines = [

FaixasInline,

]
raw_id_fields = ('categoria','interprete',)
search_fields = ('titulo',)
list_display = ('titulo','interprete','categoria','ano')
list_filter = ['categoria']
prepopulated_fields = {'slug': ('titulo',)}
save_on_top = True


Novidades desta classe:

- Nesta classe, é definido que será utilizado a classe FaixasInline criada anteriormente

- Como provavelmente teremos muitos artistas e categorias, procurá-los em um campo do tipo SELECT (tipo renderizado pelos campos ForeignKey) seria um tanto trabalhoso. Com a opção raw_id_fields, é aberto uma nova janela com a listagem definida pela referência a chave estrangeira, de forma a utilizar todas as buscas, filtros e ordenação providas pelo admin da mesma.

- list_filter - gera um filtro para facilitar a busca de um registro. O filtro só é exibido quando esta classe possuir registros pertencentes a mais de uma classe do filtro.




O admin de Faixa:

class FaixaAdmin(admin.ModelAdmin):

search_fields = ('nome',)
list_display = ('nome','album','nro','tempo')
save_on_top = True




Para concluir o admin.py, registre os admins criados ao final do arquivo:


admin.site.register(Categoria, CategoriaAdmin)
admin.site.register(Interprete, InterpreteAdmin)
admin.site.register(Album, AlbumAdmin)
admin.site.register(Faixa, FaixaAdmin)



TESTES


Adicone dentro do INSTALLED_APPS no settings.py a aplicação criada.


INSTALLED_APPS = (

'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
'app.cd',


)



Pare o servidor local de testes caso esteja rodando e execute um syncdb para gerar as tabelas.
Inicie novamente o servidor de testes com o runserver e abra o admin do seu projeto no link:

http://localhost:8000/admin/

Faça o login e veja o foi criado.