1 | =====================================
|
---|
2 | Escrevendo seu primeiro aplicativo com Django, parte 1
|
---|
3 | =====================================
|
---|
4 |
|
---|
5 | By Adrian Holovaty <holovaty@gmail.com>
|
---|
6 | Traduzido por Elton Minetto <eminetto@gmail.com>
|
---|
7 |
|
---|
8 | Vamos aprender usando um exemplo.
|
---|
9 |
|
---|
10 | Através deste tutorial vamos demonstrar os passos necessários para a criação
|
---|
11 | de uma simples aplicação Web de uma pesquisa.
|
---|
12 |
|
---|
13 | Ela vai consistir de duas partes:
|
---|
14 |
|
---|
15 | * Um site público que irá permitir que usuários votem na pesquisa e vizualizem seus resultados.
|
---|
16 | * Um site administrativo que permitirá você adicionar, alterar e excluir pesquisas
|
---|
17 |
|
---|
18 | Vamos assumir que você já tem o Django instalado.
|
---|
19 |
|
---|
20 | Instalação do Django : http://www.djangoproject.com/documentation/install/
|
---|
21 |
|
---|
22 | Configurações iniciais
|
---|
23 | =============
|
---|
24 |
|
---|
25 | Se esta é sua primeira vez usando o Django você precisará realizar algumas tarefas de
|
---|
26 | configuração inicial.
|
---|
27 |
|
---|
28 | Execute o comando ``django-admin.py startproject myproject``. Isto irá criar um
|
---|
29 | diretório ``myproject`` em seu diretório correte.
|
---|
30 |
|
---|
31 | (``django-admin.py`` deve estar em seu path se você instalou o Django usando
|
---|
32 | seu utilitário setup.py. Se ele não está em seu path, você pode encontrá-lo em
|
---|
33 | ``site-packages/django/bin``; considere a criação de um link simbólico para ele em
|
---|
34 | algum lugar de seu path, como /usr/local/bin.)
|
---|
35 |
|
---|
36 | Um projeto é uma coleção de configurações para uma instância do Django -- incluindo
|
---|
37 | configuração da base de dados, opções específicas do Django e configurações
|
---|
38 | específicas das aplicações.
|
---|
39 | Vamos dar uma olhada no diretório ``myproject`` criado::
|
---|
40 |
|
---|
41 | $ cd myproject/
|
---|
42 | $ ls
|
---|
43 | apps/ __init__.py settings/
|
---|
44 | $ ls settings/
|
---|
45 | __init__.py admin.py main.py urls/
|
---|
46 | $ ls settings/urls/
|
---|
47 | __init__.py admin.py main.py
|
---|
48 | $ ls apps/
|
---|
49 | __init__.py
|
---|
50 |
|
---|
51 | Primeiro, edite o arquivo ``myproject/settings/main.py``. Ele é um módulo Python normal
|
---|
52 | com algumas variáveis em nível de módulo representando configurações do Django. Edite o arquivo
|
---|
53 | e altere estas configurações para refletirem os parâmetros de sua conexão com a base de dados:
|
---|
54 |
|
---|
55 | * ``DATABASE_ENGINE`` -- Escolha entre 'postgresql' or 'mysql'. Mais opções estarão disponíveis em breve.
|
---|
56 | * ``DATABASE_NAME`` -- O nome de sua base de dados.
|
---|
57 | * ``DATABASE_USER`` -- Seu usuário da base de dados.
|
---|
58 | * ``DATABASE_PASSWORD`` -- Sua senha da base de dados.
|
---|
59 | * ``DATABASE_HOST`` -- O host onde sua base de dados está. Deixe este campo em branco no caso da sua base de
|
---|
60 | dados estar na mesma máquina física (localhost).
|
---|
61 |
|
---|
62 | (Tenha certeza de já ter criado a base de dados dentro do PostgreSQL ou MySQL neste ponto.
|
---|
63 | Faça isso com "``CREATE DATABASE database_name;``" dentro do prompt interativo de sua base de dados.)
|
---|
64 |
|
---|
65 | Note que o suporte ao MySQL é um desenvolvimento recente e o Django ainda não foi
|
---|
66 | testado suficientemente com esta base de dados. Se você encontrar algum bug nos
|
---|
67 | bindings do Django para MySQL, por favor notifique-os no `Django's ticket system`_ para que
|
---|
68 | possamos corrigí-los imediatamente.
|
---|
69 |
|
---|
70 | Agora, tome um segundo para garantir que ``myproject`` está em seu path do Python. Você
|
---|
71 | pode fazer isso copiando ``myproject`` para o diretório ``site-packages`` do Python, ou
|
---|
72 | pode tentar fazer isso alterando a variável de ambiente ``PYTHONPATH``. Veja o
|
---|
73 | `Python path documentation`_ para maiores informações.
|
---|
74 |
|
---|
75 | Execute o seguinte comando::
|
---|
76 |
|
---|
77 | django-admin.py init --settings=myproject.settings.main
|
---|
78 |
|
---|
79 | O utilitário ``django-admin.py`` geralmente precisa saber qual é o módulo
|
---|
80 | de configurações que você está utilizando. Aqui estamos fazendo isso especificando
|
---|
81 | ``settings=`` na linha de comando, mas isto pode se tornar tedioso. Se você não quer
|
---|
82 | digitar ``settings=`` toda vez você pode configurar a variável de ambiente
|
---|
83 | ``DJANGO_SETTINGS_MODULE``. Abaixo está como você pode fazer isso no shell Bash no Unix:
|
---|
84 |
|
---|
85 | export DJANGO_SETTINGS_MODULE=myproject.settings.main
|
---|
86 |
|
---|
87 | No Windows pode-se usar ``set``::
|
---|
88 |
|
---|
89 | set DJANGO_SETTINGS_MODULE=myproject.settings.main
|
---|
90 |
|
---|
91 | Se você não visualizar nenhum erro após executar ``django-admin.py init``, significa
|
---|
92 | que está funcionando. Este comando inicializa sua base de dados com as tabelas
|
---|
93 | principais do Django. Se você tiver interesse, execute o cliente em linha de comando
|
---|
94 | do PostgreSQL ou MySQL e digite "\\dt" (PostgreSQL) ou "SHOW TABLES;" (MySQL) para mostrar
|
---|
95 | as tabelas.
|
---|
96 |
|
---|
97 | Agora você está pronto para iniciar o trabalho. Você não precisará se preocupar
|
---|
98 | com estas tarefas administrativas massantes novamente.
|
---|
99 |
|
---|
100 | .. _`Python path documentation`: http://docs.python.org/tut/node8.html#SECTION008110000000000000000
|
---|
101 | .. _Django's ticket system: http://code.djangoproject.com/report/1
|
---|
102 |
|
---|
103 |
|
---|
104 | Criando modelos
|
---|
105 | ===============
|
---|
106 |
|
---|
107 | Mude para o diretório ``myproject/apps`` e execute o seguinte comando::
|
---|
108 |
|
---|
109 | django-admin.py startapp polls
|
---|
110 |
|
---|
111 | (De agora em diante, este tutorial vai abandonar o parametro ``--settings`` e assumirá que você
|
---|
112 | configurou a variável de ambiente ``DJANGO_SETTINGS_MODULE`` ou incluiu a opção ``--settings``
|
---|
113 | na sua chamada do comando.)
|
---|
114 |
|
---|
115 | Isto irá criar uma estrutura de diretórios como esta:::
|
---|
116 |
|
---|
117 | polls/
|
---|
118 | __init__.py
|
---|
119 | models/
|
---|
120 | __init__.py
|
---|
121 | polls.py
|
---|
122 | urls/
|
---|
123 | __init__.py
|
---|
124 | polls.py
|
---|
125 | views/
|
---|
126 | __init__.py
|
---|
127 |
|
---|
128 | Esta estrutura de diretórios irá hospedar sua aplicação de pesquisa.
|
---|
129 |
|
---|
130 | O primeiro passo para escrever uma aplicação Web no Django é definir seus modelos
|
---|
131 | -- essencialmente, o layout da sua base de dados, com metadados adicionais..
|
---|
132 |
|
---|
133 | :: Filosofia
|
---|
134 |
|
---|
135 | Um modelo é uma origem de dados simples e definitiva sobre seus dados.
|
---|
136 | Ela contém os campos essenciais e os comportamentos dos dados que você está
|
---|
137 | armazenando. Django segue o `DRY Principle`_. O objetivo é definir seu modelo
|
---|
138 | de dados em um lugar e automaticamente derivar as coisas apartir disto.
|
---|
139 |
|
---|
140 | Em nosso aplicativo simples de pesquisa nós iremos criar dois modelos: pesquisas (Poll) e
|
---|
141 | escolhas (Choise).Uma pesquisa tem uma questão e uma data de publicação. Uma escolha tem dois
|
---|
142 | campos:o texto da escolha e o registro dos votos. Cada escolha é associada a uma pesquisa.
|
---|
143 |
|
---|
144 | Altere o arquivo ``polls/models/polls.py`` de forma que ele se pareça com isto::
|
---|
145 |
|
---|
146 | from django.core import meta
|
---|
147 |
|
---|
148 | class Poll(meta.Model):
|
---|
149 | fields = (
|
---|
150 | meta.CharField('question', maxlength=200),
|
---|
151 | meta.DateTimeField('pub_date', 'date published'),
|
---|
152 | )
|
---|
153 |
|
---|
154 | class Choice(meta.Model):
|
---|
155 | fields = (
|
---|
156 | meta.ForeignKey(Poll),
|
---|
157 | meta.CharField('choice', maxlength=200),
|
---|
158 | meta.IntegerField('votes'),
|
---|
159 | )
|
---|
160 |
|
---|
161 | O código é direto e auto-explicativo. Cada modelo é representado por uma classe
|
---|
162 | que é subclasse de ``django.core.meta.Model``. Cada modelo tem uma variável
|
---|
163 | de classe simples,``fields``, que é uma tupla dos campos da base de dados
|
---|
164 | no modelo.
|
---|
165 |
|
---|
166 | Cada campo é representado por uma instância da classe ``meta.*Field``
|
---|
167 | -- por exemplo ,``meta.CharField`` para campos caracter e ``meta.DateTimeField`` para
|
---|
168 | datetimes. Isto informa ao Django qual é o tipo de dado de cada campo.
|
---|
169 |
|
---|
170 | O primeiro argumento de cada chamada ``Field`` é o nome do campo, em um formato
|
---|
171 | amigável-para-maquina. Você irá usar este valor em seu código Python e sua base de
|
---|
172 | dados irá usar isto como seu nome de coluna.
|
---|
173 |
|
---|
174 | O segundo argumento, opcional, é o nome ``mais amigável para humanos`` do campo.
|
---|
175 | Este é usado em algumas partes introspectivas do Django, e ajuda como documentação.
|
---|
176 | Se esta informação não é fornecida, Django irá usar o nome fornecido no primeiro
|
---|
177 | parâmetro. Neste exemplo nós apenas fornecemos esta informação para ``Poll.pub_date``.
|
---|
178 | Para todos os outros campos neste modelo o nome fornecido no primeiro parametro será
|
---|
179 | utilizado.
|
---|
180 |
|
---|
181 | Algumas classes ``meta.*Field`` possuem elementos adicionais requeridos.
|
---|
182 | ``meta.CharField``, por exemplo, requer que você forneça um ``maxlength``.
|
---|
183 | Isto será usado não somente no esquema da base de dados, mas na validação,
|
---|
184 | como veremos em breve.
|
---|
185 |
|
---|
186 | Finalmente, note que um relacionamento é definido, usando ``meta.ForeignKey``.
|
---|
187 | Isto informa ao Django que cada Choice é relacionada a uma única Poll.
|
---|
188 | Django suporta todos os relacionamentos comuns em uma base de dados:
|
---|
189 | muitos-para-um, muitos-para-muios e um-para-um.
|
---|
190 |
|
---|
191 | .. _DRY Principle: http://c2.com/cgi/wiki?DontRepeatYourself
|
---|
192 |
|
---|
193 | Ativando modelos
|
---|
194 | =================
|
---|
195 |
|
---|
196 | Cada pequena parte do código do modelo fornece ao Django muita informação.
|
---|
197 | Com isto, Django é capaz de:
|
---|
198 |
|
---|
199 | * Criar um esquema de base de dados (``CREATE TABLE`` statements) para cada aplicativo.
|
---|
200 | * Criar uma API Python para o acesso a base de dados, acessando os objetos Poll and Choice.
|
---|
201 |
|
---|
202 | Mas primeiro precisamos informar ao nosso projeto que a aplicação ``polls`` está instalada.
|
---|
203 |
|
---|
204 | :: Filosofia
|
---|
205 |
|
---|
206 | Aplicativos Django são "plugáveis": Você pode usar um aplicativo em múltiplos
|
---|
207 | projetos e prode distribuí-los, porque eles não estão amarrados a nenhuma
|
---|
208 | instalação do Django.
|
---|
209 |
|
---|
210 | Altere o arquivo myproject/settings/main.py novamente, e troque a configuração ``INSTALLED_APPS``
|
---|
211 | para incluir a string "myproject.apps.polls". Então, ele ficará parecido com isto::
|
---|
212 |
|
---|
213 | INSTALLED_APPS = (
|
---|
214 | 'myproject.apps.polls',
|
---|
215 | )
|
---|
216 |
|
---|
217 | (Não se esqueça da vírgula devido as regras do Python sobre tuplas com valor simples.)
|
---|
218 |
|
---|
219 | Agora Django sabe que myproject inclui o aplicativo polls. Vamos executar outro comando::
|
---|
220 |
|
---|
221 | django-admin.py sql polls
|
---|
222 |
|
---|
223 | Você deverá ver o seguinte (as cláusulas SQL CREATE TABLE SQL para o aplicativo polls)::
|
---|
224 |
|
---|
225 | BEGIN;
|
---|
226 | CREATE TABLE polls_polls (
|
---|
227 | id serial NOT NULL PRIMARY KEY,
|
---|
228 | question varchar(200) NOT NULL,
|
---|
229 | pub_date timestamp with time zone NOT NULL
|
---|
230 | );
|
---|
231 | CREATE TABLE polls_choices (
|
---|
232 | id serial NOT NULL PRIMARY KEY,
|
---|
233 | poll_id integer NOT NULL REFERENCES polls_polls (id),
|
---|
234 | choice varchar(200) NOT NULL,
|
---|
235 | votes integer NOT NULL
|
---|
236 | );
|
---|
237 | COMMIT;
|
---|
238 |
|
---|
239 | Note o seguinte:
|
---|
240 |
|
---|
241 | * Nomes de tabelas são automaticamente gerados pela combinação do nome do aplicativo (polls)
|
---|
242 | com o plural do nome do objeto (polls e choices). (Você pode sobrepor este comportamento.)
|
---|
243 | * Chaves primárias (IDs) são adicionadas automaticamente. (Você pode sobrepor isto também.)
|
---|
244 | * O relacionamento de chave estrangeira (foreign key) é feito explicitamente pela cláusula ``REFERENCES``.
|
---|
245 | * Isto é amarrado a base de dados que estão usando, então tipos de campos específicos das bases de
|
---|
246 | dados, como ``auto_increment`` (MySQL) vs. ``serial`` (PostgreSQL) são tratados para você
|
---|
247 | automaticamente. O autor deste tutorial usa PostgreSQL, então a saída de exemplo é na
|
---|
248 | sintaxe PostgreSQL.
|
---|
249 |
|
---|
250 | Se você está interessado também pode executar os seguintes comandos:
|
---|
251 |
|
---|
252 | * ``django-admin.py sqlinitialdata polls`` -- Mostra as inserções de dados iniciais requeridos
|
---|
253 | pelo framework de administração do Django.
|
---|
254 | * ``django-admin.py sqlclear polls`` -- Mostra as cláusulas ``DROP TABLE`` necessárias para este
|
---|
255 | aplicativo, de acordo com as tabelas já existentes em sua base de dados (se existentes).
|
---|
256 | * ``django-admin.py sqlindexes polls`` -- Mostra as cláusulas ``CREATE INDEX`` para este aplicativo.
|
---|
257 | * ``django-admin.py sqlall polls`` -- Uma combinação de 'sql' e 'sqlinitialdata'.
|
---|
258 |
|
---|
259 | Olhando a saída destes comandos pode ajudá-lo a entender o que realmente ocorre por baixo dos panos.
|
---|
260 |
|
---|
261 | Agora execute o seguinte comando::
|
---|
262 |
|
---|
263 | django-admin.py install polls
|
---|
264 |
|
---|
265 | Este comando automaticamente cria as tabelas da base de dados para o aplicativo polls.
|
---|
266 | Por trás das cenas, o que é feito é pegar a saída de ``django-admin.py sqlall polls``
|
---|
267 | e executar isto na base de dados apontada pelo seu arquivo de configurações do Django.
|
---|
268 |
|
---|
269 | Brincando com a API
|
---|
270 | ====================
|
---|
271 |
|
---|
272 | Agora abra o shell interativo do Python interactive shell, e iremos brincar com a API Python que
|
---|
273 | Django lhe fornece::
|
---|
274 |
|
---|
275 | # Módulos são dinamicamente criados dentro de django.models.
|
---|
276 | # Seus nomes são plurais dos nomes das classes de modelo.
|
---|
277 | >>> from django.models.polls import polls, choices
|
---|
278 |
|
---|
279 | # Nenhuma pesquisa está no sistema ainda.
|
---|
280 | >>> polls.get_list()
|
---|
281 | []
|
---|
282 |
|
---|
283 | # Cria uma nova Poll (pesquisa).
|
---|
284 | >>> from datetime import datetime
|
---|
285 | >>> p = polls.Poll(id=None, question="What's up?", pub_date=datetime.now())
|
---|
286 |
|
---|
287 | # Salva o objeto na base de dados. Você precisa chamar save() explicitamente.
|
---|
288 | >>> p.save()
|
---|
289 |
|
---|
290 | # Agora ela tem um ID.
|
---|
291 | >>> p.id
|
---|
292 | 1
|
---|
293 |
|
---|
294 | # Acesse as colunas da base de dados atravéz de atributos Python.
|
---|
295 | >>> p.question
|
---|
296 | "What's up?"
|
---|
297 | >>> p.pub_date
|
---|
298 | datetime.datetime(2005, 7, 15, 12, 00, 53)
|
---|
299 |
|
---|
300 | # Mude o valor mudando os atributos e então chamando save().
|
---|
301 | >>> p.pub_date = datetime(2005, 4, 1, 0, 0)
|
---|
302 | >>> p.save()
|
---|
303 |
|
---|
304 | # get_list() mostra todas as pesquisas na base.
|
---|
305 | >>> polls.get_list()
|
---|
306 | [<Poll object>]
|
---|
307 |
|
---|
308 | Espere um minuto. ``<Poll object>`` É definitivamente uma representação pouco útil deste objeto.
|
---|
309 | Vamos corrigir isto editando o modelo polls e adicionando um método ``__repr__()``
|
---|
310 | para ambas, ``Poll`` e ``Choice``::
|
---|
311 |
|
---|
312 | class Poll(meta.Model):
|
---|
313 | # ...
|
---|
314 | def __repr__(self):
|
---|
315 | return self.question
|
---|
316 |
|
---|
317 | class Choice(meta.Model):
|
---|
318 | # ...
|
---|
319 | def __repr__(self):
|
---|
320 | return self.choice
|
---|
321 |
|
---|
322 | É importante adicionar métodos ``__repr__()`` em seus modelos, não somente para
|
---|
323 | ajudá-lo quando tratando com o prompt interativo, mas também porque as
|
---|
324 | representações dos objetos são usadas na interface administrativa gerada automaticamente
|
---|
325 | pelo Django.
|
---|
326 |
|
---|
327 | Note que eles são métodos Python normais. Vamos adicionar um método customizado, apenas para demonstração::
|
---|
328 |
|
---|
329 | class Poll(meta.Model):
|
---|
330 | # ...
|
---|
331 | def was_published_today(self):
|
---|
332 | return self.pub_date.date() == datetime.date.today()
|
---|
333 |
|
---|
334 | Note que ``import datetime`` não é necessário. Cada método do modelo tem acesso a um
|
---|
335 | conjunto de variáveis usados comumente para conveniência, incluindo o modulo
|
---|
336 | ``datetime`` da biblioteca padrão do Python.
|
---|
337 |
|
---|
338 | Vamos voltar ao shell interativo do Python::
|
---|
339 |
|
---|
340 | >>> from django.models.polls import polls, choices
|
---|
341 | # Ter certeza que nossa adição do __repr__() funcionou.
|
---|
342 | >>> polls.get_list()
|
---|
343 | [What's up?]
|
---|
344 |
|
---|
345 | # Django fornece uma rica API para acesso a base de dados atravéz de
|
---|
346 | # argumentos chave.
|
---|
347 | >>> polls.get_object(id__exact=1)
|
---|
348 | What's up
|
---|
349 | >>> polls.get_object(question__startswith='What')
|
---|
350 | What's up
|
---|
351 | >>> polls.get_object(pub_date__year=2005)
|
---|
352 | What's up
|
---|
353 | >>> polls.get_object(id__exact=2)
|
---|
354 | Traceback (most recent call last):
|
---|
355 | ...
|
---|
356 | PollDoesNotExist: Poll does not exist for {'id__exact': 2}
|
---|
357 | >>> polls.get_list(question__startswith='What')
|
---|
358 | [What's up]
|
---|
359 |
|
---|
360 | # Testar se nosso método customizado está funcionando.
|
---|
361 | >>> p = polls.get_object(id__exact=1)
|
---|
362 | >>> p.was_published_today()
|
---|
363 | False
|
---|
364 |
|
---|
365 | # Dar a pesquisa algumas escolhas. Cada um destas chamadas de método realiza uma
|
---|
366 | # cláusula INSERT por trás das cenas e retorna o novo objeto Choice.
|
---|
367 | >>> p = polls.get_object(id__exact=1)
|
---|
368 | >>> p.add_choice(choice='Not much', votes=0)
|
---|
369 | Not much
|
---|
370 | >>> p.add_choice(choice='The sky', votes=0)
|
---|
371 | The sky
|
---|
372 | >>> c = p.add_choice(choice='Just hacking again', votes=0)
|
---|
373 |
|
---|
374 | # Objetos Choice tem acesso via API ao objeto Poll relacionado.
|
---|
375 | >>> c.get_poll()
|
---|
376 | What's up
|
---|
377 |
|
---|
378 | # E vice versa: objetos Poll tem acesso aos objetos Choice.
|
---|
379 | >>> p.get_choice_list()
|
---|
380 | [Not much, The sky, Just hacking again]
|
---|
381 | >>> p.get_choice_count()
|
---|
382 | 3
|
---|
383 |
|
---|
384 | # A API automaticamente segue os relacionamentos conforme necessário.
|
---|
385 | # Use duplos underscores para separar relacionamentos.
|
---|
386 | # Isto funciona quantos níveis de profundidade você quiser. Não há limite.
|
---|
387 | # Encontre todos os Choices para qualquer pesquisa onde a data de publicação está no ano 2005.
|
---|
388 | >>> choices.get_list(poll__pub_date__year=2005)
|
---|
389 | [Not much, The sky, Just hacking again]
|
---|
390 |
|
---|
391 | # Vamos excluir uma das escolhas. Usamos delete() para isso.
|
---|
392 | >>> c = p.get_choice(choice__startswith='Just hacking')
|
---|
393 | >>> c.delete()
|
---|
394 |
|
---|
395 | Para detalhes completos sobre a API da base de dados, veja nossa `Database API reference`_.
|
---|
396 |
|
---|
397 | Quando você estiver confortável com a API, leia a parte 2 deste tutorial para ter a interface de administração
|
---|
398 | do Django funcionando.
|
---|
399 |
|
---|
400 | .. _Database API reference: http://www.djangoproject.com/documentation/db_api/
|
---|
401 | .. _Parte 2 deste tutorial: http://www.djangoproject.com/documentation/tutorial2/
|
---|