Engitec - Minicurso de Django
-
Upload
gilson-filho -
Category
Technology
-
view
2.346 -
download
0
Transcript of Engitec - Minicurso de Django
Framework web para perfeccionistas com prazos
O que vamos aprender hoje?
- Componentes Bsicos do Django; + Models; + Forms; + Views.
- TDD; - Django Admin.Ok. Mas quem voc?
Abheek Anand
Gilson Filho
Desenvolvedor h 5 anos
Visual Basic, Java e ASP
Python h 1 ano e meio
O que
Django um framework web de alto nvel que foca no desenvolvimento rpido, limpo e design pragmtico.
Django um framework web de alto nvel que foca no desenvolvimento rpido, limpo e design pragmtico.
Django um framework web de alto nvel que foca no desenvolvimento rpido, limpo e design pragmtico.
Documentao
http://django.me/design
Histria do Django
Adrian Holovaty
@adrianholovaty
Simon Willison
@simonw
Lawrence Journal
Jacob Kaplan Moss
@jacobian
Caractersticas
Mapeamento Objeto Relacional ORM
Gerao de Formulrios
Forms e ModelForms
Interface Administrativa
Django Admin
Sistema de Templates
Internacionalizao e Localizao
i18n e i10n
Desenvolvimento em Camadas
MVC vs MTV
ModelTemplateView
Desenvolvimento guiado Testes
TDD
URLs Flexveis
Reusabilidade
Don't Repeat Yourself
Baterias Includas
AuthMessagesCacheStaticfilesLoggingLocalflavors
SitesSitemapSyndication (Feed)MarkupGeoDjango (Postgis)Security
Quem usa?
Sistema de votaes da Engitec
engipolls
Sistema de Votaes
O participante poder votar nas palestras e minicursos do evento, e deixar o seu comentrio;
No preciso login;
Sistema de Votaes
A forma de votao ser com trs alternativas:Muito bom;
Legal;
Ruim.
Gerenciar o resultado das votaes.
Preparando o Ambiente
Ferramentas
Python 2.7
Django 1.4
Distribute
Pip & Virtualenv
dj-database-url
Unipath
Distribute
$ wget http://python-distribute.org/distribute_setup.py$ sudo python distribute_setup.py
Pip & Virtualenv
$ sudo easy_install pip virtualenv
Criando o ambiente
$ virtualenv --distribute --unzip-setuptools engipolls
Ativando o ambiente
$ cd engipolls$ source bin/activate
Unipath
$ pip install unipath==0.2.1
Django
$ pip install django==1.4.1
Criando Projeto
$ django-admin.py startproject src
engipolls/ src/ manage.py src/ __init__.py settings.py urls.py
Organizando Projeto
$ cd engipolls$ mv src/manage.py .$ mv src/src/* src$ rmdir src/src
engipolls/ manage.py src/ __init__.py settings.py urls.py
Criando caminhos relativos
# src/settings.py
from unipath import PathPROJECT_DIR = Path(__file__).parent
Configurando Banco de Dados
dj-database-url
$ pip install dj-database-url==0.2.1
Banco de Dados
import dj_database_urlDATABASES = { 'default': dj_database_url.config( default='sqlite:///' + PROJECT_DIR.child('engipolls.db'))}
syncdb
$ python manage.py syncdb
Creating tables ...Creating table auth_permissionCreating table auth_group_permissionsCreating table auth_groupCreating table auth_user_user_permissionsCreating table auth_user_groupsCreating table auth_userCreating table django_content_typeCreating table django_sessionCreating table django_site
You just installed Django's auth system, which means you don't have any superusers defined.Would you like to create one now? (yes/no): yesUsername (leave blank to use 'gilson'): adminE-mail address: [email protected]: Password (again): Superuser created successfully.Installing custom SQL ...Installing indexes ...Installed 0 object(s) from 0 fixture(s)
Criando a aplicao
$ python manage.py startapp talks$ mv talks src/
src/settings.py
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', # Uncomment the next line to enable the admin: # 'django.contrib.admin', # Uncomment the next line to enable admin documentation: # 'django.contrib.admindocs',
'src.talks',)
talks/tests.py
# -*- coding: utf8 -*-
from django.test import TestCase
class TalkUrlTest(TestCase): def test_get_talk_form(self): '''Retorna status 200 da lista de palestras''' response = self.client.get('/') self.assertEquals(response.status_code, 200)
$ python manage.py test talks
Creating test database for alias 'default'...E======================================================================ERROR: test_get_talk_form (src.talks.tests.TalkUrlTest)Retorna status 200 da lista de palestras----------------------------------------------------------------------... template, origin = find_template(template_name) File "/home/gilson/Projects/engipolls/local/lib/python2.7/site-packages/django/template/loader.py", line 138, in find_template raise TemplateDoesNotExist(name)TemplateDoesNotExist: 404.html
----------------------------------------------------------------------Ran 1 test in 0.027s
Templates: 404 e 500.html
$ mkdir src/templates$ touch src/templates/{404,500}.html
src/setttings.py
TEMPLATE_DIRS = ( PROJECT_DIR.child('templates'),)
$ python manage.py test talks
Creating test database for alias 'default'...F======================================================================FAIL: test_get_talk_form (src.talks.tests.TalkUrlTest)Retorna status 200 da lista de palestras----------------------------------------------------------------------... File "/home/gilson/Projects/engipolls/src/talks/tests.py", line 10, in test_get_talk_form self.assertEquals(response.status_code, 200)AssertionError: 404 != 200
----------------------------------------------------------------------Ran 1 test in 0.021s
Rotas
page.php
script.cgi?pageid=144
StoryPage.aspx
0,2097,1-1-30-72-707-4027,00.html
/products/new/
/products/1/details/
/about/
src/urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('', url(r'^$', 'src.talks.views.home', name='home'),)
$ python manage.py test talks
Creating test database for alias 'default'...E======================================================================ERROR: test_get_talk_form (src.talks.tests.TalkUrlTest)Retorna status 200 da lista de palestras----------------------------------------------------------------------...ViewDoesNotExist: Could not import src.talks.views.home.View does not exist in module src.talks.views.
----------------------------------------------------------------------Ran 1 test in 0.026s
Fluxo HTTP
GET
/
ROOT_URLCONF
src.urls
url(r'^$','src.talks.views.home')
home(request)
Documentao
http://django.me/urls
Views
talks/views.py
# -*- coding: utf8 -*-from django.http import HttpResponse
def home(request): return HttpResponse()
$ python manage.py tests talks
Creating test database for alias 'default'....----------------------------------------------------------------------Ran 1 test in 0.014s
Refatorando
talks/tests.py
# -*- coding: utf8 -*-
from django.test import TestCasefrom django.core.urlresolvers import reverse
class TalkUrlTest(TestCase): def test_get_talk_form(self): '''Retorna status 200 da lista de palestras''' response = self.client.get(reverse('home')) self.assertEquals(response.status_code, 200)
$ python manage.py test talks
Creating test database for alias 'default'....----------------------------------------------------------------------Ran 1 test in 0.014s
talks/tests.py
# -*- coding: utf8 -*-
from django.test import TestCasefrom django.core.urlresolvers import reverse
class TalkUrlTest(TestCase): def setUp(self): self.resp = self.client.get(reverse('home'))
def test_get_talk_form(self): '''Retorna status 200 da lista de palestras''' self.assertEquals(self.resp.status_code, 200)
$ python manage.py test talks
Creating test database for alias 'default'....----------------------------------------------------------------------Ran 1 test in 0.014s
talks/tests.py
# -*- coding: utf8 -*-
from django.test import TestCasefrom django.core.urlresolvers import reverse
class TalkUrlTest(TestCase): # ...
def test_template(self): '''Renderiza template para enviar na resposta''' self.assertTemplateUsed(self.resp, 'talks/talks_list.html')
$ python manage.py test talks
Creating test database for alias 'default'....F======================================================================FAIL: test_template (src.talks.tests.TalkUrlTest)Usa o template talks/talks_list.html----------------------------------------------------------------------... File "/home/gilson/Projects/engipolls/local/lib/python2.7/site-packages/django/test/testcases.py", line 741, in assertTemplateUsed self.fail(msg_prefix + "No templates used to render the response")AssertionError: No templates used to render the response
----------------------------------------------------------------------Ran 2 tests in 0.057s
# -*- coding: utf8 -*-
from django.http import HttpResponsefrom django.template import loader, Context
def home(request): t = loader.get_template('talks/talks_list.html') c = Context()
content = t.render(c)
return HttpResponse(content)
$ python manage.py test talks
Creating test database for alias 'default'...EE======================================================================ERROR: test_get_talk_form (src.talks.tests.TalkUrlTest)Retorna status 200 da lista de palestras----------------------------------------------------------------------...TemplateDoesNotExist: talks/talks_list.html======================================================================ERROR: test_template (src.talks.tests.TalkUrlTest)Renderiza template para enviar na resposta----------------------------------------------------------------------...TemplateDoesNotExist: talks/talks_list.html----------------------------------------------------------------------Ran 2 tests in 0.168s
Django Templates
Carregando templates
TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader',# 'django.template.loaders.eggs.Loader',)
src/settings.py
# crie a pasta templates e subpasta talks na aplicao$ mkdir -p src/talks/templates/talks$ touch src/talks/templates/talks/talks_list.html
app_directories.Loader
$ python manage.py test talks
Creating test database for alias 'default'.....----------------------------------------------------------------------Ran 2 tests in 0.025s
Django Models
O que Models?
class Talk(models.Model): name = models.CharField(max_length=100) resume = models.TextField() at = models.DateTimeField(auto_now_add=True) talker = models.TextField(max_length=80)
Exemplo de Model
Agora s fazer
Agora s fazer
mas criar o teste, claro!
# -*- coding: utf8 -*-import datetime# from .models import Talk
class TalkModelTest(TestCase): def setUp(self): self.talk = Talk.objects.create( name=uO que Python?, resume=uPalestra sobre Python, at=datetime.datetime.now(), talker=Guido Van Rossum )
def test_create(self): '''Registra a palestra corretamente''' self.assertEquals(self.talk.pk, 1)
$ python manage.py test talks
Traceback (most recent call last):... File "/home/gilson/Projects/engipolls/src/talks/tests.py", line 7, in from .models import TalkImportError: cannot import name Talk
class Talk(models.Model): name = models.CharField(max_length=100) resume = models.TextField() at = models.DateTimeField(auto_now_add=True) talker = models.TextField(max_length=80)
talks/models.py
$ python manage.py test talks
Creating test database for alias 'default'......----------------------------------------------------------------------Ran 3 tests in 0.027s
# -*- coding: utf8 -*-import datetime# from .models import Talk
class TalkModelTest(TestCase): # ...
def test_unicode(self): ''' usado para a representao do objeto''' self.assertEquals( u'Palestra: O que Python?', unicode(self.talk))
$ python manage.py test talks
Creating test database for alias 'default'....F..======================================================================FAIL: test_unicode (src.talks.tests.TalkModelTest) usado para retornar a representao do objeto----------------------------------------------------------------------...AssertionError: u'Palestra: O que \xe9 Python?' != u'Talk object'- Palestra: O que \xe9 Python?+ Talk object----------------------------------------------------------------------Ran 4 tests in 0.047s
class Talk(models.Model): name = models.CharField(max_length=100) resume = models.TextField() at = models.DateTimeField(auto_now_add=True) talker = models.TextField(max_length=80)
def __unicode__(self): return Palestra: %s % (self.name,)
talks/models.py
$ python manage.py test talks
Creating test database for alias 'default'.......----------------------------------------------------------------------Ran 4 tests in 0.030s
Django Models
Meta options
class Talk(models.Model): # ...
class Meta: verbose_name = uPalestra db_table = talks ordering = ['at,']
def __unicode__(self): return Palestra: %s % (self.name,)
talks/models.py
Minicurso
Dados para cadastro:Nome do minicurso;
Resumo;
Hora do minicurso;
Palestrante.
Palestra == Minicurso
class TalkModelTest(TestCase): def setUp(self): self.talk = Talk.objects.create( name=uO que Python?, resume=uPalestra sobre Python, at=datetime.datetime.now(), talker=Guido Van Rossum, type_talk='P' )
def test_create(self): '''Registra a palestra corretamente''' self.assertEquals(self.talk.pk, 1)
talks/tests.py
$ python manage.py test talks
Creating test database for alias 'default'...EE..======================================================================ERROR: test_create (src.talks.tests.TalkModelTest)Registra a palestra corretamente----------------------------------------------------------------------...TypeError: 'type_talk' is an invalid keyword argument for this function======================================================================ERROR: test_unicode (src.talks.tests.TalkModelTest) usado para retornar a representao do objeto----------------------------------------------------------------------...TypeError: 'type_talk' is an invalid keyword argument for this function----------------------------------------------------------------------Ran 4 tests in 0.125s
class Talk(models.Model): TALK_CHOICES = ( ('P', u'Palestra'), ('M', u'Minicurso'), ) # ... type_talk = models.CharField(max_length=1, choices=TALK_CHOICES)
# ... def __unicode__(self): if self.type_talk == 'P': return Palestra: %s % (self.name,) elif self.type_talk == 'M': return Minicurso: %s % (self.name,)
talks/models.py
$ python manage.py test talks
Creating test database for alias 'default'.......----------------------------------------------------------------------Ran 4 tests in 0.033s
$ python manage.py syncdb
Creating tables ...Creating table talks_talkInstalling custom SQL ...Installing indexes ...Installed 0 object(s) from 0 fixture(s)
Atualizando banco
Votao
Dados para cadastro:Palestra/Minicurso;
Tipo de votao (Muito bom, legal e ruim);
Comentrios;
class Poll(models.Model): POLL_CHOICES = ( (u'B', u'Muito Bom'), (u'L', u'Legal'), (u'R', u'Ruim'), ) talk = models.ForeignKey('Talk', max_length=100) poll = models.CharField(max_length=1, choices=POLL_CHOICES) comments = models.TextField(max_length=180, blank=True)
def __unicode__(self): return self.get_poll_display()
talks/models.py
Documentao
http://django.me/modelshttp://django.me/metaoptions
Querysets
Demonstrao
Painel Administrativo
Django Admin
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.admin',)
src/settings.py
# ...from django.contrib import adminadmin.autodiscover()
urlpatterns = patterns('', # ...
url(r'^admin/', include(admin.site.urls)),)
src/urls.py
$ python manage.py syncdb
Creating tables ...Creating table django_admin_logInstalling custom SQL ...Installing indexes ...Installed 0 object(s) from 0 fixture(s)
Atualizando banco
Inserindo talk no Admin
# -*- coding: utf8 -*-
from django.contrib import admin
from .models import Talk
admin.site.register(Talk)
talks/admin.py
$ python manage.py runserver
Validating models...
0 errors foundDjango version 1.4.1, using settings 'src.settings'Development server is running at http://127.0.0.1:8000/Quit the server with CONTROL-C.
Internacionalizao
i18n
TIME_ZONE = 'America/Sao_Paulo'
LANGUAGE_CODE = 'pt-br'
src/settings.py
# from django.utils.translation import ugettext as _
class Talk(models.Model): TALK_CHOICES = ( ('P', _(u'Palestra')), ('M', _(u'Minicurso')), ) # ...
talks/models.py
#
class Talk(models.Model): name = models.CharField(_(u'Nome da Sesso'), max_length=100) resume = models.TextField(_(u'Resumo')) at = models.DateTimeField(_(u'Data da sesso'), auto_now_add=True) talker = models.TextField(_(u'Palestrante'), max_length=80) type_talk = models.CharField(_(u'Tipo da Sesso'), max_length=1, choices=TALK_CHOICES)
def __unicode__(self): return Palestra: %s % (self.name,)
talks/models.py
Django Admin
Filtros
# -*- coding: utf8 -*-
from django.contrib import admin
from .models import Talk
class TalkAdmin(admin.ModelAdmin): list_filter = ['at', 'type_talk']
admin.site.register(Talk, TalkAdmin)
talks/admin.py
Django Admin
Pesquisa
# -*- coding: utf8 -*-
from django.contrib import admin
from .models import Talk
class TalkAdmin(admin.ModelAdmin): list_filter = ['at', 'type_talk'] search_fields = ('name',)
admin.site.register(Talk, TalkAdmin)
talks/admin.py
Django Admin
List Display
# -*- coding: utf8 -*-
from django.contrib import admin
from .models import Talk
class TalkAdmin(admin.ModelAdmin): list_display = ('name', 'at', 'type_talk',) list_filter = ['at', 'type_talk'] search_fields = ('name',)
admin.site.register(Talk, TalkAdmin)
talks/admin.py
Documentao
http://django.me/admin
# -*- coding: utf8 -*-from django.shortcuts import render
def home(request): return render(request, 'talks/talks_list.html', {})
talks/views.py
$ python manage.py test talks
Creating test database for alias 'default'.......----------------------------------------------------------------------Ran 4 tests in 0.033s
# -*- coding: utf8 -*-from django.shortcuts import render
from .models import Talk
def home(request): talks = Talk.objects.all() return render(request, 'talks/talks_list.html', { 'talks': talks, })
talks/views.py
Engipolls
Lista de Palestras e Minicursos {% for talk in talks %} {{ talk.name }} {{ talk.resume }} Horrio: {{ talk.at|date:"d/M/Y" }} {% endfor %}
src/templates/base.html
Engipolls
{% block content %}{% endblock content %}
talks_list.html
{% extends base.html %}
{% block content %} Lista de Palestras e Minicursos {% for talk in talks %} {{ talk.name }} {{ talk.resume }} Horrio: {{ talk.at|date:"d/M/Y" }} {% endfor %}{% endblock content %}
talks_list.html
{% for talk in talks %} {{ talk.name }} {{ talk.resume }} Horrio: {{ talk.at|date:"d/M/Y" }} Votar agora
Formulrios
Django Forms
Criando arquivo
$ touch src/talks/forms.py
Formulrios
Exemplo
talks/forms.py
# -*- coding: utf8 -*-
from django import forms
class TalkForm(forms.Form): TALK_CHOICES = ( ('P', _(u'Palestra')), ('M', _(u'Minicurso')), ) name = forms.CharField(label=u'Nome da Sesso') resume = forms.CharField(label=u'Resumo', widget=forms.Textarea) at = forms.DateTimeField(label=u'Data da Sesso') talker = forms.CharField(label=u'Palestrante') type_talk = forms.ChoiceField(label=u'Tipo de Sesso', choices=TALK_CHOICES)
talks/forms.py
# -*- coding: utf8 -*-
from django import forms
from .models import Talk
class TalkForm(forms.Form): TALK_CHOICES = ( ('P', _(u'Palestra')), ('M', _(u'Minicurso')), ) name = forms.CharField(label=u'Nome da Sesso') resume = forms.CharField(label=u'Resumo', widget=forms.Textarea) at = forms.DateTimeField(label=u'Data da Sesso')
class Meta: model = Talk
Formulrios
Criando PollForm
talks/forms.py
# -*- coding: utf8 -*-
from django import forms
from .models import Poll
class PollForm(forms.Form): class Meta: model = Poll
talks/urls.py
urlpatterns = patterns('', # ... url(r'^votacao/(?P[\d]+)/$', 'src.talks.views.poll_form', name='poll_form'),)
talks/views.py
# -*- coding: utf8 -*-
from django import forms
from .forms import PollForm
def poll_form(request, talk_id): return render(request, 'talks/polls_form.html', { 'form': PollForm(), })
templates/talks/polls_form.html
{% extends base.html %}
{% block content %} {% csrf_token %} {{ form.as_p }} {% endblock content %}
talks/forms.py
# -*- coding: utf8 -*-
from django import forms
from .models import Poll
class PollForm(forms.Form): class Meta: model = Poll exclude = ('talk',)
talks/views.py
# from django.shortcuts import get_object_or_404from .models import Talk
def poll_form(request, talk_id): talk = get_object_or_404(Talk, pk=talk_id) if request.method == 'POST': form = PollForm(request.POST) if form.is_valid(): poll = form.save(commit=False) poll.talk = talk poll.save()
return render(request, 'talks/polls_form.html', { 'form': PollForm(), })
talks/views.py
# from django.shortcuts import redirect
if form.is_valid(): poll = form.save(commit=False) poll.talk = talk poll.save()
return redirect('/votacoes/sucesso')
return render(request, 'talks/polls_form.html', { 'form': PollForm(),})
talks_list.html
{% for talk in talks %} {{ talk.name }} {{ talk.resume }} Horrio: {{ talk.at|date:"d/M/Y" }} Votar agora
talks/urls.py
urlpatterns = patterns('', # ... url(r'^votacoes/sucesso/$', 'src.talks.views.success', name='success'),)
talks/views.py
# def success(request): return render(request, 'talks/polls_success.html', {})
templates/talks/polls_success.html
{% extends base.html %}
{% block content %} Sua votao foi efetuada com sucesso! Continue com a votao aqui{% endblock content %}
Dicas Finais
http://welcometothedjango.com.br
Desenvolvimento gil com Python e Django
http://docs.djangoproject.com
https://github.com/nathanborror/django-basic-apps
Obrigado!
[email protected]@gilsonfilhoblog.gilsondev.comhttp://github.com/gilsondev