Baixe o app para aproveitar ainda mais
Prévia do material em texto
Apresentando Marcel P. Caraciolo @marcelcaraciolo Residência RISE - 2011 1 Esta palestra está sobre a licença Creative Commons Residência de Reuso - 2011.1 - Recife/PE ou seja distribuir , modificar e copiar tudo liberado :D mas sempre cite a original nos seus créditos http://creativecommons.org/licenses/by-sa/3.0/ Esta aula faz parte do curso de Residência de Reuso de Software pela RISE 2 O que é Django ? Residência de Reuso - 2011.1 - Recife/PE 3 O que é Django ? Não é Jungle. É Django. 4 Não é Django Reinhardt ... na verdade é 5 É um framework web Criado em 2005 Lawrence, Kansas - Lawerence Journal World Licença BSD Aplicação Web Residência de Reuso - 2011.1 - Recife/PE 6 É um framework web Criado em 2005 Lawrence, Kansas - Lawerence Journal World Licença BSD Aplicação Web http://www.flickr.com/photos/plinton/215437652/ DRY Don’t Repeat Yourself 7 Django é Python! Escrito em Python Focado em Desenvolvimento Ágil Don’t Repeat yourself !"#$%&'()*"* ! *+"(,%-'./0. !"#$$$%&'(&)*+, Residência de Reuso - 2011.1 - Recife/PE 8 Projeto == Várias aplicações http://djangopackages.com django.contrib.admin django.contrib.commentssouth django-paginationdjango-mailer django-registration ... Residência de Reuso - 2011.1 - Recife/PE 9 E isto é MVC ? Models Controllers Views Residência de Reuso - 2011.1 - Recife/PE 10 Alguns chamam de MTV Residência de Reuso - 2011.1 - Recife/PE 11 Alguns chamam de MTV Model - Template - Views 12 Aplicações Deve fazer uma coisa, e fazer direito Se a descrição de sua aplicação for maior que uma linha, talvez ela precise ser quebrada Reutilizável (DRY se lembra ?) Talvez já exista! Residência de Reuso - 2011.1 - Recife/PE 13 Instalando a aplicação Aplicações Coloque no path (PYTHONPATH) Coloque no INSTALLED_APPS no settings.py settings.py Residência de Reuso - 2011.1 - Recife/PE 14 Aplicações A aplicação é auto-contida tests.py urls.py templates/ admin.py Residência de Reuso - 2011.1 - Recife/PE 15 Fácil de Usar $ pip install django $ django-admin.py startproject dwitter Residência de Reuso - 2011.1 - Recife/PE 16 Fácil de Usar $ pip install django $ django-admin.py startproject dwitter !"#$"%&'#()"*%+"*,#-)* $ django-admin.py startproject dwitter !"#$%&'"(%")*"+,'-(.&'///"0"%%./%*(%0#%1/%2#3#444 __init__.py manage.py settings.py urls.py !".51"23%+'*(4'%"2(")*"+,'-(.&'"5!"#$%&#'(6"(*"278*9'/ 6#%7%8-9#"*(%:;< Residência de Reuso - 2011.1 - Recife/PE 17 Fácil de Usar $ cd dwitter $ python manage.py runserver!""#$%#"&$'()*"+&,"+-(%*+ .(&/&0%1("+)&234 $ cd dwitter $ python manage.py runserver Validating models... 0 errors found Django version 1.1, using settings 'dwitter.settings' Development server is running at http:// 127.0.0.1:8000/ Quit the server with CONTROL-C. Já vem com um servidor web ! Residência de Reuso - 2011.1 - Recife/PE 18 Fácil de Usar Residência de Reuso - 2011.1 - Recife/PE 19 Quem usa ? !"#$$$ !"#$%&'#()'*+)&,-. Residência de Reuso - 2011.1 - Recife/PE 20 Documentação 21 Banco de Dados !"#$% 22 Banco de Dados!"#$%&'()*+ def book_list(request): try: db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost') cursor = db.cursor() cursor.execute('SELECT nama FROM books ORDER BY name') names = [] for row in cursor.fetchall() names.append(row[0]) db.close() except: return render_to_response('500.html') return render_to_response('book_list.html', {'names':names}) Residência de Reuso - 2011.1 - Recife/PE 23 Banco de Dados !"#$%&'()#*'#!"#$%&+++#,-, 12 linhas em Python ... :( 24 Banco de Dados 12 linhas em Python ... :( !"#$%!&'()*+"(,-./0-,$1-223045 25 ORM Padrão Active Record Classe Table !"#$%&'()*+ def book_list(request): names = Books.objects.all().order_by('name') return render_to_response('book_list.html', {'names':names}) Residência de Reuso - 2011.1 - Recife/PE 26 Criar tabelas?! Fácil! $ python manage.py syncdb Crie as tabelas no banco. E pronto! Residência de Reuso - 2011.1 - Recife/PE 27 Vamos começar ? djangoproject.com - site oficial djangobrasil.org - site oficial nacional djangogigs.com - vagas de empregro djangopeople.net - rede social djangosites.org - rede social de sites em django djangosearch.com - busca assuntos relacionados djangocodesearch.com - busca nos fontes Residência de Reuso - 2011.1 - Recife/PE 28 Vamos à prática! Residência de Reuso - 2011.1 - Recife/PE 29 Instalação Python http://www.python.org/download sudo apt-get install python Residência de Reuso - 2011.1 - Recife/PE !"#$%&'()(*+,%#-.'/0% $ sudo apt-get install python http://www.python.org/download/ !"#$%&'#()*+%,"-./0'%.)1%2'*1,#"'1%2.5.4%0%2.6.1 !"#$%&'()(*+,%#-.'/0% $ sudo apt-get install python http://www.python.org/download/ !"#$%&'#()*+%,"-./0'%.)1%2'*1,#"'1%2.5.4%0%2.6.1 !"#$%&'()(*+,%#-.'/0% $ sudo apt-get install python http://www.python.org/download/ !"#$%&'#()*+%,"-./0'%.)1%2'*1,#"'1%2.5.4%0%2.6.1Já vem com python instalado 30 Instalação de Banco de Dados Poderíamos escolher dentre vários SGBD’s Residência de Reuso - 2011.1 - Recife/PE !"#$%&'(')&#)*"+"'),-).(/-),-)0(+"/1 2)3$45(6-/1) 2)7"/+%'-89: 2);<89: 2)3'(46- 2)!"#$%& 2)!"*,(,1) 2)8<=(/-)89:)>#<?@-'- 2)A.;)0.B 2);54'"/"C)89:)8-'D-')BEEF 2)G5'-=5', 2)30.! '()*+,%-.-/$0+)!123 31 Instalação de Banco de Dados Vamos usar o Sqlite! Residência de Reuso - 2011.1 - Recife/PE Precisa instalar ?! Não :D Python já vem com SGBD incluso! http://docs.python.org/library/sqlite3.html 32 Instalação de Django 3 maneiras! Residência de Reuso - 2011.1 - Recife/PE apt-get install python-django http://www.djangoproject.com/download python setup.py install http://www.djangoproject.com/svn/django/trunk 33 Instalação de Django Residência de Reuso - 2011.1 - Recife/PE !""#$%&'() >>> import django >>> django.VERSION (1, 1, 0, 'final', 0) >>> import django Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named django !""#$%&'() >>> import django >>> django.VERSION (1, 1, 0, 'final', 0) >>> import django Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named django !""#$%&'() >>> import django >>> django.VERSION (1, 1, 0, 'final', 0) >>> import django Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named django !""#$%&'() >>> import django >>> django.VERSION (1, 1, 0, 'final', 0) >>> import django Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named django 34 Criando um projeto Residência de Reuso - 2011.1 - Recife/PE !"#$"%&'#()"*%+"*,#-)* $ django-admin.py startproject dwitter !"#$%&'"(%")*"+,'-(.&'///"0"%%./%*(%0#%1/%2#3#444 __init__.py manage.py settings.py urls.py 5#%6%7-8#"*(%9:; $ django-admin.py startproject seminario 35 Criando um projeto Residência de Reuso - 2011.1 - Recife/PE!"#$%!&'( 36 Criando um projeto Residência de Reuso - 2011.1 - Recife/PE !""#$%#"&$'()*"+&,"+-(%*+ .(&/&0%1("+)&234$ cd dwitter $ python manage.py runserver Validating models... 0 errors found Django version 1.1, using settings 'dwitter.settings' Development server is running at http:// 127.0.0.1:8000/ Quit the server with CONTROL-C. 37 Entendendo sua App Residência de Reuso - 2011.1 - Recife/PE !"#$%&$'()&*+ !!"#$!%&%!+,%- "'()*%&%.%/0-)1% #!+),!$*"!,%&%234-"5%6 38 urls.py Residência de Reuso - 2011.1 - Recife/PE Módulo urls.py serve como porta de entrada para requisições HTTP As URL’s são definidas por expressões regulares que redirecionam as requisições para as respectivas views !"#$%&%'($)*$ ! "#$%&'()*$+,-$./&$+&,-+$&*.*$/0(),+$1($(2,)+1+$/+)+$#+3$ /(4&5*2(3$6778 ! 9($1(%2(2$:;<3$(#(=+2,(3$.(15+2,($(>/)(35*2(3$)(=0#+)(3$ ?0($)(15)5=(2$+$@02&5*2(3$1($0(12$./& 0)#3A/B C5(D3A/B 'E/FGG.B35,(A&*.G+H*0,G ',.# ... I0)#/+E()23J 39 views.py Residência de Reuso - 2011.1 - Recife/PE Módulo views.py tem funções com parâmetros um objeto HttpRequest Retorna um objeto HttpResponse !"#$%&%'($)*$ ! "#$%&'()*'$+,$-),./012$3,()4,$(565$1#376,835/$&'$549,85$ +,-"./0.$)$2$85+5/$:5/$1#376,835/$+,$:#$;<"$(#18&3#+5/=$ 8,'),'+5$>&,$+,-5:-,3$/),613,$&'$549,85$+,-".$-12$. -),./012 +,-"./0.$)345%666 +,-".$-12$.34 40 Exemplo Residência de Reuso - 2011.1 - Recife/PE !"#$%&%'($)*$ +,-./01%2!""http://mysite.com/time from django.conf.urls.defaults import * from mysite.views import hora_actual urlpatterns = patterns('', (r'^time/$', hora_actual), ) from django.http import HttpResponse from datetime import datetime def hora_actual(request): now = datetime.now() html = "Son las %s." % now return HttpResponse(html) !"#$%&' ()*+$%&' urls.py !"#$%&%'($)*$ +,-./01%2!""http://mysite.com/time from django.conf.urls.defaults import * from mysite.views import hora_actual urlpatterns = patterns('', (r'^time/$', hora_actual), ) from django.http import HttpResponse from datetime import datetime def hora_actual(request): now = datetime.now() html = "Son las %s." % now return HttpResponse(html) !"#$%&' ()*+$%&'views.py http://mysite.com.time 41 Exemplo 2 Residência de Reuso - 2011.1 - Recife/PE urls.py views.py http://mysite.com.time/plus/2 !"#$%&%'($)*$ from django.conf.urls.defaults import * from mysite.views import dentro_de urlpatterns = patterns('', (r'^time/plus/(\d{1,2})/$', dentro_de), ) from django.http import HttpResponse from datetime import datetime, timedelta def dentro_de(request, offset): offset = int(offset) dt = datetime.now() + timedelta(hours=offset) html = "En %i hora(s), serán las %s." % (offset, dt) return HttpResponse(html) !"#$%&' ()*+$%&' +,-./01%2!""http://mysite.com/time/plus/2 !"#$%&%'($)*$ from django.conf.urls.defaults import * from mysite.views import dentro_de urlpatterns = patterns('', (r'^time/plus/(\d{1,2})/$', dentro_de), ) from django.http import HttpResponse from datetime import datetime, timedelta def dentro_de(request, offset): offset = int(offset) dt = datetime.now() + timedelta(hours=offset) html = "En %i hora(s), serán las %s." % (offset, dt) return HttpResponse(html) !"#$%&' ()*+$%&' +,-./01%2!""http://mysite.com/time/plus/2 42 Residência de Reuso - 2011.1 - Recife/PE Html dentro da views? 43 Templates Residência de Reuso - 2011.1 - Recife/PE Separa a camada de apresentação de forma independente Linguagem de marcação embarcada dentro do html (Designers :D) !"#$%&'"( ! "#$%&%'()%()*+,-%(.#($)"("*'&+,-*(%(/'%(-%$%(,'.#$#'.,#'0#1 ! 2,-3#&45(,'.#$#'.,#'0#5(61307)8 ! 9#'+/%:#(,'.#$#'.,#'0#(6;$%&%(.,5#<%.4=8 44 Templates Residência de Reuso - 2011.1 - Recife/PE Baseia-se em 2 objetos: Template String a ser devolvida pelo HttpResponse (geralmente HTML) com alguns marcadores especiais de Django. Context Um dicionário com os valores a serem renderizados no Template. !"#$%&'"( ! "#$%&'&($#($)*'$+,*'$)#$*%-#.*'/$0#1,2&.#34$5$6*(.#7.348 ! 9($*%-#.*$!"#$%&'"34$:*(+#(#$#2$(')*+,$)#$'&2;)&$<=#$ <=#>#1*'$)#?*2?#>$#($#2$@A,B#',*('#$3(*>1&21#(.#$ @0CD4E$,#>*$;(:2=5#()*$#+<=#.&'$#',#:;&2#'$)#$F-&(G*8 ! 9($*%-#.*$-.+'"/'34$:*(+#(#$=($0*11*.+&)*.$:*($2*'$ ?&2*>#'$<=#$)&($:*(.#7.*$&$=(&$,2&(+22&E$2*'$<=#$)#%#($ ='&>'#$,&>&$>#()#>;H&>$=($*%-#.*$0#1,2&.#348 "Bienvenido, {{ user }}." {'user': 'alatar'} 0#1,2&.#/ 6*(.#7./ "Bienvenido, alatar." 45 Exemplo 1 Residência de Reuso - 2011.1 - Recife/PE !"#$%&'"( from django.http import HttpResponse from django.template import Template, Context from datetime import datetime PLANTILLA = """<html><body> Son las {{ hora }}. </body></html>""" def hora_actual(request): now = datetime.now() t = Template(PLANTILLA) c = Context({'hora': now}) html = t.render(c) return HttpResponse(html) ! )*+#"*&"#$%&'()#*(+,"#-"&./012&3"!"#$%&'",-,./0'"1':( 46 Exemplo 2 Residência de Reuso - 2011.1 - Recife/PE !"#$%&'"( ! )"*+,-&"#$%&'()#*(+,"#-"&./012&3".$",/0123"&-/0124%.("/0 from django.http import HttpResponse from django.template import Template, Context from datetime import datetime def hora_actual(request): now = datetime.now() fp = open('/home/django/templates/hora.html') t = Template(fp.read()) fp.close() c = Context({'hora': now}) html = t.render(c) return HttpResponse(html) :| 47 Exemplo 3 Residência de Reuso - 2011.1 - Recife/PE !"#$%&'"( ! !")*")&"#$%&'()#*(+,"#-"&./012&3"+"','"#$%&'"-. from django.http import HttpResponse from django.template.loader import get_template from django.template import Context from datetime import datetime def hora_actual(request): now = datetime.now() t = get_template('hora.html') c = Context({'hora': now}) html = t.render(c) return HttpResponse(html) TEMPLATE_DIRS = ( '/home/django/templates', ) 405,647$8 :) 48 Exemplo 3 Residência de Reuso - 2011.1 - Recife/PE !"#$%&'"( ! !")*")&"#$%&'()#*(+,"#-"&./012&3"+"','"#$%&'"-. from django.http import HttpResponse from django.template.loader import get_template from django.template import Context from datetime import datetime def hora_actual(request): now = datetime.now() t = get_template('hora.html') c = Context({'hora': now}) html = t.render(c) return HttpResponse(html) TEMPLATE_DIRS = ( '/home/django/templates', ) 405,647$8 :D 49 Exemplo 4 Residência de Reuso - 2011.1 - Recife/PE !"#$%&'"( ! "#$%&'()*+,*-.*/(0))"*+"),'-,)"($-*("./ from django.shortcuts import render_to_response from datetime import datetime def hora_actual(request): now = datetime.now() return render_to_response('hora.html', {'hora': now}) :O 50 Lembrete! Residência de Reuso - 2011.1 - Recife/PE !"#$%&'"()*!+$ TEMPLATE_DIRS = ( '/home/django/templates', ) !"#$%!&'( )"* !+,-". +''!/ &, -, 0 1+.2+3'"4+./templates."!.,*!2+5+.5"$436.5".2+5+.+''& 0 76$89"$".9$2-*93.*$+.2+3'"4+.26$."-.$6:,3".5".-+.+''.'63.2-+395+5& TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.load_template_source', 'django.template.loaders.app_directories.load_template_source', ) return render_to_response('website/index.html') ;-4"3$+<8+.3"*<-9=+,-"> !"#$%&'"()*!+$ TEMPLATE_DIRS = ( '/home/django/templates', ) !"#$%!&'( )"* !+,-". +''!/ &, -, 0 1+.2+3'"4+./templates."!.,*!2+5+.5"$436.5".2+5+.+''& 0 76$89"$".9$2-*93.*$+.2+3'"4+.26$."-.$6:,3".5".-+.+''.'63.2-+395+5& TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.load_template_source', 'django.template.loaders.app_directories.load_template_source',) return render_to_response('website/index.html') ;-4"3$+<8+.3"*<-9=+,-"> !"#$%&'"()*!+$ TEMPLATE_DIRS = ( '/home/django/templates', ) !"#$%!&'( )"* !+,-". +''!/ &, -, 0 1+.2+3'"4+./templates."!.,*!2+5+.5"$436.5".2+5+.+''& 0 76$89"$".9$2-*93.*$+.2+3'"4+.26$."-.$6:,3".5".-+.+''.'63.2-+395+5& TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.load_template_source', 'django.template.loaders.app_directories.load_template_source', ) return render_to_response('website/index.html') ;-4"3$+<8+.3"*<-9=+,-"> !"#$%&'"()*!+$ TEMPLATE_DIRS = ( '/home/django/templates', ) !"#$%!&'( )"* !+,-". +''!/ &, -, 0 1+.2+3'"4+./templates."!.,*!2+5+.5"$436.5".2+5+.+''& 0 76$89"$".9$2-*93.*$+.2+3'"4+.26$."-.$6:,3".5".-+.+''.'63.2-+395+5& TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.load_template_source', 'django.template.loaders.app_directories.load_template_source', ) return render_to_response('website/index.html') ;-4"3$+<8+.3"*<-9=+,-"> 51 Templates: {{}} Residência de Reuso - 2011.1 - Recife/PE Sintaxe simples de templates Desacoplado de Python HTML com anabolizantes Extensível Designers vão se apaixonar! !"#$%&'"()*++,, <html> <head>Ejemplo templates</head> <body> Hola, {{ username }}. </body> </html> {'username': 'juan'} <html> <head>Ejemplo templates</head> <body> Hola, juan. </body> </html> Templates não podem executar código Python!!!! 52 Templates: {{}} Residência de Reuso - 2011.1 - Recife/PE !"#$%&'()(*+,' Tags 53 Tags Residência de Reuso - 2011.1 - Recife/PE !"#$%&'"()*'&+(*,-*-. {% comment %} Bu! {% endcomment %}/0##"1' 203 {% for elemento in lista %} <li>{{ elemento }}<li> {% endfor %} 42 {% if username == "Juan" %} Hola Juan, me gustas! {% else %} Hola {{ username }}, {% endif %} == != > < >= <= in and or not 54 Filters Residência de Reuso - 2011.1 - Recife/PE !"#$%&'"()*+,%'"-( <html> <head>Ejemplo templates</head> <body> Hola, {{ username|title }}. </body> </html> {'username': 'juan'} <html> <head>Ejemplo templates</head> <body> Hola, Juan. </body> </html> .'%" 55 Filters Residência de Reuso - 2011.1 - Recife/PE !"#$%&'"()*+,%'"-( {'value': 123456789} {{ value|add:”1” }}&.. 123456790 {{ value|filesizeformat }}/%"(,0"12-#&' 117.7MB {'date': datetime.datetime(2010, 9, 11, 17, 1, 59, 385323) } {{ date|date:”d M Y” }}.&'" 11 Sep 2010 {{ date|timesince }}3#"(,45" 4 days, 6 hours {{ date|timeuntil }}3#"643% 1 days, 6 hours 56 Modelos Residência de Reuso - 2011.1 - Recife/PE Nós temos objetos e queremos persistí-los Mapeamento entre Objetos e tabelas Django tem ORM! 57 Eu crio classes e objetos Residência de Reuso - 2011.1 - Recife/PE !"#$%" from django.db import models class Books(models.Model): name = models.CharField(blank=True, max_length=100) created = models.DateTimeField(blank=False) available = models.BooleanField(default=True) !"&'#$($'#$')*+",-./0 !"#$%&'()*"$*+,-.+-,/*"0$"'&1),(/.'2&"1$'23*)+43 !"#$%&'()*"3$453*))*"'$4"!"#$"%&&'()&*"+'(,*-.&/"01$2223 !"6'*)+"0$%&'.'2&"0$4"()0$4)"!4#"50%6*478"'(,*9/#(*(:)3" 58 O ORM converte para SQL Residência de Reuso - 2011.1 - Recife/PE !"#$%&'(&)$*+, BEGIN; CREATE TABLE "website_books" ( "id" integer NOT NULL PRIMARY KEY, "name" varchar(100) NOT NULL, "created" datetime NOT NULL, "available" bool NOT NULL ); COMMIT; BEGIN; CREATE TABLE "website_books" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(100) NOT NULL, "created" timestamp with time zone NOT NULL, "available" boolean NOT NULL ); COMMIT; 59 Com 1 comando! Residência de Reuso - 2011.1 - Recife/PE $ python manage.py syncdb 60 Configure o seu banco Residência de Reuso - 2011.1 - Recife/PE !"#$%&'(')*+,#%*-./ DATABASE_ENGINE = 'sqlite3' DATABASE_NAME = 'db.sqlite' DATABASE_USER = '' DATABASE_PASSWORD = '' DATABASE_HOST = '' DATABASE_PORT = '' settings.py 61 e se alterar os modelos ? Residência de Reuso - 2011.1 - Recife/PE Não atualiza os esquemas existentes! :( GoHorse: Dropa na mão e rexecuta syncdb! south desed django-evolution yasdel Ou aplicações externas: 62 Exemplo Residência de Reuso - 2011.1 - Recife/PE !"#$%& $ python manage.py syncdb Creating table auth_permission Creating table auth_group Creating table auth_user Creating table auth_message Creating table django_content_type Creating table django_session Creating table django_site Creating table website_tweet 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 'neo'): admin E-mail address: user@example.com Password: Password (again): Superuser created successfully. Installing index for auth.Permission model Installing index for auth.Message model Installing index for website.Tweet model 63 Exercício 03 Residência de Reuso - 2011.1 - Recife/PE Criar o backend da sua app seminarios Vamos usar o sqlite3 64 Exemplo Residência de Reuso - 2011.1 - Recife/PE Hora de fazer montar consultas! 65 ORM- Consultas Residência de Reuso - 2011.1 - Recife/PE $ python manage.py shell select * from publisher; !"#$%&'()*+,#,(-#*(./0 ts = Publisher.objects.all() Model Manager QuerySet 66 ORM- Consultas Residência de Reuso - 2011.1 - Recife/PE !"#$%&'())*+%,&-#))./ class Publisher(models.Model): ... def __unicode__(self): return self.name >>> Publisher.objects.all() [<Publisher: Publisher object>] >>> Publisher.objects.all() [<Publisher: Apress>] 67 ORM- Inserção Residência de Reuso - 2011.1 - Recife/PE !"#$%& >>> p = Publisher( ... name='Apress', ... address='2855 Telegraph Avenue', ... city='Berkeley', ... state_province='CA', ... country='U.S.A.', ... website='http://www.apress.com/') >>> p.save() !" o = Model(...) o.save() 68 ORM- Atualização Residência de Reuso - 2011.1 - Recife/PE !"#$%& >>> ... >>> p.id 52 >>> p.name = 'Apress Publishing' >>> p.save() o.save() ! !"#$%& >>> Publisher.objects.all().update(country='USA') 2 >>> ... >>> p.id 52 >>> p.name = 'Apress Publishing' >>> p.save() o.save() queryset.update(...) ! " 69 ORM- Deleção Residência de Reuso - 2011.1 - Recife/PE !"#"$" >>> ps = Publisher.objects.all() >>> ps.delete() >>> ... >>> p.id 52 >>> p.delete() o.delete() queryset.delete() ! " !"#"$" >>> ps = Publisher.objects.all() >>> ps.delete() >>> ... >>> p.id 52 >>> p.delete() o.delete() queryset.delete() ! " 70 Select 1 resultado Residência de Reuso - 2011.1 - Recife/PE !"#"$%&'(&)&*(+,-./'0 >>> Publisher.objects.get(name="Apress") <Publisher: Apress> .get(...) >>> Publisher.objects.get(country="U.S.A.") Traceback (most recent call last): ... MultipleObjectsReturned: get() returned more than one Publisher -- it returned 2! Lookup parameters were {'country': 'U.S.A.'} >>> Publisher.objects.get(name="Anaya") Traceback (most recent call last): ... DoesNotExist: Publisher matching query does not exist. !"#"$%&'(&)&*(+,-./'0 >>> Publisher.objects.get(name="Apress") <Publisher: Apress> .get(...) >>> Publisher.objects.get(country="U.S.A.") Traceback (most recent call last): ... MultipleObjectsReturned:get() returned more than one Publisher -- it returned 2! Lookup parameters were {'country': 'U.S.A.'} >>> Publisher.objects.get(name="Anaya") Traceback (most recent call last): ... DoesNotExist: Publisher matching query does not exist. !"#"$%&'(&)&*(+,-./'0 >>> Publisher.objects.get(name="Apress") <Publisher: Apress> .get(...) >>> Publisher.objects.get(country="U.S.A.") Traceback (most recent call last): ... MultipleObjectsReturned: get() returned more than one Publisher -- it returned 2! Lookup parameters were {'country': 'U.S.A.'} >>> Publisher.objects.get(name="Anaya") Traceback (most recent call last): ... DoesNotExist: Publisher matching query does not exist. 71 Select n resultados Residência de Reuso - 2011.1 - Recife/PE !"#"$%&'(&)&*(+,-./'0+ >>> Publisher.objects.all() [<Publisher: Apress>, <Publisher: O'Reilly>] .all() >>> Publisher.objects.filter( country="U.S.A.", state_province="CA") [<Publisher: Apress>] .filter(...) !"#"$%&'(&)&*(+,-./'0+ >>> Publisher.objects.all() [<Publisher: Apress>, <Publisher: O'Reilly>] .all() >>> Publisher.objects.filter( country="U.S.A.", state_province="CA") [<Publisher: Apress>] .filter(...) !"#"$%&'(&)&*(+,-./'0+ >>> Publisher.objects.all() [<Publisher: Apress>, <Publisher: O'Reilly>] .all() >>> Publisher.objects.filter( country="U.S.A.", state_province="CA") [<Publisher: Apress>] .filter(...) RETORNAM QUERYSETS e não LISTAS! 72 Manipulação de consultas Residência de Reuso - 2011.1 - Recife/PE !"#$%&'()#"*$%'+'",-)./"$% Modelo.objects.filter(campo1="valor1", campo2="valor2") !"#$%&'()*+'"#$%,*-*.$/.-/0&'$),01"$)(#$2,*$/3,&4-&-$567 campo__exact='' campo__iexact='' campo__contains='' campo__icontains='' campo__isnull=T|F campo__day=31 campo__gt=0 campo__gte=0 campo__lt=0 campo__lte=0 campo__in=[ ,] campo__month=12 campo__startswith='' campo__istartswith='' campo__endswith='' campo__iendswith='' campo__range=( ,) campo__year=2010 !"#$%&'()#"*$%'+'",-)./"$% Modelo.objects.filter(campo1="valor1", campo2="valor2") !"#$%&'()*+'"#$%,*-*.$/.-/0&'$),01"$)(#$2,*$/3,&4-&-$567 campo__exact='' campo__iexact='' campo__contains='' campo__icontains='' campo__isnull=T|F campo__day=31 campo__gt=0 campo__gte=0 campo__lt=0 campo__lte=0 campo__in=[ ,] campo__month=12 campo__startswith='' campo__istartswith='' campo__endswith='' campo__iendswith='' campo__range=( ,) campo__year=2010 73 Order By Residência de Reuso - 2011.1 - Recife/PE !"#$"%&' >>> Publisher.objects.order_by("name") [<Publisher: Apress>, <Publisher: O'Reilly>] .order_by(...) >>> Publisher.objects.order_by("-name") [<Publisher: O'Reilly>, <Publisher: Apress>] >>> Publisher.objects.order_by("-name", "country") [<Publisher: O'Reilly>, <Publisher: Apress>] !"#$%#&'()*+%,'- !"#$"%&' >>> Publisher.objects.order_by("name") [<Publisher: Apress>, <Publisher: O'Reilly>] .order_by(...) >>> Publisher.objects.order_by("-name") [<Publisher: O'Reilly>, <Publisher: Apress>] >>> Publisher.objects.order_by("-name", "country") [<Publisher: O'Reilly>, <Publisher: Apress>] !"#$%#&'()*+%,'- 74 Relacionamentos One-to-One Residência de Reuso - 2011.1 - Recife/PE !"#$%"&'()*"+%, OneToOneField class Coche(models.Model): motor = OneToOneField(Motor) class Motor(models.Model): ... >>> c.motor <Motor: Motor object> >>> m.coche <Coche: Coche object> !"#$%&'()$%(&*)&+,*)-.#/&0,(0,&*)(&./(1)/-.)(2 3+)-.)(&)&/%(%1+%( 3+)-.)(&)&-*$./0 4 4 1 1 !"#$%"&'()*"+%, OneToOneField class Coche(models.Model): motor = OneToOneField(Motor) class Motor(models.Model): ... >>> c.motor <Motor: Motor object> >>> m.coche <Coche: Coche object> !"#$%&'()$%(&*)&+,*)-.#/&0,(0,&*)(&./(1)/-.)(2 3+)-.)(&)&/%(%1+%( 3+)-.)(&)&-*$./0 4 4 !"#$%"&'()*"+%, OneToOneField class Coche(models.Model): motor = OneToOneField(Motor) class Motor(models.Model): ... >>> c.motor <Motor: Motor object> >>> m.coche <Coche: Coche object> !"#$%&'()$%(&*)&+,*)-.#/&0,(0,&*)(&./(1)/-.)(2 3+)-.)(&)&/%(%1+%( 3+)-.)(&)&-*$./0 4 4 !"#$%"&'()*"+%, OneToOneField class Coche(models.Model): motor = OneToOneField(Motor) class Motor(models.Model): ... >>> c.motor <Motor: Motor object> >>> m.coche <Coche: Coche object> !"#$%&'()$%(&*)&+,*)-.#/&0,(0,&*)(&./(1)/-.)(2 3+)-.)(&)&/%(%1+%( 3+)-.)(&)&-*$./0 4 4 75 Relacionamentos One-to-Many Residência de Reuso - 2011.1 - Recife/PE 1 n !"#$%"&'()*"+%, ForeignKeyField class Blog(models.Model): ... class Post(models.Model): blog = ForeignKeyField(Blog) >>> p.blog <Blog: Blog object> >>> b.post_set.all() [<Post: Post object>, ...] !"#$%&'()$%(&*)&+,*)-.#/&0,(0,&*)(&./(1)/-.)(2 3+)-.)(&)&/%(%1+%( 3+)-.)(&)&-*$./0 4 / !"#$%"&'()*"+%, ForeignKeyField class Blog(models.Model): ... class Post(models.Model): blog = ForeignKeyField(Blog) >>> p.blog <Blog: Blog object> >>> b.post_set.all() [<Post: Post object>, ...] !"#$%&'()$%(&*)&+,*)-.#/&0,(0,&*)(&./(1)/-.)(2 3+)-.)(&)&/%(%1+%( 3+)-.)(&)&-*$./0 4 / !"#$%"&'()*"+%, ForeignKeyField class Blog(models.Model): ... class Post(models.Model): blog = ForeignKeyField(Blog) >>> p.blog <Blog: Blog object> >>> b.post_set.all() [<Post: Post object>, ...] !"#$%&'()$%(&*)&+,*)-.#/&0,(0,&*)(&./(1)/-.)(2 3+)-.)(&)&/%(%1+%( 3+)-.)(&)&-*$./0 4 / !"#$%"&'()*"+%, ForeignKeyField class Blog(models.Model): ... class Post(models.Model): blog = ForeignKeyField(Blog) >>> p.blog <Blog: Blog object> >>> b.post_set.all() [<Post: Post object>, ...] !"#$%&'()$%(&*)&+,*)-.#/&0,(0,&*)(&./(1)/-.)(2 3+)-.)(&)&/%(%1+%( 3+)-.)(&)&-*$./0 4 / 76 Relacionamentos Many-to-Many Residência de Reuso - 2011.1 - Recife/PE m n !"#$%"&'()*"+%, ManyToManyField class Post(models.Model): tags = ManyToManyField(Tag) class Tag(models.Model): ... >>> p.tags.add(t1, t2) >>> p.tags.all() [<Tag: Tag object>, ...] >>> t.post_set.add(p1, p2) >>> t.post_set.all() [<Post: Post object>, ...] !"#$%&'()$%(&*)&+,*)-.#/&0,(0,&*)(&./(1)/-.)(2 3+)-.)(&)&/%(%1+%( 3+)-.)(&)&-*$./0 / $ !"#$%"&'()*"+%, ManyToManyField class Post(models.Model): tags = ManyToManyField(Tag) class Tag(models.Model): ... >>> p.tags.add(t1, t2) >>> p.tags.all() [<Tag: Tag object>, ...] >>> t.post_set.add(p1, p2) >>> t.post_set.all() [<Post: Post object>, ...] !"#$%&'()$%(&*)&+,*)-.#/&0,(0,&*)(&./(1)/-.)(2 3+)-.)(&)&/%(%1+%( 3+)-.)(&)&-*$./0 / $ !"#$%"&'()*"+%, ManyToManyField class Post(models.Model): tags = ManyToManyField(Tag) class Tag(models.Model): ... >>> p.tags.add(t1, t2) >>> p.tags.all() [<Tag: Tag object>, ...] >>> t.post_set.add(p1, p2) >>> t.post_set.all() [<Post: Post object>, ...] !"#$%&'()$%(&*)&+,*)-.#/&0,(0,&*)(&./(1)/-.)(2 3+)-.)(&)&/%(%1+%( 3+)-.)(&)&-*$./0 / $ !"#$%"&'()*"+%, ManyToManyField class Post(models.Model): tags = ManyToManyField(Tag) class Tag(models.Model): ... >>> p.tags.add(t1, t2) >>> p.tags.all() [<Tag: Tag object>, ...] >>> t.post_set.add(p1, p2) >>> t.post_set.all() [<Post: Post object>, ...] !"#$%&'()$%(&*)&+,*)-.#/&0,(0,&*)(&./(1)/-.)(2 3+)-.)(&)&/%(%1+%( 3+)-.)(&)&-*$./0 / $ 77 Ponteiros inversos Residência de Reuso - 2011.1 - Recife/PE 1 n !"#$%"&'()*"+%, !"#$%&'(#)**'(#+%&),%(#-"./0)-$-#)*#+-"$).%#/"0).(% class Blog(models.Model): ... class Post(models.Model): blog = ForeignKeyField(Blog, related_name='posts') >>> p.blog <Blog:Blog object> >>> b.posts.all() [<Post: Post object>, ...] !"#$%#&'#'()&)*")& !"#$%#&'#'1*$.2/ + ( 1-'"&%#2'3'#3'-"#$+4/.",'".%-"'3'0/&"#/,4#().5#/)#42$%/-4/ !"#$%"&'()*"+%, !"#$%&'(#)**'(#+%&),%(#-"./0)-$-#)*#+-"$).%#/"0).(% class Blog(models.Model): ... class Post(models.Model): blog = ForeignKeyField(Blog, related_name='posts') >>> p.blog <Blog: Blog object> >>> b.posts.all() [<Post: Post object>, ...] !"#$%#&'#'()&)*")& !"#$%#&'#'1*$.2/ + ( 1-'"&%#2'3'#3'-"#$+4/.",'".%-"'3'0/&"#/,4#().5#/)#42$%/-4/ !"#$%"&'()*"+%, !"#$%&'(#)**'(#+%&),%(#-"./0)-$-#)*#+-"$).%#/"0).(% class Blog(models.Model): ... class Post(models.Model): blog = ForeignKeyField(Blog, related_name='posts') >>> p.blog <Blog: Blog object> >>> b.posts.all() [<Post: Post object>, ...] !"#$%#&'#'()&)*")& !"#$%#&'#'1*$.2/ + ( 1-'"&%#2'3'#3'-"#$+4/.",'".%-"'3'0/&"#/,4#().5#/)#42$%/-4/ !"#$%"&'()*"+%, !"#$%&'(#)**'(#+%&),%(#-"./0)-$-#)*#+-"$).%#/"0).(% class Blog(models.Model): ... class Post(models.Model): blog = ForeignKeyField(Blog, related_name='posts') >>> p.blog <Blog: Blog object> >>> b.posts.all() [<Post: Post object>, ...] !"#$%#&'#'()&)*")& !"#$%#&'#'1*$.2/ + ( 1-'"&%#2'3'#3'-"#$+4/.",'".%-"'3'0/&"#/,4#().5#/)#42$%/-4/ 78 Laziness Residência de Reuso - 2011.1 - Recife/PE Otimização!! Consulta só realizada quando necessário! !"#$%&'' ! "#$%&'($)*+#$%'()*%$,%,-,&)+#./(%&)#(0'%.,#*1,(+,%$,% (,&,$2+,%'3+,(,.%*'$%'3-,+'$4%5(%*#$%$26)2,(+,$%$2+)#&2'(,$7 ! 8+,.#&2'(,$ ! 9*2&2(6 ! 9,.2#*2:#&2;( • repr() • len() !!! • list() • bool() for p in Publisher.objects.all(): Publisher.objects.filter(country='USA')[0] <=#&>?@ [<Publisher: Publisher object>] len(Publisher.objects.all()) list(Publisher.objects.all()) if Publisher.objects.filter(country='USA'): !"#$%&'' ! "#$%&'($)*+#$%'()*%$,%,-,&)+#./(%&)#(0'%.,#*1,(+,%$,% (,&,$2+,%'3+,(,.%*'$%'3-,+'$4%5(%*#$%$26)2,(+,$%$2+)#&2'(,$7 ! 8+,.#&2'(,$ ! 9*2&2(6 ! 9,.2#*2:#&2;( • repr() • len() !!! • list() • bool() for p in Publisher.objects.all(): Publisher.objects.filter(country='USA')[0] <=#&>?@ [<Publisher: Publisher object>] len(Publisher.objects.all()) list(Publisher.objects.all()) if Publisher.objects.filter(country='USA'): 79 Exercício 04 Residência de Reuso - 2011.1 - Recife/PE!"#$%&!'()*(+&"(*',(-(+&#./)*(&0&$(1(*( 80 Interface Administrativa Residência de Reuso - 2011.1 - Recife/PE 81 Interface Administrativa Residência de Reuso - 2011.1 - Recife/PE 82 djang.contrib.admin Residência de Reuso - 2011.1 - Recife/PE Instalação 1/3 83 djang.contrib.admin Residência de Reuso - 2011.1 - Recife/PE Instalação 2/3 !"#$%&'#()*$+',$-.#/#0*1$ INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.admin', ... ) !"#$%!&'( 1 84 djang.contrib.admin Residência de Reuso - 2011.1 - Recife/PE Instalação 3/3 !"#$%&'(%)*+,&%,-. $ python manage.py syncdb Creating table django_admin_log Installing index for admin.LogEntry model !"#$%&'$()*&+*,*&-(*, !"#$%&'(%)*+,&%,-. $ python manage.py syncdb Creating table django_admin_log Installing index for admin.LogEntry model !"#$%&'$()*&+*,*&-(*, Acesse http://localhost:8000/admin 85 Opa! Falta registrar os modelos Residência de Reuso - 2011.1 - Recife/PE Criar o módulo admin.py !"#$%&'( ! "#$#%!''%$&'&%$&%(&)&*%&+%,-./0 ! 1&2)&%3-4%5/$&+/,%,&*6)%78,8'+&,%$&,$&%&+%#$58)%.% 9&*58(&%9&*,/)#+8:#*%,-%#,9&;(/0 from django.contrib import admin from website.models import Tweet class TweetAdmin(admin.ModelAdmin): list_display = ('id','user','message','timestamp') admin.site.register(Tweet, TweetAdmin) Cada app deve ter o seu, pode ser configurável! 86 Exercício 04 Residência de Reuso - 2011.1 - Recife/PE!"#$%&'#(") 87 Forms Residência de Reuso - 2011.1 - Recife/PE 3 componentes Widget Componente Visual Field Campo Lógico Form !"#$%$&'()*"+,-#.#$ Widget !"#$"%&%'&()'$+#"(&)*+,-.&%'&(-(/012 TextInput CheckboxInput <input type='text'...> <input type='checkbox'...> Field /01',#(3&(*%(4-#$"5(-6"4+-3"(-(*%(7+38&' EmailField IPAddressField widget, initial, error, ... Form !*(2+(3*(3&(9+&.36(3&(*%(:";#*.-;+" ContactForm [nombre, email, telefono, mensaje, ...] !"#$%$&'()*"+,-#.#$ Widget !"#$"%&%'&()'$+#"(&)*+,-.&%'&(-(/012 TextInput CheckboxInput <input type='text'...> <input type='checkbox'...> Field /01',#(3&(*%(4-#$"5(-6"4+-3"(-(*%(7+38&' EmailField IPAddressField widget, initial, error, ... Form !*(2+(3*(3&(9+&.36(3&(*%(:";#*.-;+" ContactForm [nombre, email, telefono, mensaje, ...] !"#$%$&'()*"+,-#.#$ Widget !"#$"%&%'&()'$+#"(&)*+,-.&%'&(-(/012 TextInput CheckboxInput <input type='text'...> <input type='checkbox'...> Field /01',#(3&(*%(4-#$"5(-6"4+-3"(-(*%(7+38&' EmailField IPAddressField widget, initial, error, ... Form !*(2+(3*(3&(9+&.36(3&(*%(:";#*.-;+" ContactForm [nombre, email, telefono, mensaje, ...] Formulário em si 88 Criação de Formulário Residência de Reuso - 2011.1 - Recife/PE Passo 1: Definição de um formulário forms.py http://docs.djangoproject.com/en/dev/ref/forms/fields/ 89 Criação de Formulário Residência de Reuso - 2011.1 - Recife/PE Passo 2: Definição do template do Formulário contato.html 90 Criação de Formulário Residência de Reuso - 2011.1 - Recife/PE Passo 3: Definição da view do Formulário 91 Criação de Formulário Residência de Reuso - 2011.1 - Recife/PE Forms tem validação própria! Cool :D !"#$%"&$'()*+,*$" from django import forms class ContactForm(forms.Form): subject = forms.CharField(max_length=100) email = forms.EmailField(required=False) message = forms.CharField(widget=forms.Textarea) def clean_message(self): message = self.cleaned_data['message'] num_words = len(message.split()) if num_words < 4: raise forms.ValidationError("Not enough words!") return message !"#$%"&'()"*)+%+)',+-.#+/.01'$23)+'+&"/.+#+'+'/+#+'4.$-#' #$-'5")%6-+)."'$&/).7.$1#"'61'%83"#"'clean_<fieldname>9 92 Forms a partir de Models Residência de Reuso - 2011.1 - Recife/PE Aqui é DRY meu caro!! !"#$%&'&('#)#&*+&,"*+-% from django.db import models class Author(models.Model): name = models.CharField(max_length=100) birth_date = models.DateField(blank=True, null=True) country = models.ModelChoiceField(Country) ... from django import forms from books.models import Author class AuthorForm(forms.ModelForm): class Meta: model = Author exclude = ('country',) !"#$%&'() ."#$%/(0 93 Exercício 04 Residência de Reuso - 2011.1 - Recife/PE !"#$"%"&"'(")" Alguns truques agora... 94 Django Avançado Residência de Reuso - 2011.1 - Recife/PE 1. Middleware 2. Caching 3. Deploying 4. Apps Recomendadas 95 Django Avançado Residência de Reuso - 2011.1 - Recife/PE 1. Middleware 2. Caching 3. Deploying 4. Apps Recomendadas 96 Middleware Residência de Reuso - 2011.1 - Recife/PE Permite incrementar a funcionalidade injetando fluxo de execução em Django !"##$%&'(% !"#$%&'()*&$&#+'),)'$-./+)"/01)202$'&.31)40,1&$ 5.&$#&$)/#&'*0$&/$&1$6.7"$2&$&7&+.+)8/$2&$970/:" 97 Middleware Residência de Reuso - 2011.1 - Recife/PE !"##$%&'(% class MyMiddleware(object): def process_request(self, request):"""Se ejecuta antes de que Django decida a quâˆ!© View llamar. -> HttpRequest(): Se corta el flujo de middleware. -> None: El flujo sigue con el siguiente middleware.""" # ... def process_view(self, request, view_func, view_args, view_kwargs): """Se ejecuta antes de que se llame a la View. -> HttpRequest(): Se corta el flujo de middleware. -> None: El flujo sigue con el siguiente middleware.""" # ... def process_response(self, request, response): """Se ejecuta despuâˆ!©s de que la View devuelva una response. -> HttpResponse()""" # ... def process_exception(self, request, exception): """Se ejecuta cuando una View lanza una excepciâˆ!≥n. -> HttpResponse(). -> None: La excepciâˆ!≥n se propaga hasta el cliente.""" # ... 98 Middleware Residência de Reuso - 2011.1 - Recife/PE !"##$%&'(% !"#"$%&'()"'*#+,)*-'#)"&.-%'$*//,"01-"'"#'",',)21-' ()"'#%&'+%#3"#214')%*"%*#+,%*,-.%*)',%$,+(#%*,#%, %/%-.-"0*,%*,$',1%2.%3),4,%*,$',1%35+*3%5 MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', ) Registrar o middlewares no settings.py 99 Django Avançado Residência de Reuso - 2011.1 - Recife/PE 1. Middleware 2. Caching 3. Deploying 4. Apps Recomendadas 100 Caching Residência de Reuso - 2011.1 - Recife/PE Sempre importante estar aliviando o banco de consultas... !"!#$%& from django.views.decorators.cache import cache_page @cache_page(60 * 15) def my_view(request): ... '$()* !"!#$%& '()*'+,+' >>> from django.core.cache import cache >>> cache.set('my_key', 'hello, world!', 30) >>> cache.get('my_key') 'hello, world!' !"#$%&#'()*)+%*,()-*./-0%,(12#($%(#34%5#(/-%('%(2-%$*('%,0*.06*,7 !(8-%,9:%5' !(;0'5*' !(777 101 Django Avançado Residência de Reuso - 2011.1 - Recife/PE 1. Middleware 2. Caching 3. Deploying 4. Apps Recomendadas 102 Deploying Residência de Reuso - 2011.1 - Recife/PE Por o sistema em produção VirtualEnv + PIP + Fabric 103 Virtualenv Residência de Reuso - 2011.1 - Recife/PE Projeto independente do sistema Ou seja cada projeto com suas dependências específicas !"#$%&'()* !"#$%&%#$%#'()*'+,&-%.)*$%*-)/*-(01%12)/*$%-*/(.%,)3 !4)$)*&1+5%'.+*6%#%*/7*87%9+*$%*-(01%12)/*%#*-)*:%1/(;#*<7%*#%'%/(.) !=(#*,(%$+*)*)'.7)-(>)1 !=(#*,(%$+*)*,(91)1 !%.'333 $ virtualenv --no-site-packages mi_entorno +#(&# Adeus dor de cabeça de migrar, atualizar, etc. !"#$%&'()* !"#$%&%#$%#'()*'+,&-%.)*$%*-)/*-(01%12)/*$%-*/(.%,)3 !4)$)*&1+5%'.+*6%#%*/7*87%9+*$%*-(01%12)/*%#*-)*:%1/(;#*<7%*#%'%/(.) !=(#*,(%$+*)*)'.7)-(>)1 !=(#*,(%$+*)*,(91)1 !%.'333 $ virtualenv --no-site-packages mi_entorno +#(&# $ source mi_entorno/bin/activate &+,*&# 104 Pip Residência de Reuso - 2011.1 - Recife/PE Gerenciador de Pacotes Você pode criar uma lista de requisitos (requirements) para instalação automática! :D !"! !"#$%&'()#(*+,-#%#$()#.($/0.&(12(34 !5#'6/%#(#$*#7/87+'(-9(87:#'&()#(;<=>?;<@<ABC(7&9(-9(./$%+)&()#( *+,-#%#$(+(/9$%+.+'D 4E+90&FF2D1D2 *$G7&*01 H##)*+'$#'FFID2 $%'/*&0'+6FF2DJ "K:+'%L'+**#'FFMDN pip install -E mi_entorno -r REQUIREMENTS !"! !"#$%&'()#(*+,-#%#$()#.($/0.&(12(34 !5#'6/%#(#$*#7/87+'(-9(87:#'&()#(;<=>?;<@<ABC(7&9(-9(./$%+)&()#( *+,-#%#$(+(/9$%+.+'D 4E+90&FF2D1D2 *$G7&*01 H##)*+'$#'FFID2 $%'/*&0'+6FF2DJ "K:+'%L'+**#'FFMDN pip install -E mi_entorno -r REQUIREMENTS 105 Fabric Residência de Reuso - 2011.1 - Recife/PE “Repetition leads to boredom, boredom to horrifying mistakes, horrifying mistakes to God-I-wish-I-was-still-bored” !"#$%& env.user = "example" env.hosts = ["example.com"] def deploy(): run('svn up /home/example/') sudo('/etc/init.d/lighttpd restart') '"#()*+,- Repetition leads to boredom, boredom to horrifying mistakes, horrifying mistakes to God-I-wish-I-was-still-bored“ !"#$%& env.user = "example" env.hosts = ["example.com"] def deploy(): run('svn up /home/example/') sudo('/etc/init.d/lighttpd restart') '"#()*+,- fabric deploy ./0 Repetition leads to boredom, boredom to horrifying mistakes, horrifying mistakes to God-I-wish-I-was-still-bored“ 106 Django Avançado Residência de Reuso - 2011.1 - Recife/PE 1. Middleware 2. Caching 3. Deploying 4. Apps Recomendadas 107 django-registration Residência de Reuso - 2011.1 - Recife/PE Sistema completo de cadastro de usuários DRY!! Instalação Copy and Paste !"#$%&'()%*+,(#-&$ !"#$%%&'(&)*+,(-./0%)&,/1.2(/)3%45610.7/,0'2(/68.1% %6*896(,%*.3#:,(,% %6*896(,%;6*8968.1<+,=>% %?/,0'2(,/% %?/,0'2(,/%*.3#:,(,% %?/,0'2(,/%*:.2,4% %?:.0'1% %?:.0.)(% %?#622@./4%*!610,% %?#622@./4%*!610,%4.1,% %?#622@./4%/,2,(% %?#622@./4%/,2,(%*.1A/3%;(.+,1> %?#622@./4%/,2,(%*.3#:,(,% %?#622@./4%/,2,(%4.1,% %?/,6*896(,% 108 django-socialregistration Residência de Reuso - 2011.1 - Recife/PE O django-registration só que anabolizado! Autenticação com Twitter, Facebook, oAuth, openID Integração perfeita com django.contrib.auth !"#$%&'(&)*#+,-%*(.,#/&$ !"#$%%&'(!)*+,-.%/01!'2&#).#3'2%4502&-61-,'0789&'1(80:-2 ;<-2=&)80,'>2?192,'770 ;@)(92:,0,'>2?,-2$ ;(A'"98B?C0,9*--3B?-0)(!B?-#92'4 ;D2(9&80,'>2?#98C9,(0?,-2?,-2(8'*+0)(! 109 django-piston Residência de Reuso - 2011.1 - Recife/PE Framework Django para construção de serviços RESTful Fácil de instalar !"#$%&'()*+&$ !"#$%%&'(&)*+,(-./0%1,2#,/3%41530.6#'2(.3%7'+'%8.9, :;</59,7./+;#5/5;*/,5/;=>?2;@ABCD)E :;F)G;DH*'E;'32(5E5*'I3 :;B,/'5E'J5*'I3;5$ :KBLMN;O=FPN;>G(!.3;>G*+E,N;QFP;--- :L=)(! :@,*.9,3454.;RRRRR Suporte para YAML, JSON, XML, etc. OAuth !"#$%&'()*+&$ !"#$%%&'(&)*+,(-./0%1,2#,/3%41530.6#'2(.3%7'+'%8.9, :;</59,7./+;#5/5;*/,5/;=>?2;@ABCD)E :;F)G;DH*'E;'32(5E5*'I3 :;B,/'5E'J5*'I3;5$ :KBLMN;O=FPN;>G(!.3;>G*+E,N;QFP;--- :L=)(! :@,*.9,3454.;RRRRR 110 Residência de Reuso - 2011.1 - Recife/PE !"#$%&'"#()*#+,)-)./ Apenas uma ponta do iceberg 111 Lembre-se da comunidade! Residência de Reuso - 2011.1 - Recife/PE http://python.org.br http://djangobrasil.org http://pug-pe.python.org.br #django-br #python-br 112 Trabalho da Semana Residência de Reuso - 2011.1 - Recife/PE Trabalho para 5 pessoas Criar um sistema em Django com o assunto visto até aqui O sistema deve ter no mínimo 10 entidades O sistema deve ter controle de acesso (ver django-registration) Modelagem vocês decidem Apresentar pontos positivos e negativos durante o uso da tecnologia 113 Referências e Créditos Residência de Reuso - 2011.1 - Recife/PE Desenvolvimento web com Python e Django http://www.slideshare.net/igorsobreira/desenvolvimento-web-com-python-e-django Django: Disfruta Programando http://www.slideshare.net/etox/django-eghost-2010 Tutoriais DjangoBrasil http://docs.djangobrasil.org/intro/tutorial01.html 114 Bibliografia Residência de Reuso - 2011.1 - Recife/PE The Definitive Guide to Django: Web Development Done Right. Adrian Holovaty, Jacob K. Ed. Appress ISBN-13: 978-1430219361 Pro Django (1st ed.) Marty Alchin. 2008. . Apress, Berkely, CA, USA. ISBN - 1430210478 Python e Django - Desenvolvimento Ágil de Aplicações Web - Osvaldo Santana Neto e Thiago Galesi; Editora Novatec ISBN. 9788575222478.115 Apresentando Marcel P. Caraciolo caraciol@gmail.com Residência RISE - 2011 116 Exercício 01 Residência de Reuso - 2011.1 - Recife/PE Vamos construir um mini-sistema de submissão de palestras do nosso seminário 1. Criar um projeto seminario 2. Criar uma app trabalhos 3. Criar uma view index redirecionando para uma página html de boas vindas usando templates. 117 Exercício 05 Residência de Reuso - 2011.1 - Recife/PE Vamos criar a nossa interface administrativa para o nossos modelos recém-criados 118 Exercício 04 Residência de Reuso - 2011.1 - Recife/PE Vamos criar os modelos para Trabalho e Palestrante Trabalho usuario: User titulo: String descricao: String slides: File status: Integer name Palestrante *1. * 119 Exercício 02 Residência de Reuso - 2011.1 - Recife/PE Vamos criar 2 novos templates 1.trabalhos.html 2. detalhes.html 120 Exercício 06 Residência de Reuso - 2011.1 - Recife/PE Vamos construir um formulário simples de submissão de palestras! 121
Compartilhar