Microtutoriais A

De Pontão Nós Digitais
Revisão de 12h04min de 18 de setembro de 2011 por Rfabbri (discussão | contribs) (→‎Django12: Generic Views)
(dif) ← Edição anterior | Revisão atual (dif) | Versão posterior → (dif)
Ir para navegaçãoIr para pesquisar

Django1: Baixar e rodar em 3 comandos

Simplesme baixe o tar.gz do site e rode

   $ sudo python setup.py install

depois vá para um dir.. dê um

   $ python django-admin.py startproject mysite

inicie o servidor (entra no diretório do projeto)

   $ python manage.py runserver

pronto! só ir no endereço que o terminal soltou

Django2: Fazendo o bixinho acessar um BD.

   $ python manage.py syncdb

dá pau até que vc arrume o

   DATABASES = { 'default' :

do settings.py

Pode usar sqlite que fica imediato, mas eu arrumei um user mysql rapidinho.

Rode:

   $ python manage.py syncdb

Até que não sintamos nada de mais pegando.


Django3: Suas tabelas de BD são classes

Crie um app:

   $ python manage.py startapp appzinhoCoxa

Coloque 'sitezinhoCoxa' no final da tupla INSTALLED_APPS do settings.py,

Crie estas duas classes no seu appzinhoCoxa/models.py:

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice = models.CharField(max_length=200)
    votes = models.IntegerField()

Relaxa, vai dar certo. Só falta rodar este comando:

   $ python manage.py sql aexp

A saída deve ser algo muito próximo (ou idêntico) a isso:

CREATE TABLE `aexp_poll` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `question` varchar(200) NOT NULL,
    `pub_date` datetime NOT NULL
)
;
CREATE TABLE `aexp_choice` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `poll_id` integer NOT NULL,
    `choice` varchar(200) NOT NULL,
    `votes` integer NOT NULL
)
;

Pronto! só dê um:

   $ python manage.py syncdb

para seu projeto dar conta de usar a base de dados que vc fez.

Django4: Interlúdio na shell

(fim da parte 1 do tutorial oficial)

Para inicar uma shell com o ambiente bonitinho para fazer alterações na mão e colocar coisas nos BD:

   $ python manage.py shell 

Aí pode fazer coisas como:

[1]: from aexp.models import Poll, Choice
[2]: p = Poll(question="What's up?", pub_date=datetime.datetime.now())
[3]: p.save()
[4]: p.choice_set.create(choice='Not much', votes=0)

etc...

Django5: Habilite seu Admin

(inicio da parte 2 do tutorial)

Depois de descomentar 'django.contrib.admin' do INSTALLED_APPS do settings.py

   $ python manage.py syncdb # porque estamos com um app novo, o admin

Aí é preciso habilitar a URL para acessar o admin, isso é feito no url.py descomentando as seguintes três linhas:

from django.contrib import admin
admin.autodiscover()
(r'^admin/', include(admin.site.urls)),

A última fica ao final do bloco identado.

Pronto. Inicie o server

   $ python manage.py runserver

e vá para o endereço previsto, provavelmente:

   http://127.0.0.1:8000/admin/

Vualá seu admin tá rodando. Faz login aí, irmão.

Django6: Faça seu Admin responder

Depois de devidamente logado,

Crie um arquivo admin.py no diretório do app que startou com startapp. Coloque as seguintes linhas neste arquivo admin.py:

from XXXX.models import Poll
from XXXX.models import Choice
from django.contrib import admin

admin.site.register(Poll)  <----------------
admin.site.register(Choice)  <----------------

XXX você substitui por appzinhoCoxa ou qualquer nome do app que você fez.

Recarregue a página e veja que o admin já possui uma entrada para o polls.


Troque:

admin.site.register(Poll)  <----------------
admin.site.register(Choice)  <----------------

por:

class ChoiceInline(admin.TabularInline):
    model = Choice
    extra = 3

class PollAdmin(admin.ModelAdmin):
    list_display = ('question', 'pub_date', 'was_published_today')
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]
    list_filter = ['pub_date']
    search_fields = ['question']
    date_hierarchy = 'pub_date'

admin.site.register(Poll, PollAdmin)

E veja o resultado.

Django7: Seu Admin é customizável completamente

(último da parte 2 do tutorial)

no settings.py mude:

TEMPLATE_DIRS = (
    "/home/XXXX/mytemplates", # Change this to your own directory.
)

XXXX é o que você quer.

copie coisas como:

   django/contrib/admin/templates/admin/base_site.html

para

   /home/XXXXX/mytemplates/admin/base_site.html.

e não veja a mudança alguma AINDA. Ou tente fuçar no base_site.html

Django8: Criando respostas às URLs

(início da parte 3 do tutorial oficial)

Quando vocẽ deu 'startapp nomedoapp', foi criado um diretório com 'nomedoapp'.

São 3 pequenas alterações para poder notar as mudanças. A primeira é no settings.py, ajuste a ROOT_URLCONF para nomedoPROJ/urls.py assim:

   ROOT_URLCONF = 'nomedoPROJ.urls'

Deixe eu urlpatterns deste jeit (ele fica no seu urls.py):

urlpatterns = patterns('',
    (r'^nodedoAPP/$', 'nomedoAPP.views.index'), <---- aqui
    (r'^admin/', include(admin.site.urls)),
)

Note a linha destacada que é a única adicionada. E tente perceber como ele endereça alguém chamado index dentro do views.py do diretório/app nodedoAPP

Coloque agora no views.py a função:

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the poll index.")

Django9: Utilizando os Templates do Django

Agora é importante que você tenha ao menos as seguintes linhas no seu views.py:

from django.shortcuts import render_to_response
from nodedoAPP.models import Poll

def index(request):
    latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
    return render_to_response('nomedoAPP/index.html', {'latest_poll_list': latest_poll_list})

Aí falta-nos colocar este index.html no lugar. Na sua pasta de templates, cria uma pasta nomedoAPP, dentro faça um arquivo index.html rodando:

{% if latest_poll_list %}
    <ul>
    {% for poll in latest_poll_list %}
        <li><a href="/nomedoAPP/{{ poll.id }}/">{{ poll.question }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

Para ver o efeito, acesse o link relacionado. Algo como:

   http://127.0.0.1:8000/nomedoAPP/


Django10: Organização das URLs. (Perfumaria)

(último do terceiro tutorial)

No urls.py, você pode mudar:

urlpatterns = patterns('',
    (r'^aexp/$', 'aexp.views.index'),
    (r'^aexp/(?P<poll_id>\d+)/$', 'aexp.views.detail'),
    (r'^aexp/(?P<poll_id>\d+)/results/$', 'aexp.views.results'),
    (r'^aexp/(?P<poll_id>\d+)/vote/$', 'aexp.views.vote'),
    (r'^admin/', include(admin.site.urls)),
)

para

urlpatterns = patterns('aexp.views',
    (r'^aexp/$', 'index'),
    (r'^aexp/(?P<poll_id>\d+)/$', 'detail'),
    (r'^aexp/(?P<poll_id>\d+)/results/$', 'results'),
    (r'^aexp/(?P<poll_id>\d+)/vote/$', 'vote'),
)

urlpatterns += patterns('',
    (r'^admin/', include(admin.site.urls)),
)

Ou pode colocar todos os links referentes ao APP aexp dentro de um arquivo. Seu urls.py fica assim:

from django.conf.urls.defaults import patterns, include

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    (r'^polls/', include('polls.urls')),
    (r'^admin/', include(admin.site.urls)),
)

E seu arquivo ./aexp/urls.py fica:

from django.conf.urls.defaults import patterns, include

urlpatterns = patterns('polls.views',
    (r'^$', 'index'),
    (r'^(?P<poll_id>\d+)/$', 'detail'),
    (r'^(?P<poll_id>\d+)/results/$', 'results'),
    (r'^(?P<poll_id>\d+)/vote/$', 'vote'),
)

Django11: Django interagindo

Percebeu que o index.html do seu APP (no meu caso 'aexp') lista todas as questões que estão rolando?

Caso você clique em alguma das questões, você será redirecionado para um tal de details.html, note o 'href' no seu index.html:

<li><a href="/aexp/{{ poll.id }}/">{{ poll.question }}</a></li>

E esta linha do seu urls.py:

(r'^aexp/(?P<poll_id>\d+)/$', 'detail'),

Por fim, veja a função detail do seu views.py. Coloque algo como:

def detail(request, poll_id):
    p = get_object_or_404(Poll, pk=poll_id)
    return render_to_response('aexp/detail.html', {'poll': p},
                               context_instance=RequestContext(request))

Visto isso. Vamos agir. Coloque no details.html este código:

<h1>{{ poll.question }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="/aexp/{{ poll.id }}/vote/" method="post">
{% csrf_token %}
{% for choice in poll.choice_set.all %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
    <label for="choice{{ forloop.counter }}">{{ choice.choice }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>

Como no seu urls.py tem a linha:

   (r'^aexp/(?P<poll_id>\d+)/$', 'detail'),

Você precisa fazer a função para vote (no seu views.py):

def vote(request, poll_id):
    p = get_object_or_404(Poll, pk=poll_id)
    try:
        selected_choice = p.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the poll voting form.
        return render_to_response('aexp/detail.html', {
            'poll': p,
            'error_message': "You didn't select a choice.",
        }, context_instance=RequestContext(request))
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse('aexp.views.results', args=(p.id,)))

Por fim, basta fazer a função 'results' que está requerida no vote():

def results(request, poll_id):
    p = get_object_or_404(Poll, pk=poll_id)
    return render_to_response('aexp/results.html', {'poll': p})

E fazer seu results.html, eis um modelo:

<h1>{{ poll.question }}</h1>

<ul>
{% for choice in poll.choice_set.all %}
    <li>{{ choice.choice }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a href="/polls/{{ poll.id }}/">Vote again?</a>

Pronto! Você viu seu Django interagindo com graça e elegância. Note que pode ser importante que você vá na tela de administração e registre algumas perguntas...

Django12: Generic Views

As 'generic views' são atalhos para a seguinte rotina corriqueira: busca-se os dados no banco de dados a partir de configurações da URL, retornando uma página renderizada com os dados buscados.

De forma resumida, faremos isso especificando diretamente na urls.py que utilizaremos uma generic view.

Primeiro adicione esta linha no seu urls.py:

   from django.views.generic import DetailView, ListView

Depois delete a parte do urlspatterns que não está relacionada ao admin, coloque isso no lugar:

urlpatterns = patterns('',
    (r'^aexp/$',
        ListView.as_view(
            queryset=Poll.objects.order_by('-pub_date')[:5],
            context_object_name='latest_poll_list',
            template_name='aexp/index.html')),
    (r'^aexp/(?P<pk>\d+)/$',
        DetailView.as_view(
            model=Poll,
            template_name='aexp/detail.html')),
    url(r'^aexp/(?P<pk>\d+)/results/$',
        DetailView.as_view(
            model=Poll,
            template_name='aexp/results.html'),
        name='aexp_results'),
    (r'^aexp/(?P<poll_id>\d+)/vote/$', 'aexp.views.vote'),
)

Repare como utilzam os o ListView e o DetailView que importamos.

O ListView é dedicado a dispor uma lista de itens na página e é simples: o queryset é sua lista de objetos a serem apresentados. A string atribuida ao context_object é o nome que vai aparecer no seu template. Veja seu template como especificado no template_name.html

O DetailView é dedicado a mostrar os detalhes sobre algum objeto. É necessário especificar o 'model' (no nosso caso é o Poll). O segundo DetailView tem 2 detalhes: primeiramente o 'name' está nomeando a URL para que ela possa ser referenciada depois. Em segundo lugar, a função url encapsula todo mundo: o padrão, o modelo, o template e o nome.

O útlimo passo é arrumar o HttpresponseRedirect para:

   return HttpResponseRedirect(reverse('poll_results', args=(p.id,)))

E este reverse permanece um mistério... ;O)

Pronto. Delete este views do seu views.py (as funções index(), details() e results). Verifique como está tudo rodando ok e macio!