Your SlideShare is downloading. ×
Engitec - Minicurso de Django
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Engitec - Minicurso de Django

1,864
views

Published on

Minicurso ministrado no Engitec 2013, usando a tecnologia Django.

Minicurso ministrado no Engitec 2013, usando a tecnologia Django.


0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,864
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
14
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Framework web para perfeccionistas com prazos
  • 2. O que vamos aprender hoje?
  • 3. Ok. Mas quem é você?
  • 4. Abheek
  • 5. Gilson
  • 6. Desenvolvedor há 5 anos Visual Basic, Java e ASP Python há 1 ano e meio
  • 7. O que é
  • 8. Django é um framework web de alto nível que foca no desenvolvimento rápido, limpo e design pragmático.
  • 9. Django é um framework web de alto nível que foca no desenvolvimento rápido, limpo e design pragmático.
  • 10. Django é um framework web de alto nível que foca no desenvolvimento rápido, limpo e design pragmático.
  • 11. Documentação http://django.me/design
  • 12. História do Django
  • 13. Adrian Holovaty @adrianholovaty
  • 14. Simon Willison @simonw
  • 15. Lawrence Journal
  • 16. Jacob Kaplan Moss @jacobian
  • 17. Características
  • 18. Mapeamento Objeto Relacional ORM
  • 19. Geração de Formulários Forms e ModelForms
  • 20. Interface Administrativa Django Admin
  • 21. Sistema de Templates
  • 22. Internacionalização e Localização i18n e i10n
  • 23. Desenvolvimento em Camadas MVC vs MTV
  • 24. Model Template View
  • 25. Desenvolvimento guiado à Testes TDD
  • 26. URLs Flexíveis
  • 27. Reusabilidade Don't Repeat Yourself
  • 28. Baterias Incluídas
  • 29. Auth Sites Messages Sitemap Cache Syndication (Feed) Staticfiles Markup Logging GeoDjango (Postgis) Localflavors Security
  • 30. Quem usa?
  • 31. Sistema de votações da Engitec engipolls
  • 32. Sistema de Votações ● ● O participante poderá votar nas palestras e minicursos do evento, e deixar o seu comentário; Não é preciso login;
  • 33. Sistema de Votações ● A forma de votação será com três alternativas: – – Legal; – ● Muito bom; Ruim. Gerenciar o resultado das votações.
  • 34. Preparando o Ambiente
  • 35. Ferramentas Python 2.7 Django 1.4 Distribute Pip & Virtualenv dj-database-url Unipath
  • 36. Distribute $ wget http://pythondistribute.org/distribute_setup.py $ sudo python distribute_setup.py
  • 37. Pip & Virtualenv $ sudo easy_install pip virtualenv
  • 38. Criando o ambiente $ virtualenv --distribute --unzip-setuptools engipolls
  • 39. Ativando o ambiente $ cd engipolls $ source bin/activate
  • 40. Unipath $ pip install unipath==0.2.1
  • 41. Django $ pip install django==1.4.1
  • 42. Criando Projeto $ django-admin.py startproject src
  • 43. engipolls/ src/ manage.py src/ __init__.py settings.py urls.py
  • 44. Organizando Projeto $ cd engipolls $ mv src/manage.py . $ mv src/src/* src $ rmdir src/src
  • 45. engipolls/ manage.py src/ __init__.py settings.py urls.py
  • 46. Criando caminhos relativos # src/settings.py from unipath import Path PROJECT_DIR = Path(__file__).parent
  • 47. Configurando Banco de Dados
  • 48. dj-database-url $ pip install dj-database-url==0.2.1
  • 49. Banco de Dados import dj_database_url DATABASES = { 'default': dj_database_url.config( default='sqlite:///' + PROJECT_DIR.child('engipolls.db')) }
  • 50. syncdb $ python manage.py syncdb
  • 51. Creating tables ... Creating table auth_permission Creating table auth_group_permissions Creating table auth_group Creating table auth_user_user_permissions Creating table auth_user_groups Creating table auth_user Creating table django_content_type Creating table django_session Creating table django_site
  • 52. 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): yes Username (leave blank to use 'gilson'): admin E-mail address: contato@gilsondev.com Password: Password (again): Superuser created successfully. Installing custom SQL ... Installing indexes ... Installed 0 object(s) from 0 fixture(s)
  • 53. Criando a aplicação
  • 54. $ python manage.py startapp talks $ mv talks src/
  • 55. 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',
  • 56. 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)
  • 57. 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/sitepackages/django/template/loader.py", line 138, in find_template raise TemplateDoesNotExist(name) TemplateDoesNotExist: 404.html -----------------------------------------------------------
  • 58. Templates: 404 e 500.html $ mkdir src/templates $ touch src/templates/{404,500}.html
  • 59. src/setttings.py TEMPLATE_DIRS = ( PROJECT_DIR.child('templates'), )
  • 60. 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 ---------------------------------------------------------------------
  • 61. Rotas
  • 62. page.php script.cgi?pageid=144 StoryPage.aspx 0,2097,1-1-30-72-707-4027,00.html
  • 63. /products/new/ /products/1/details/ /about/
  • 64. src/urls.py from django.conf.urls import patterns, include, url urlpatterns = patterns('', url(r'^$', 'src.talks.views.home', name='home'), )
  • 65. $ 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
  • 66. Fluxo HTTP ● ● GET / ● ROOT_URLCONF ● src.urls ● url(r'^$', ● home(request) 'src.talks.views.home')
  • 67. Documentação http://django.me/urls
  • 68. Views
  • 69. talks/views.py # -*- coding: utf8 -*from django.http import HttpResponse def home(request): return HttpResponse()
  • 70. $ python manage.py tests talks Creating test database for alias 'default'... . --------------------------------------------------------------------Ran 1 test in 0.014s
  • 71. Refatorando
  • 72. # -*- coding: utf8 -*- talks/tests.py from django.test import TestCase from 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,
  • 73. $ python manage.py test talks Creating test database for alias 'default'... . --------------------------------------------------------------------Ran 1 test in 0.014s
  • 74. # -*- coding: utf8 -*- talks/tests.py from django.test import TestCase from 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)
  • 75. $ python manage.py test talks Creating test database for alias 'default'... . --------------------------------------------------------------------Ran 1 test in 0.014s
  • 76. talks/tests.py # -*- coding: utf8 -*from django.test import TestCase from 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')
  • 77. .F =========================================================== =========== FAIL: test_template (src.talks.tests.TalkUrlTest) Usa o template talks/talks_list.html --------------------------------------------------------------------... File "/home/gilson/Projects/engipolls/local/lib/python2.7/sitepackages/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 -----------------------------------------------------------
  • 78. # -*- coding: utf8 -*from django.http import HttpResponse from 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)
  • 79. 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 -----------------------------------------------------------
  • 80. Django Templates Carregando templates
  • 81. src/settings.py TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader' , # ) 'django.template.loaders.eggs.Loader',
  • 82. app_directories.Loader # crie a pasta templates e subpasta talks na aplicação $ mkdir -p src/talks/templates/talks $ touch src/talks/templates/talks/talks_list.html
  • 83. $ python manage.py test talks Creating test database for alias 'default'... .. --------------------------------------------------------------------Ran 2 tests in 0.025s
  • 84. Django Models
  • 85. O que é Models?
  • 86. Exemplo de Model 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)
  • 87. Agora é só fazer
  • 88. Agora é só fazer mas criar o teste, é claro!
  • 89. import datetime # … from .models import Talk class TalkModelTest(TestCase): def setUp(self): self.talk = Talk.objects.create( name=u”O que é Python?”, resume=u”Palestra sobre Python”, at=datetime.datetime.now(), talker=”Guido Van Rossum” ) def test_create(self): '''Registra a palestra corretamente''' self.assertEquals(self.talk.pk, 1)
  • 90. $ python manage.py test talks Traceback (most recent call last): ... File "/home/gilson/Projects/engipolls/src/talks/tests.py", line 7, in <module> from .models import Talk ImportError: cannot import name Talk
  • 91. talks/models.py 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)
  • 92. $ python manage.py test talks Creating test database for alias 'default'... ... --------------------------------------------------------------------Ran 3 tests in 0.027s
  • 93. # -*- coding: utf8 -*import datetime # … from .models import Talk class TalkModelTest(TestCase): # ... def test_unicode(self): '''É usado para a representação do objeto''' self.assertEquals( u'Palestra: O que é Python?', unicode(self.talk))
  • 94. Creating test database for alias 'default'... .F.. =========================================================== =========== FAIL: test_unicode (src.talks.tests.TalkModelTest) É usado para retornar a representação 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
  • 95. talks/models.py 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,)
  • 96. $ python manage.py test talks Creating test database for alias 'default'... .... --------------------------------------------------------------------Ran 4 tests in 0.030s
  • 97. Django Models Meta options
  • 98. talks/models.py class Talk(models.Model): # ... class Meta: verbose_name = u”Palestra” db_table = “talks” ordering = ['at,'] def __unicode__(self): return “Palestra: %s” % (self.name,)
  • 99. Minicurso ● Dados para cadastro: – Nome do minicurso; – Resumo; – Hora do minicurso; – Palestrante.
  • 100. Palestra == Minicurso
  • 101. talks/tests.py class TalkModelTest(TestCase): def setUp(self): self.talk = Talk.objects.create( name=u”O que é Python?”, resume=u”Palestra 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)
  • 102. ============================================================= ========= 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 representação do objeto --------------------------------------------------------------------... TypeError: 'type_talk' is an invalid keyword argument for
  • 103. class Talk(models.Model): talks/models.py 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':
  • 104. $ python manage.py test talks Creating test database for alias 'default'... .... --------------------------------------------------------------------Ran 4 tests in 0.033s
  • 105. Atualizando banco $ python manage.py syncdb Creating tables ... Creating table talks_talk Installing custom SQL ... Installing indexes ... Installed 0 object(s) from 0 fixture(s)
  • 106. Votação ● Dados para cadastro: – Palestra/Minicurso; – Tipo de votação (Muito bom, legal e ruim); – Comentários;
  • 107. talks/models.py 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):
  • 108. Documentação http://django.me/models http://django.me/metaoptions
  • 109. Querysets
  • 110. Demonstração
  • 111. Painel Administrativo Django Admin
  • 112. src/settings.py INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.admin', )
  • 113. src/urls.py # ... from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', # ... url(r'^admin/', include(admin.site.urls)), )
  • 114. Atualizando banco $ python manage.py syncdb Creating tables ... Creating table django_admin_log Installing custom SQL ... Installing indexes ... Installed 0 object(s) from 0 fixture(s)
  • 115. Inserindo talk no Admin
  • 116. talks/admin.py # -*- coding: utf8 -*from django.contrib import admin from .models import Talk admin.site.register(Talk)
  • 117. $ python manage.py runserver Validating models... 0 errors found Django 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.
  • 118. Internacionalização i18n
  • 119. src/settings.py TIME_ZONE = 'America/Sao_Paulo' LANGUAGE_CODE = 'pt-br'
  • 120. talks/models.py # … from django.utils.translation import ugettext as _ class Talk(models.Model): TALK_CHOICES = ( ('P', _(u'Palestra')), ('M', _(u'Minicurso')), ) # ...
  • 121. talks/models.py # … class Talk(models.Model): name = models.CharField(_(u'Nome da Sessão'), max_length=100) resume = models.TextField(_(u'Resumo')) at = models.DateTimeField(_(u'Data da sessão'), auto_now_add=True) talker = models.TextField(_(u'Palestrante'), max_length=80) type_talk = models.CharField(_(u'Tipo da Sessão'), max_length=1, choices=TALK_CHOICES)
  • 122. Django Admin Filtros
  • 123. talks/admin.py # -*- 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)
  • 124. Django Admin Pesquisa
  • 125. talks/admin.py # -*- 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)
  • 126. Django Admin List Display
  • 127. talks/admin.py # -*- 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)
  • 128. Documentação http://django.me/admin
  • 129. talks/views.py # -*- coding: utf8 -*from django.shortcuts import render def home(request): return render(request, 'talks/talks_list.html', {})
  • 130. $ python manage.py test talks Creating test database for alias 'default'... .... --------------------------------------------------------------------Ran 4 tests in 0.033s
  • 131. talks/views.py # -*- 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, })
  • 132. <!DOCTYPE HTML> <html lang="pt-BR"> <head> <meta charset="UTF-8"> <title>Engipolls</title> </head> <body> <h1>Lista de Palestras e Minicursos</h1> {% for talk in talks %} <h3>{{ talk.name }}</h3> <p>{{ talk.resume }}</p> <p>Horário: {{ talk.at|date:"d/M/Y" }}</p> {% endfor %} </body> </html>
  • 133. src/templates/base.html <!DOCTYPE HTML> <html lang="pt-BR"> <head> <meta charset="UTF-8"> <title>Engipolls</title> </head> <body> {% block content %}{% endblock content %} </body> </html>
  • 134. talks_list.html {% extends “base.html” %} {% block content %} <h1>Lista de Palestras e Minicursos</h1> {% for talk in talks %} <h3>{{ talk.name }}</h3> <p>{{ talk.resume }}</p> <p>Horário: {{ talk.at|date:"d/M/Y" }}</p> {% endfor %} {% endblock content %}
  • 135. talks_list.html {% for talk in talks %} <h3>{{ talk.name }}</h3> <p>{{ talk.resume }}</p> <p> Horário: {{ talk.at|date:"d/M/Y" }} <a href=”#”>Votar agora</a> </p> <!-- (…) -->
  • 136. Formulários Django Forms
  • 137. Criando arquivo $ touch src/talks/forms.py
  • 138. Formulários Exemplo
  • 139. 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 Sessão') resume = forms.CharField(label=u'Resumo', widget=forms.Textarea) at = forms.DateTimeField(label=u'Data da Sessão') talker = forms.CharField(label=u'Palestrante') type_talk = forms.ChoiceField(label=u'Tipo de Sessão', choices=TALK_CHOICES)
  • 140. 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 Sessão') resume = forms.CharField(label=u'Resumo', widget=forms.Textarea) at = forms.DateTimeField(label=u'Data da Sessão') class Meta: model = Talk
  • 141. Formulários Criando PollForm
  • 142. talks/forms.py # -*- coding: utf8 -*from django import forms from .models import Poll class PollForm(forms.Form): class Meta: model = Poll
  • 143. talks/urls.py urlpatterns = patterns('', # ... url(r'^votacao/(?P<talk_id>[d]+)/$', 'src.talks.views.poll_form', name='poll_form'), )
  • 144. 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(), })
  • 145. templates/talks/polls_form.ht ml {% extends “base.html” %} {% block content %} <form action="." method="POST"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="Salvar Votação" /> </form> {% endblock content %}
  • 146. talks/forms.py # -*- coding: utf8 -*from django import forms from .models import Poll class PollForm(forms.Form): class Meta: model = Poll exclude = ('talk',)
  • 147. talks/views.py # … from django.shortcuts import get_object_or_404 from .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(), })
  • 148. 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(), })
  • 149. talks_list.html {% for talk in talks %} <h3>{{ talk.name }}</h3> <p>{{ talk.resume }}</p> <p> Horário: {{ talk.at|date:"d/M/Y" }} <a href=”{% url poll_form %}”>Votar agora</a> </p> <!-- (…) -->
  • 150. talks/urls.py urlpatterns = patterns('', # ... url(r'^votacoes/sucesso/$', 'src.talks.views.success', name='success'), )
  • 151. talks/views.py # … def success(request): return render(request, 'talks/polls_success.html', {})
  • 152. templates/talks/polls_success .html {% extends “base.html” %} {% block content %} <h2>Sua votação foi efetuada com sucesso!</h2> <p>Continue com a votação <a href=”{% url home %}”>aqui</a></p> {% endblock content %}
  • 153. Dicas Finais
  • 154. http://welcometothedjango.com.br
  • 155. Desenvolvimento Ágil com Python e Django
  • 156. http://docs.djangoproject.com
  • 157. https://github.com/nathanborror/django-basic-ap
  • 158. Obrigado! contato@gilsondev.com @gilsonfilho blog.gilsondev.com http://github.com/gilsondev