engitec - minicurso de django

Download Engitec - Minicurso de Django

If you can't read please download the document

Upload: gilson-filho

Post on 16-Apr-2017

2.346 views

Category:

Technology


0 download

TRANSCRIPT

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