Slide 1

Slide 1 text

Um raio-x do Django Henrique Bastos PythonBrasil[9] 1

Slide 2

Slide 2 text

henrique@bastos.net @henriquebastos http://henriquebastos.net 2

Slide 3

Slide 3 text

3

Slide 4

Slide 4 text

Django 4

Slide 5

Slide 5 text

“ ” Django é o framework web para perfeccionistas com prazos. #jabá 5

Slide 6

Slide 6 text

Models Django 6

Slide 7

Slide 7 text

“ ” Django é o seu banco de dados na web. #sqn 7

Slide 8

Slide 8 text

Top Down vs Bottom Up 8

Slide 9

Slide 9 text

World Wide What? 9

Slide 10

Slide 10 text

HttpRequest HttpResponse 10

Slide 11

Slide 11 text

$  curl  -­‐iv  http://welcometothedjango.com.br GET  /  HTTP/1.1 User-­‐Agent:  curl/7.19.7  (universal-­‐apple-­‐darwin10.0)  libcurl/7.19.7 Host:  welcometothedjango.com.br Accept:  */*   HTTP Request 11

Slide 12

Slide 12 text

$  curl  -­‐i  http://welcometothedjango.com.br/ HTTP/1.1  200  OK Server:  nginx/0.7.65 Content-­‐Type:  text/html;  charset=utf-­‐8 Cache-­‐Control:  max-­‐age=600        Welcome  to  the  Django  |  Aprendendo  Python  e  Django  na  prática!        

Welcome  to  the  Django

HTTP Response 12

Slide 13

Slide 13 text

django-admin.py startproject myproject Projeto Django 13

Slide 14

Slide 14 text

repo/    manage.py    myproject/    __init__.py    settings.py    urls.py    wsgi.py Estrutura do Projeto 14

Slide 15

Slide 15 text

$  python  manage.py Usage:  manage.py  subcommand  [options]  [args] Options:    -­‐v  VERBOSITY,  -­‐-­‐verbosity=VERBOSITY                                                Verbosity  level;  0=minimal  output,  1=normal  output,                                                2=verbose  output,  3=very  verbose  output    -­‐-­‐settings=SETTINGS      The  Python  path  to  a  settings  module,  e.g.                                                "myproject.settings.main".  If  this  isn't  provided,  the                                                DJANGO_SETTINGS_MODULE  environment  variable  will  be                                                used.    -­‐-­‐pythonpath=PYTHONPATH                                                A  directory  to  add  to  the  Python  path,  e.g.                                                "/home/djangoprojects/myproject".    -­‐-­‐traceback                      Print  traceback  on  exception    -­‐-­‐version                          show  program's  version  number  and  exit    -­‐h,  -­‐-­‐help                        show  this  help  message  and  exit Type  'manage.py  help  '  for  help  on  a  specific  subcommand. Available  subcommands: ... 15

Slide 16

Slide 16 text

Um pacote Python que contém um módulo models.py Django App 16

Slide 17

Slide 17 text

repo/    manage.py    myproject/    __init__.py    settings.py    urls.py    wsgi.py    myapp/        __init__.py        models.py        tests.py        views.py Estrutura da App 17

Slide 18

Slide 18 text

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',        'myproject.myapp', ) myproject/settings.py 18

Slide 19

Slide 19 text

$  manage  runserver Validating  models... 0  errors  found Django  version  1.5.2,  using  settings  'myproject.settings' Development  server  is  running  at  http://127.0.0.1:8000/ Quit  the  server  with  CONTROL-­‐C. 19

Slide 20

Slide 20 text

1. Request Middleware 2. Url Resolve 3. View Middleware 4. View 5. Template Response Middleware 6. Response Middleware Request Handler 20

Slide 21

Slide 21 text

Url Resolve 21

Slide 22

Slide 22 text

URLConf Um módulo que contém uma variável urlpatterns que referencia uma sequência de rotas associadas à views. 22

Slide 23

Slide 23 text

urlpatterns  =  patterns('',        url('^time/plus/1/$',  one_hour_ahead),        url('^time/plus/2/$',  two_hours_ahead),        ...        url('^time/plus/24/$',  tons_hours_ahead), ) Exemplo 23

Slide 24

Slide 24 text

urlpatterns  =  patterns('',        url('^time/plus/(\d{1,2})/$',  time_ahead), ) Bem melhor... 24

Slide 25

Slide 25 text

Expressões Regulares http://docs.python.org/library/re.html#re-syntax http://www.pythonregex.com/ 25

Slide 26

Slide 26 text

URL Resolvers $  manage  shell >>> from django.core.urlresolvers import reverse, resolve >>> resolve('/inscricao/1/') (, ('1',), {}) >>> reverse('myapp:detail', args=[1]) '/inscricao/1/' 26

Slide 27

Slide 27 text

Views Um callable que recebe uma instância de HttpRequest e retorna uma instância de HttpResponse. 27

Slide 28

Slide 28 text

# coding: utf-8 from django.http import HttpResponse def myview(request): return HttpResponse('Opa!') A view mais simples do mundo. 28

Slide 29

Slide 29 text

Anti-patterns Views grandes; Conversões de dados na view; Pilhas de decoradores; Uso de funções auxiliares que instanciam o HttpResponse; Contextos de templates gigantes; 29

Slide 30

Slide 30 text

Forms Muito além de formulários... 30

Slide 31

Slide 31 text

Arquitetura dos Forms Forms Responsável pelo pipeline de validação Fields Valida dados da requisição e os converte para tipos Python Widgets Representa o valor do field em html. 31

Slide 32

Slide 32 text

Form Fields BooleanField CharField ChoiceField TypedChoiceField DateField DateTimeField DecimalField EmailField FileField FilePathField FloatField ImageField IntegerField IPAddressField MultipleChoiceField NullBooleanField RegexField SlugField TimeField URLField 32

Slide 33

Slide 33 text

Form Widgets Input TextInput PasswordInput HiddenInput MultipleHiddenInput FileInput ClearableFileInput Textarea DateInput DateTimeInput TimeInput CheckboxInput Select NullBooleanSelect SelectMultiple RadioInput RadioFieldRenderer RadioSelect CheckboxSelectMultiple MultiWidget 33

Slide 34

Slide 34 text

Anatomia de um FormField 34

Slide 35

Slide 35 text

class IntegerField(Field): default_error_messages = { 'invalid': _(u'Enter a whole number.'), 'max_value': _(u'Ensure this value is less than or equal to %(limit_value)s.'), 'min_value': _(u'Ensure this value is greater than or equal to %(limit_value)s.'), } def __init__(self, max_value=None, min_value=None, *args, **kwargs): super(IntegerField, self).__init__(*args, **kwargs) if max_value is not None: self.validators.append(validators.MaxValueValidator(max_value)) if min_value is not None: self.validators.append(validators.MinValueValidator(min_value)) def to_python(self, value): """ Validates that int() can be called on the input. Returns the result of int(). Returns None for empty values. """ value = super(IntegerField, self).to_python(value) if value in validators.EMPTY_VALUES: return None if self.localize: value = formats.sanitize_separators(value) try: value = int(str(value)) except (ValueError, TypeError): raise ValidationError(self.error_messages['invalid']) return value 35

Slide 36

Slide 36 text

Anatomia de um Widget 36

Slide 37

Slide 37 text

class Textarea(Widget): def __init__(self, attrs=None): # The 'rows' and 'cols' attrs are required for HTML correctness. default_attrs = {'cols': '40', 'rows': '10'} if attrs: default_attrs.update(attrs) super(Textarea, self).__init__(default_attrs) def render(self, name, value, attrs=None): if value is None: value = '' final_attrs = self.build_attrs(attrs, name=name) return format_html('\r\n{1}', flatatt(final_attrs), force_text(value)) 37

Slide 38

Slide 38 text

Bounded SubscriptionForm(request.POST) ou seja, com dados vs Unbounded SubscriptionForm() ou seja, sem dados 38

Slide 39

Slide 39 text

Dentro do form.is_valid() 1. Se Form for bounded... 2. Form full_clean() 3. Para cada Field é executado: 3.1. clean() do Field 3.2. validators do Field 3.3. método clean_* se existir no Form 4. Form clean() 5. errors ou cleaned_data 39

Slide 40

Slide 40 text

Models 40

Slide 41

Slide 41 text

# coding: utf-8 from django.db import models class Subscription(models.Model): name = models.CharField(max_length=100) cpf = models.CharField(max_length=11) email = models.EmailField() phone = models.CharField(max_length=20, blank=True) created_at = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['created_at'] def __unicode__(self): return self.name Model 41

Slide 42

Slide 42 text

CREATE  TABLE  "myapp_subscription"  (        "id"  integer  NOT  NULL  PRIMARY  KEY,        "name"  varchar(100)  NOT  NULL,        "cpf"  varchar(11)  NOT  NULL  UNIQUE,        "email"  varchar(75)  NOT  NULL  UNIQUE,        "phone"  varchar(20)  NOT  NULL,        "created_at"  datetime  NOT  NULL ); 42

Slide 43

Slide 43 text

Cada um no seu quadrado >>>  type(Subscription) ...   >>>  type(Subscription(...)) ...  >>  type(Subscription.objects) ...   >>>  type(Subscription.objects.all()) ...   43

Slide 44

Slide 44 text

Cada um no seu quadrado >>>  Subscription ...  Descreve  a  estrutura  de  uma  tabela >>>  Subscription(...) ...  Corresponde  à  uma  linha  da  tabela >>>  Subscription.objects ...  Manipula  todas  as  linhas  da  tabela >>>  Subscription.objects.all() ...  Acumula  estados  que  serão  usados  pelo  ORM  para ...  compilar  uma  query  SQL 44

Slide 45

Slide 45 text

Model Fields Correlacionam atributos do modelo com colunas da tabela 45

Slide 46

Slide 46 text

Insert e Update 46

Slide 47

Slide 47 text

$  manage  shell >>>  from  myproject.myapp.models  import  Subscription >>>  s  =  Subscription( ...          name="Henrique  Bastos", ...          cpf="12345678901", ...          email="henrique@bastos.net", ...          phone="21-­‐9618-­‐6180") >>>  s.save() 47

Slide 48

Slide 48 text

$  manage  shell >>>  s.id ...  1 >>>  s.pk  #  property  que  neste  caso  retorna  s.id ...  1 >>>  s.phone="234-­‐5678" >>>  s.save()  #  update,  pois  s  já  tem  id 48

Slide 49

Slide 49 text

Seleção e Filtro 49

Slide 50

Slide 50 text

>>>  #  instancia  um  QuerySet >>>  qs  =  Subscription.objects.all()   >>>  #  realiza  a  query  no  banco  apenas  quando  necessário >>>  print  qs [Henrique  Bastos] >>>  qs[0].email  #  retorna  o  email  do  1º  elemento u'henrique@bastos.net' 50

Slide 51

Slide 51 text

Selecionando 1 único objeto >>>  s  =  Subscription.objects.get(name__contains="Bas") >>>  s.phone u'21-­‐9618-­‐6180' 51

Slide 52

Slide 52 text

Filtros >>>  qs  =  Subscription.objects.filter(name__startswith="H") >>>  qs[0].phone u'21-­‐9618-­‐6180' 52

Slide 53

Slide 53 text

Encadeamento >>>  qs  =  Subscription.objects.all() >>>  qs  =  qs.filter(name__contains="Bas") >>>  qs  =  qs.order_by("name") Subscription.objects.filter(name__contains="Bas").order_by("name") 53

Slide 54

Slide 54 text

Field Lookup exact iexact contains icontains in gt gte lt lte startswith istartswith endswith iendswith ... https://docs.djangoproject.com/en/1.5/topics/db/queries/#field-lookups 54

Slide 55

Slide 55 text

Ordenação #  Ascendente Subscription.objects.order_by("name") #  Descendente Subscription.objects.order_by("-­‐name") 55

Slide 56

Slide 56 text

Slicing limita a sua query Subscription.objects.all()[0] Subscription.objects.all()[0:2] Subscription.objects.all()[-­‐1]  #  NOT 56

Slide 57

Slide 57 text

Subscription.objects.all().update(name="Outro  Nome") Subscription.objects.all().delete() Update e Delete múltiplo 57

Slide 58

Slide 58 text

abstract app_label db_table db_tablespace ordering proxy unique_together verbose_name verbose_name_plural ... Meta https://docs.djangoproject.com/en/1.5/ref/models/options/ 58

Slide 59

Slide 59 text

Templates 59

Slide 60

Slide 60 text

Myproject

Parabéns  {{  subscription.name  }}!

Sua  inscrição  foi  realizada  em   {{  subscription.created_at|date:"d/m/Y"  }}.

Em  breve,  alguém  entrará  em  contato  pelo {%  if  subscription.phone  %} telefone  {{  subscription.phone  }}. {%  else  %} e-­‐mail  {{  subscription.email  }}. {%  endif  %}

                  Template Variables 60

Slide 61

Slide 61 text

{{ subscription.name }} 1. subscription["name"] 2. subscription.name 3. subscription.name() O ponto-chave 61

Slide 62

Slide 62 text

Myproject

Parabéns  {{  subscription.name  }}!

Sua  inscrição  foi  realizada  em   {{  subscription.created_at|date:"d/m/Y"  }}.

Em  breve,  alguém  entrará  em  contato  pelo {%  if  subscription.phone  %} telefone  {{  subscription.phone  }}. {%  else  %} e-­‐mail  {{  subscription.email  }}. {%  endif  %}

                  Template Filters 62

Slide 63

Slide 63 text

{{  subscription.created_at|date:"d/m/Y"  }} {{  text|escape|linebreaks  }} {{  text|truncatewords:"30"  }} 63

Slide 64

Slide 64 text

Myproject

Parabéns  {{  subscription.name  }}!

Sua  inscrição  foi  realizada  em   {{  subscription.created_at|date:"d/m/Y"  }}.

Em  breve,  alguém  entrará  em  contato  pelo {%  if  subscription.phone  %} telefone  {{  subscription.phone  }}. {%  else  %} e-­‐mail  {{  subscription.email  }}. {%  endif  %}

                  Template Tags 64

Slide 65

Slide 65 text

# coding: utf-8 from django.http import HttpResponse from django.template import loader, RequestContext def homepage(request): t = loader.get_template('index.html') c = RequestContext(request) content = t.render(c) return HttpResponse(content) Uso de Templates 65

Slide 66

Slide 66 text

Include vs Extends 66

Slide 67

Slide 67 text

67

Slide 68

Slide 68 text

https://docs.djangoproject.com/en/1.5/ref/templates/builtins/ 68