=====================================
Escrevendo seu primeiro aplicativo com Django, parte 1
=====================================

By Adrian Holovaty <holovaty@gmail.com>
Traduzido por Elton Minetto <eminetto@gmail.com>

Vamos aprender usando um exemplo.

Atravs deste tutorial vamos demonstrar os passos necessrios para a criao 
de uma simples aplicao Web de uma pesquisa.

Ela vai consistir de duas partes:

* Um site pblico que ir permitir que usurios votem na pesquisa e vizualizem seus resultados.
* Um site administrativo que permitir voc adicionar, alterar e excluir pesquisas 

Vamos assumir que voc j tem o Django instalado.

Instalao do Django : http://www.djangoproject.com/documentation/install/

Configuraes iniciais
=============

Se esta  sua primeira vez usando o Django voc precisar realizar algumas tarefas de 
configurao inicial.

Execute o comando ``django-admin.py startproject myproject``. Isto ir criar um 
diretrio ``myproject`` em seu diretrio correte.

(``django-admin.py`` deve estar em seu path se voc instalou o Django usando
seu utilitrio setup.py. Se ele no est em seu path, voc pode encontr-lo em 
``site-packages/django/bin``; considere a criao de um link simblico para ele em
algum lugar de seu path, como /usr/local/bin.)

Um projeto  uma coleo de configuraes para uma instncia do Django -- incluindo
configurao da base de dados, opes especficas do Django e configuraes 
especficas das aplicaes. 
Vamos dar uma olhada no diretrio ``myproject`` criado::

    $ cd myproject/
    $ ls
    apps/  __init__.py  settings/
    $ ls settings/
    __init__.py  admin.py  main.py  urls/
    $ ls settings/urls/
    __init__.py  admin.py  main.py
    $ ls apps/
    __init__.py

Primeiro, edite o arquivo ``myproject/settings/main.py``. Ele  um mdulo Python normal
com algumas variveis em nvel de mdulo representando configuraes do Django. Edite o arquivo
e altere estas configuraes para refletirem os parmetros de sua conexo com a base de dados:

* ``DATABASE_ENGINE`` -- Escolha entre 'postgresql' or 'mysql'. Mais opes estaro disponveis em breve.
* ``DATABASE_NAME`` -- O nome de sua base de dados.
* ``DATABASE_USER`` -- Seu usurio da base de dados.
* ``DATABASE_PASSWORD`` -- Sua senha da base de dados.
* ``DATABASE_HOST`` -- O host onde sua base de dados est. Deixe este campo em branco no caso da sua base de
dados estar na mesma mquina fsica  (localhost).

(Tenha certeza de j ter criado a base de dados dentro do PostgreSQL ou MySQL neste ponto.
Faa isso com "``CREATE DATABASE database_name;``" dentro do prompt interativo de sua base de dados.)

Note que o suporte ao MySQL  um desenvolvimento recente e o Django ainda no foi
testado suficientemente com esta base de dados. Se voc encontrar algum bug nos
bindings do Django para MySQL, por favor notifique-os no `Django's ticket system`_ para que
possamos corrig-los imediatamente.

Agora, tome um segundo para garantir que ``myproject`` est em seu path do Python. Voc
pode fazer isso copiando ``myproject`` para o diretrio ``site-packages`` do Python, ou
pode tentar fazer isso alterando a varivel de ambiente ``PYTHONPATH``. Veja o 
`Python path documentation`_ para maiores informaes.

Execute o seguinte comando::

    django-admin.py init --settings=myproject.settings.main

O utilitrio ``django-admin.py`` geralmente precisa saber qual  o mdulo
de configuraes que voc est utilizando. Aqui estamos fazendo isso especificando 
``settings=`` na linha de comando, mas isto pode se tornar tedioso. Se voc no quer
digitar ``settings=`` toda vez voc pode configurar a varivel de ambiente 
``DJANGO_SETTINGS_MODULE``. Abaixo est como voc pode fazer isso no shell Bash no Unix:

    export DJANGO_SETTINGS_MODULE=myproject.settings.main

No Windows pode-se usar ``set``::

    set DJANGO_SETTINGS_MODULE=myproject.settings.main

Se voc no visualizar nenhum erro aps executar ``django-admin.py init``, significa
que est funcionando. Este comando inicializa sua base de dados com as tabelas
principais do Django. Se voc tiver interesse, execute o cliente em linha de comando 
do PostgreSQL ou MySQL e digite "\\dt" (PostgreSQL) ou "SHOW TABLES;" (MySQL) para mostrar
as tabelas.

Agora voc est pronto para iniciar o trabalho. Voc no precisar se preocupar 
com estas tarefas administrativas massantes novamente.

.. _`Python path documentation`: http://docs.python.org/tut/node8.html#SECTION008110000000000000000
.. _Django's ticket system: http://code.djangoproject.com/report/1


Criando modelos
===============

Mude para o diretrio ``myproject/apps`` e execute o seguinte comando::

    django-admin.py startapp polls

(De agora em diante, este tutorial vai abandonar o parametro ``--settings`` e assumir que voc
configurou a varivel de ambiente ``DJANGO_SETTINGS_MODULE`` ou incluiu a opo ``--settings``
na sua chamada do comando.)

Isto ir criar uma estrutura de diretrios como esta:::

    polls/
        __init__.py
        models/
            __init__.py
            polls.py
        urls/
            __init__.py
            polls.py
        views/
            __init__.py

Esta estrutura de diretrios ir hospedar sua aplicao de pesquisa.

O primeiro passo para escrever uma aplicao Web no Django  definir seus modelos
-- essencialmente, o layout da sua base de dados, com metadados adicionais..

:: Filosofia
   
   Um modelo  uma origem de dados simples e definitiva sobre seus dados.
   Ela contm os campos essenciais e os comportamentos dos dados que voc est
   armazenando. Django segue o `DRY Principle`_. O objetivo  definir seu modelo 
   de dados em um lugar e automaticamente derivar as coisas apartir disto.

Em nosso aplicativo simples de pesquisa ns iremos criar dois modelos: pesquisas (Poll) e 
escolhas (Choise).Uma pesquisa tem uma questo e uma data de publicao. Uma escolha tem dois 
campos:o texto da escolha e o registro dos votos. Cada escolha  associada a uma pesquisa.

Altere o arquivo ``polls/models/polls.py`` de forma que ele se parea com isto::

    from django.core import meta

    class Poll(meta.Model):
        fields = (
            meta.CharField('question', maxlength=200),
            meta.DateTimeField('pub_date', 'date published'),
        )

    class Choice(meta.Model):
        fields = (
            meta.ForeignKey(Poll),
            meta.CharField('choice', maxlength=200),
            meta.IntegerField('votes'),
        )

O cdigo  direto e auto-explicativo. Cada modelo  representado por uma classe
que  subclasse de ``django.core.meta.Model``. Cada modelo tem uma varivel 
de classe simples,``fields``, que  uma tupla dos campos da base de dados
no modelo.

Cada campo  representado por uma instncia da classe ``meta.*Field`` 
-- por exemplo ,``meta.CharField`` para campos caracter e ``meta.DateTimeField`` para
datetimes. Isto informa ao Django qual  o tipo de dado de cada campo.

O primeiro argumento de cada chamada ``Field``   o nome do campo, em um formato 
amigvel-para-maquina. Voc ir usar este valor em seu cdigo Python e sua base de 
dados ir usar isto como seu nome de coluna.

O segundo argumento, opcional,  o nome ``mais amigvel para humanos`` do campo.
Este  usado em algumas partes introspectivas do Django, e ajuda como documentao.
Se esta informao no  fornecida, Django ir usar o nome fornecido no primeiro 
parmetro. Neste exemplo ns apenas fornecemos esta informao para ``Poll.pub_date``.
Para todos os outros campos neste modelo o nome fornecido no primeiro parametro ser
utilizado.

Algumas classes ``meta.*Field`` possuem elementos adicionais requeridos.
``meta.CharField``, por exemplo, requer que voc fornea um ``maxlength``.
Isto ser usado no somente no esquema da base de dados, mas na validao, 
como veremos em breve.

Finalmente, note que um relacionamento  definido, usando ``meta.ForeignKey``. 
Isto informa ao Django que cada Choice  relacionada a uma nica Poll.
Django suporta todos os relacionamentos comuns em uma base de dados:
muitos-para-um, muitos-para-muios e um-para-um.

.. _DRY Principle: http://c2.com/cgi/wiki?DontRepeatYourself

Ativando modelos
=================

Cada pequena parte do cdigo do modelo fornece ao Django muita informao.
Com isto, Django  capaz de:

* Criar um esquema de base de dados (``CREATE TABLE`` statements) para cada aplicativo.
* Criar uma API Python para o acesso a base de dados, acessando os objetos Poll and Choice.

Mas primeiro precisamos informar ao nosso projeto que a aplicao ``polls`` est instalada.

:: Filosofia

   Aplicativos Django so "plugveis": Voc pode usar um aplicativo em mltiplos
   projetos e prode distribu-los, porque eles no esto amarrados a nenhuma 
   instalao do Django.

Altere o arquivo myproject/settings/main.py novamente, e troque a configurao ``INSTALLED_APPS``
para incluir a string "myproject.apps.polls". Ento, ele ficar parecido com isto::

    INSTALLED_APPS = (
        'myproject.apps.polls',
    )

(No se esquea da vrgula devido as regras do Python sobre tuplas com valor simples.)

Agora Django sabe que myproject inclui o aplicativo polls. Vamos executar outro comando::

    django-admin.py sql polls

Voc dever ver o seguinte (as clusulas SQL CREATE TABLE SQL para o aplicativo polls)::

    BEGIN;
    CREATE TABLE polls_polls (
        id serial NOT NULL PRIMARY KEY,
        question varchar(200) NOT NULL,
        pub_date timestamp with time zone NOT NULL
    );
    CREATE TABLE polls_choices (
        id serial NOT NULL PRIMARY KEY,
        poll_id integer NOT NULL REFERENCES polls_polls (id),
        choice varchar(200) NOT NULL,
        votes integer NOT NULL
    );
    COMMIT;

Note o seguinte:

* Nomes de tabelas so automaticamente gerados pela combinao do nome do aplicativo  (polls) 
  com o plural do nome do objeto (polls e choices). (Voc pode sobrepor este comportamento.)
* Chaves primrias (IDs) so adicionadas automaticamente. (Voc pode sobrepor isto tambm.)
* O relacionamento de chave estrangeira (foreign key)  feito explicitamente pela clusula ``REFERENCES``.
* Isto  amarrado a base de dados que esto usando, ento tipos de campos especficos das bases de
dados, como ``auto_increment`` (MySQL) vs. ``serial`` (PostgreSQL) so tratados para voc 
automaticamente. O autor deste tutorial usa PostgreSQL, ento a sada de exemplo  na 
sintaxe PostgreSQL.

Se voc est interessado tambm pode executar os seguintes comandos:

* ``django-admin.py sqlinitialdata polls`` -- Mostra as inseres de dados iniciais requeridos
  pelo framework de administrao do Django.
* ``django-admin.py sqlclear polls`` -- Mostra as clusulas ``DROP TABLE`` necessrias para este
  aplicativo, de acordo com as tabelas j existentes em sua base de dados (se existentes).
* ``django-admin.py sqlindexes polls`` -- Mostra as clusulas ``CREATE INDEX`` para este aplicativo.
* ``django-admin.py sqlall polls`` -- Uma combinao de 'sql' e 'sqlinitialdata'.

Olhando a sada destes comandos pode ajud-lo a entender o que realmente ocorre por baixo dos panos.

Agora execute o seguinte comando::

    django-admin.py install polls

Este comando automaticamente cria as tabelas da base de dados para o aplicativo polls.
Por trs das cenas, o que  feito  pegar a sada de ``django-admin.py sqlall polls`` 
e executar isto na base de dados apontada pelo seu arquivo de configuraes do Django.

Brincando com a API
====================

Agora abra o shell interativo do Python interactive shell, e iremos brincar com a API Python que 
Django lhe fornece::

    # Mdulos so dinamicamente criados dentro de django.models.
    # Seus nomes so plurais dos nomes das classes de modelo.
    >>> from django.models.polls import polls, choices

    # Nenhuma pesquisa est no sistema ainda.
    >>> polls.get_list()
    []

    # Cria uma nova Poll (pesquisa).
    >>> from datetime import datetime
    >>> p = polls.Poll(id=None, question="What's up?", pub_date=datetime.now())

    # Salva o objeto na base de dados. Voc precisa chamar save() explicitamente.
    >>> p.save()

    # Agora ela tem um ID.
    >>> p.id
    1

    # Acesse as colunas da base de dados atravz de atributos Python.
    >>> p.question
    "What's up?"
    >>> p.pub_date
    datetime.datetime(2005, 7, 15, 12, 00, 53)

    # Mude o valor mudando os atributos e ento chamando save().
    >>> p.pub_date = datetime(2005, 4, 1, 0, 0)
    >>> p.save()

    # get_list() mostra todas as pesquisas na base.
    >>> polls.get_list()
    [<Poll object>]

Espere um minuto. ``<Poll object>``  definitivamente uma representao pouco til deste objeto.
Vamos corrigir isto editando o modelo polls e adicionando um mtodo ``__repr__()`` 
para ambas, ``Poll`` e ``Choice``::

    class Poll(meta.Model):
        # ...
        def __repr__(self):
            return self.question

    class Choice(meta.Model):
        # ...
        def __repr__(self):
            return self.choice

 importante adicionar mtodos ``__repr__()`` em seus modelos, no somente para 
ajud-lo quando tratando com o prompt interativo, mas tambm porque as 
representaes dos objetos so usadas na interface administrativa gerada automaticamente
pelo Django.

Note que eles so mtodos Python normais. Vamos adicionar um mtodo customizado, apenas para demonstrao::

    class Poll(meta.Model):
        # ...
        def was_published_today(self):
            return self.pub_date.date() == datetime.date.today()

Note que ``import datetime`` no  necessrio. Cada mtodo do modelo tem acesso a um 
conjunto de variveis usados comumente para convenincia, incluindo o modulo 
``datetime`` da biblioteca padro do Python.

Vamos voltar ao shell interativo do Python::

    >>> from django.models.polls import polls, choices
    # Ter certeza que nossa adio do __repr__() funcionou.
    >>> polls.get_list()
    [What's up?]

    # Django fornece uma rica API para acesso a base de dados atravz de
    # argumentos chave.
    >>> polls.get_object(id__exact=1)
    What's up
    >>> polls.get_object(question__startswith='What')
    What's up
    >>> polls.get_object(pub_date__year=2005)
    What's up
    >>> polls.get_object(id__exact=2)
    Traceback (most recent call last):
        ...
    PollDoesNotExist: Poll does not exist for {'id__exact': 2}
    >>> polls.get_list(question__startswith='What')
    [What's up]

    # Testar se nosso mtodo customizado est funcionando.
    >>> p = polls.get_object(id__exact=1)
    >>> p.was_published_today()
    False

    # Dar a pesquisa algumas escolhas. Cada um destas chamadas de mtodo realiza uma
    # clusula INSERT por trás das cenas e retorna o novo objeto Choice.
    >>> p = polls.get_object(id__exact=1)
    >>> p.add_choice(choice='Not much', votes=0)
    Not much
    >>> p.add_choice(choice='The sky', votes=0)
    The sky
    >>> c = p.add_choice(choice='Just hacking again', votes=0)

    # Objetos Choice tem acesso via API ao objeto Poll relacionado.
    >>> c.get_poll()
    What's up

    # E vice versa: objetos Poll tem acesso aos objetos Choice.
    >>> p.get_choice_list()
    [Not much, The sky, Just hacking again]
    >>> p.get_choice_count()
    3

    # A API automaticamente segue os relacionamentos conforme necessrio.
    # Use duplos underscores para separar relacionamentos.
    # Isto funciona quantos nveis de profundidade voc quiser. No h limite.
    # Encontre todos os Choices para qualquer pesquisa onde a data de publicao est no ano 2005.
    >>> choices.get_list(poll__pub_date__year=2005)
    [Not much, The sky, Just hacking again]

    # Vamos excluir uma das escolhas. Usamos delete() para isso.
    >>> c = p.get_choice(choice__startswith='Just hacking')
    >>> c.delete()

Para detalhes completos sobre a API da base de dados, veja nossa `Database API reference`_.

Quando voc estiver confortvel com a API, leia a parte 2 deste tutorial para ter a interface de administrao
do Django funcionando.

.. _Database API reference: http://www.djangoproject.com/documentation/db_api/
.. _Parte 2 deste tutorial: http://www.djangoproject.com/documentation/tutorial2/
