Slide 1

Slide 1 text

Start on Django Thursday, November 14, 13

Slide 2

Slide 2 text

Quem sou eu?! • Programador globo.com • Entusiasta python e django • #cobrateam • tarsisazevedo.com Thursday, November 14, 13

Slide 3

Slide 3 text

Thursday, November 14, 13

Slide 4

Slide 4 text

Thursday, November 14, 13

Slide 5

Slide 5 text

E voces? • Trabalham com web? • Com algum framework? • E front-end? Thursday, November 14, 13

Slide 6

Slide 6 text

Por que Django? • Framework para perfeccionistas com prazo • O facil é facil • O complexo é possivel • Documentação imensa e boa Thursday, November 14, 13

Slide 7

Slide 7 text

Porque Django? • Comunidade foda • Ecossistema completo Thursday, November 14, 13

Slide 8

Slide 8 text

O que tem pra hoje? Thursday, November 14, 13

Slide 9

Slide 9 text

E o que nao tem! • Testes =/ • Organização de projetos grandes • Modularização de JS Thursday, November 14, 13

Slide 10

Slide 10 text

Bora começar! • mkvirtualenv start-on-django • pip install django south • django-admin.py startproject to_do . • chmod +x manage.py Thursday, November 14, 13

Slide 11

Slide 11 text

Projeto • ./manage.py startapp tasks Thursday, November 14, 13

Slide 12

Slide 12 text

settings.py # Django settings for to_do project. import os PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__)) Thursday, November 14, 13

Slide 13

Slide 13 text

settings.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'to_do.db', 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '', } } Thursday, November 14, 13

Slide 14

Slide 14 text

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', 'tasks', 'south', ) Thursday, November 14, 13

Slide 15

Slide 15 text

O banco! • ./manage.py syncdb Thursday, November 14, 13

Slide 16

Slide 16 text

to-do list? • Tasks • descrição Thursday, November 14, 13

Slide 17

Slide 17 text

tasks/models.py from django.db import models class Task(models.Model): descricao = models.CharField(max_length=255) Thursday, November 14, 13

Slide 18

Slide 18 text

South • ./manage.py schemamigration tasks --initial • ./manage.py migrate Thursday, November 14, 13

Slide 19

Slide 19 text

Ta quase... • ./manage.py runserver Thursday, November 14, 13

Slide 20

Slide 20 text

It Works!!! Thursday, November 14, 13

Slide 21

Slide 21 text

Thursday, November 14, 13

Slide 22

Slide 22 text

Django Admin! • Facil de usar • Facil de extender • Completo Thursday, November 14, 13

Slide 23

Slide 23 text

urls.py from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns( '', # Examples: # url(r'^$', 'to_do.views.home', name='home'), # url(r'^to_do/', include('to_do.foo.urls')), url(r'^admin/', include(admin.site.urls)), ) Thursday, November 14, 13

Slide 24

Slide 24 text

tasks/admin.py from django.contrib import admin from tasks.models import Task admin.site.register(Task) Thursday, November 14, 13

Slide 25

Slide 25 text

Vamos brincar :D Thursday, November 14, 13

Slide 26

Slide 26 text

Thursday, November 14, 13

Slide 27

Slide 27 text

Agora todo o resto • Views • Templates Thursday, November 14, 13

Slide 28

Slide 28 text

Listando Tasks • Generic Views! Thursday, November 14, 13

Slide 29

Slide 29 text

tasks/views.py from django.views.generic import ListView from tasks.models import Task class TaskList(ListView): template_name = 'tasks.html' model = Task Thursday, November 14, 13

Slide 30

Slide 30 text

urls.py from django.conf.urls import patterns, include, url from django.contrib import admin from tasks.views import TaskList admin.autodiscover() urlpatterns = patterns( '', url(r'^$', TaskList.as_view(), name='index'), # url(r'^to_do/', include('to_do.foo.urls')), url(r'^admin/', include(admin.site.urls)), ) Thursday, November 14, 13

Slide 31

Slide 31 text

E entao... Thursday, November 14, 13

Slide 32

Slide 32 text

Vamos arrumar! • mkdir tasks/templates/ • touch tasks/templates/tasks.html Thursday, November 14, 13

Slide 33

Slide 33 text

Client-side :D Thursday, November 14, 13

Slide 34

Slide 34 text

Client-side :D • HTML • CSS • JS Thursday, November 14, 13

Slide 35

Slide 35 text

HTML My Tasks!

My Tasks!

    {% for task in object_list %}
  • {{ task.descricao }}
  • {% endfor %}
Thursday, November 14, 13

Slide 36

Slide 36 text

CSS .grid-12 { width: 1055px; margin: 0 auto; } .titulo { font-family: Helvetica; font-size: 45px; } Thursday, November 14, 13

Slide 37

Slide 37 text

CSS .tasks { font-family: Arial; font-size: 18px; width: 500px; } .tasks .task { border-bottom: 1px solid #dcdcdc; height: 30px; margin-bottom: 5px; line-height: 30px; } Thursday, November 14, 13

Slide 38

Slide 38 text

urls.py from django.conf import settings from django.conf.urls.static import static urlpatterns = patterns( ... ) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) Thursday, November 14, 13

Slide 39

Slide 39 text

Criando tasks! Thursday, November 14, 13

Slide 40

Slide 40 text

tasks/views.py from django.views.generic import ListView, CreateView class TaskCreate(CreateView): model = Task Thursday, November 14, 13

Slide 41

Slide 41 text

urls.py from tasks.views import TaskList, TaskCreate url(r'tasks/create/$', TaskCreate.as_view(), name='create_task'), Thursday, November 14, 13

Slide 42

Slide 42 text

Thursday, November 14, 13

Slide 43

Slide 43 text

Criando o template! • mkdir tasks/templates/tasks/ • touch tasks/templates/tasks/task_form.html Thursday, November 14, 13

Slide 44

Slide 44 text

HTML {% csrf_token %} {{ form.as_ul }} Thursday, November 14, 13

Slide 45

Slide 45 text

Thursday, November 14, 13

Slide 46

Slide 46 text

tasks/views.py class TaskCreate(CreateView): model = Task success_url = '/' Thursday, November 14, 13

Slide 47

Slide 47 text

Thursday, November 14, 13

Slide 48

Slide 48 text

AJAX! Thursday, November 14, 13

Slide 49

Slide 49 text

AJAX? Thursday, November 14, 13

Slide 50

Slide 50 text

Ajax!!! $(document).ready(function(){ $(".adicionar-tarefa").click(function(){ $.ajax({ url: '/tasks/create/', method: 'GET', success: function(data) { $('.tasks').append('<li class="task"></li>'); $('.task:last-child').append(data); } }); return false; }); }); Thursday, November 14, 13

Slide 51

Slide 51 text

CSS .adicionar-tarefa { border: 1px solid black; color: black; display: inline-block; height: 20px; padding: 5px; margin-top: 20px; } .adicionar-tarefa:hover { color: blue; } Thursday, November 14, 13

Slide 52

Slide 52 text

HTML ... Adicionar tarefa ... Thursday, November 14, 13

Slide 53

Slide 53 text

Mais JS $(document).on('click', '.salvar-task', function() { var task = $(this).closest('.task'); var form = $(this).closest('form'); var data_processada = $(form).serialize(); var request = $.ajax({ url: $(form).attr('action'), method: 'POST', data: data_processada }); request.done(function(data) { $(task).html(data); }); return false; }); Thursday, November 14, 13

Slide 54

Slide 54 text

tasks/views.py from django.views.generic import CreateView, DetailView class TaskCreate(CreateView): model = Task class TaskDetail(DetailView): model = Task Thursday, November 14, 13

Slide 55

Slide 55 text

tasks/models.py from django.db import models class Task(models.Model): descricao = models.CharField(max_length=255) def get_absolute_url(self): return "/task/%s/" % self.id Thursday, November 14, 13

Slide 56

Slide 56 text

urls.py from tasks.views import TaskDetail url(r'^task/(?P\w+)/$', TaskDetail.as_view(), name='detail_task'), Thursday, November 14, 13

Slide 57

Slide 57 text

HTML • touch tasks/templates/tasks/ task_detail.html Thursday, November 14, 13

Slide 58

Slide 58 text

HTML {{ object.descricao }} Thursday, November 14, 13

Slide 59

Slide 59 text

Done! Thursday, November 14, 13

Slide 60

Slide 60 text

tasks/models.py from django.db import models class Task(models.Model): ... done = models.BooleanField(default=False) ... Thursday, November 14, 13

Slide 61

Slide 61 text

Thursday, November 14, 13

Slide 62

Slide 62 text

South • Migrando banco! Thursday, November 14, 13

Slide 63

Slide 63 text

South • ./manage.py schemamigration tasks --auto • ./manage.py migrate Thursday, November 14, 13

Slide 64

Slide 64 text

HTML • touch tasks/templates/tasks/task.html Thursday, November 14, 13

Slide 65

Slide 65 text

task.html
  • {% csrf_token %} {{ task.descricao }}
  • Thursday, November 14, 13

    Slide 66

    Slide 66 text

    tasks.html ...
      {% for task in object_list %} {% include "tasks/task.html" %} {% endfor %}
    ... Thursday, November 14, 13

    Slide 67

    Slide 67 text

    CSS ... .task.done { text-decoration: line-through; } ... Thursday, November 14, 13

    Slide 68

    Slide 68 text

    JS $(document).on('click', '.task input[name="done"]', function() { var task = $(this).parent(); var data_processada = $(this).parent().find('input').serialize(); var task_update_url = $(this).data('update-url'); $.ajax({ url: task_update_url, type: 'POST', data: data_processada, success: function(data) { $(task).toggleClass('done'); }, }); $(this).attr('checked', true); }); Thursday, November 14, 13

    Slide 69

    Slide 69 text

    tasks/views.py from django import forms from django.views.generic import ListView, CreateView, DetailView, UpdateView ... class TaskUpdateForm(forms.ModelForm): class Meta: model = Task fields = ['done'] class TaskUpdate(UpdateView): model = Task form_class = TaskUpdateForm Thursday, November 14, 13

    Slide 70

    Slide 70 text

    urls.py ... from tasks.views import TaskList, TaskCreate, TaskDetail, TaskUpdate url(r'^task/(?P\w+)/update/$', TaskUpdate.as_view(), name='update_task'), ... Thursday, November 14, 13

    Slide 71

    Slide 71 text

    E o adicionar?! ... class TaskCreateForm(forms.ModelForm): class Meta: model = Task fields = ['descricao'] class TaskCreate(CreateView): model = Task form_class = TaskCreateForm ... Thursday, November 14, 13

    Slide 72

    Slide 72 text

    E o HTML de add? {% csrf_token %} {{ form.descricao }} Thursday, November 14, 13

    Slide 73

    Slide 73 text

    tasks/task_detail.html {% with object as task %} {% include "tasks/task.html" %} {% endwith %} Thursday, November 14, 13

    Slide 74

    Slide 74 text

    JS $(document).on('click', '.salvar-task', function() { ... request.done(function(data) { $(task).replaceWith(data); }); ... }); Thursday, November 14, 13

    Slide 75

    Slide 75 text

    Arrumando a casa Thursday, November 14, 13

    Slide 76

    Slide 76 text

    tasks/views.py • Extrair os forms! Thursday, November 14, 13

    Slide 77

    Slide 77 text

    tasks/forms.py from django import forms from tasks.models import Task class TaskCreateForm(forms.ModelForm): class Meta: model = Task fields = ['descricao'] class TaskUpdateForm(forms.ModelForm): class Meta: model = Task fields = ['done'] Thursday, November 14, 13

    Slide 78

    Slide 78 text

    tasks/views.py from django.views.generic import ListView, CreateView, DetailView, UpdateView from tasks.forms import TaskCreateForm, TaskUpdateForm from tasks.models import Task class TaskList(ListView): template_name = 'tasks.html' model = Task class TaskCreate(CreateView): model = Task form_class = TaskCreateForm class TaskDetail(DetailView): model = Task class TaskUpdate(UpdateView): model = Task form_class = TaskUpdateForm Thursday, November 14, 13

    Slide 79

    Slide 79 text

    tasks.html • Extrair os JS! Thursday, November 14, 13

    Slide 80

    Slide 80 text

    tasks/static/js/tasks.js $(document).ready(function(){ $(".adicionar-tarefa").click(function(){ $.ajax({ url: '/tasks/create/', method: 'GET', success: function(data) { $('.tasks').append('
  • '); $('.task:last-child').append(data); } }); return false; }); $(document).on('click', '.salvar-task', function() { var task = $(this).closest('.task'); var form = $(this).closest('form'); var data_processada = $(form).serialize(); var request = $.ajax({ url: $(form).attr('action'), method: 'POST', data: data_processada }); request.done(function(data) { $(task).replaceWith(data); }); return false; }); Thursday, November 14, 13

    Slide 81

    Slide 81 text

    tasks/static/js/tasks.js $(document).on('click', '.task input[name="done"]', function() { var task = $(this).parent(); var data_processada = $(this).parent().find('input').serialize(); var task_update_url = $(this).data('update-url'); $.ajax({ url: task_update_url, type: 'POST', data: data_processada, success: function(data) { $(task).toggleClass('done'); }, }); $(this).attr('checked', true); }); }); Thursday, November 14, 13

    Slide 82

    Slide 82 text

    tasks.html My Tasks!

    My Tasks!

      {% for task in object_list %} {% include "tasks/task.html" %} {% endfor %}
    Adicionar tarefa
    Thursday, November 14, 13

    Slide 83

    Slide 83 text

    Apagando! Thursday, November 14, 13

    Slide 84

    Slide 84 text

    task.html
  • {% csrf_token %} {{ task.descricao }} x
  • Thursday, November 14, 13

    Slide 85

    Slide 85 text

    JS $(document).on('click', '.task .delete', function() { var task = $(this).parent(); var task_delete_url = $(this).attr('href'); var request = $.ajax({ url: task_delete_url, type: 'POST', }); request.done(function(data) { $(task).destroy(); }); return false; }); Thursday, November 14, 13

    Slide 86

    Slide 86 text

    urls.py ... from tasks.views import TaskList, TaskCreate, TaskDetail, TaskUpdate, TaskDelete url(r'^task/(?P\w+)/delete/$', TaskDelete.as_view(), name='delete_task'), ... Thursday, November 14, 13

    Slide 87

    Slide 87 text

    tasks/views.py from django.views.generic import ..., DeleteView ... class TaskDelete(DeleteView): model = Task success_url = '/' Thursday, November 14, 13

    Slide 88

    Slide 88 text

    CSS .task .delete { display: inline-block; width: 10px; background: #ddd; font-size: 15px; text-align: center; padding: 0 10px; color: #bbb; text-decoration: none; float: right; } .task .delete:hover { background: #eee; color: black; } Thursday, November 14, 13

    Slide 89

    Slide 89 text

    Categorias! Thursday, November 14, 13

    Slide 90

    Slide 90 text

    tasks/models.py from django.db import models class Categoria(models.Model): nome = models.CharField(max_length=255) class Task(models.Model): descricao = models.CharField(max_length=255) done = models.BooleanField(default=False) categoria = models.ForeignKey(Categoria, blank=True, null=True) def get_absolute_url(self): return "/task/%s/" % self.id Thursday, November 14, 13

    Slide 91

    Slide 91 text

    Banco • ./manage.py schemamigration tasks --auto • ./manage.py migrate tasks Thursday, November 14, 13

    Slide 92

    Slide 92 text

    tasks/forms.py ... class TaskCreateForm(forms.ModelForm): class Meta: model = Task fields = ['descricao', 'categoria'] ... Thursday, November 14, 13

    Slide 93

    Slide 93 text

    task_form.html {% csrf_token %} {{ form.descricao }} {{ form.categoria }} Thursday, November 14, 13

    Slide 94

    Slide 94 text

    task.html ... {{ task.descricao }} {% if task.categoria %} - {{ task.categoria }}{% endif %} ... Thursday, November 14, 13

    Slide 95

    Slide 95 text

    tasks/admin.py ... from tasks.models import Task, Categoria admin.site.register(Categoria) ... Thursday, November 14, 13

    Slide 96

    Slide 96 text

    CSS ... .task .categoria { background-color: #ddd; border-radius: 4px; color: #333; display: inline-block; font-size: 15px; height: 15px; line-height: 15px; padding: 3px; } ... Thursday, November 14, 13

    Slide 97

    Slide 97 text

    E a exibição das categorias?? ... class Categoria(models.Model): nome = models.CharField(max_length=255) def __unicode__(self): return self.nome ... Thursday, November 14, 13

    Slide 98

    Slide 98 text

    Ao infinito... • funcionalidades do django • queryset api • herança de template • apps instalaveis Thursday, November 14, 13

    Slide 99

    Slide 99 text

    E alem! • powerful admin • temas para admin • github • heroku Thursday, November 14, 13

    Slide 100

    Slide 100 text

    Obrigado! tarsisazevedo.com Thursday, November 14, 13