Upgrade to Pro — share decks privately, control downloads, hide ads and more …

HHGTTWD

 HHGTTWD

Hitchhiker's Guide to the Web Development

Carlos Hernando

March 21, 2013
Tweet

More Decks by Carlos Hernando

Other Decks in Programming

Transcript

  1. The Hitchhiker's Guide to the
    Web Development
    Carlos Hernando
    @chernando

    View full-size slide

  2. 1,220,000,000
    results

    View full-size slide

  3. DON’T
    PANIC

    View full-size slide

  4. PHP
    Python
    Ruby Java
    JavaScript
    ?

    View full-size slide

  5. Model
    View Controller

    View full-size slide

  6. Model
    View Controller

    View full-size slide

  7. Object-Relational Mapping

    View full-size slide

  8. Object-Relational Mapping
    Post.comments
    SELECT * FROM comment where post_id = 2;

    View full-size slide

  9. Model
    View Controller

    View full-size slide

  10. Model
    View Controller

    View full-size slide

  11. http://www.ticketea.com/try-it-general
    http://www.ticketea.com/
    URL Controller:
    Index
    URL Controller:
    event
    ‘try-it’

    View full-size slide

  12. GET
    POST
    HTTP
    REQUEST

    View full-size slide

  13. Config
    CLI Tools
    Module/Application
    URLs

    View full-size slide

  14. Model
    View Controller
    Template
    MVT

    View full-size slide

  15. Model
    Template View

    View full-size slide

  16. class Post(models.Model):
    title = models.CharField(max_length=45)
    author = models.ForeignKey(AUTH_USER_MODEL)
    content = models.TextField()

    View full-size slide

  17. class Comment(models.Model):
    author = models.ForeignKey(AUTH_USER_MODEL)
    post = models.ForeignKey(Post)
    content = models.TextField()

    View full-size slide

  18. Model
    Template View

    View full-size slide

  19. {% extends "base.html" %}
    {% block content %}
    {% for post in posts %}


    {{ post.title }}

    by {{ post.author }}

    {{ post.content }}

    {{ post.comments }} comments

    {% endfor %}
    {% endblock %}

    View full-size slide

  20. class Post(models.Model):
    title = models.CharField(max_length=45)
    author = models.ForeignKey(AUTH_USER_MODEL)
    content = models.TextField()
    @property
    def comments(self):
    return self.comment_set.count()
    def __unicode__(self):
    return self.title
    def get_absolute_url(self):
    return reverse('post', args=[self.pk])
    ;-(

    View full-size slide

  21. class PostForm(forms.ModelForm):
    class Meta:
    model = Post
    exclude = ('author',)
    method="post">
    {{ form.as_p }}

    {% csrf_token %}

    forms.py
    post_create.html

    View full-size slide

  22. Model
    Template View

    View full-size slide

  23. from . import views
    urlpatterns = patterns('',
    url(r'^$',
    views.index,
    name='index'),
    url(r'^publish/$',
    views.post_create,
    name='publish'),
    url(r'^post/(?P\d+)/$',
    views.post_detail,
    name='post'),
    url(r'^post/(?P\d+)/comment/$',
    views.comment_create,
    name='comment'),
    )

    View full-size slide

  24. def index(request):
    last_posts = Post.objects\
    .order_by('-pk')[:5]
    context = {'posts': last_posts}
    return render(request,
    'blog/post_list.html',
    context)

    View full-size slide

  25. {% extends "base.html" %}
    {% block content %}
    {% for post in posts %}


    {{ post.title }}

    by {{ post.author }}

    {{ post.content }}

    {{ post.comments }} comments

    {% endfor %}
    {% endblock %}

    View full-size slide

  26. def comment_create(request, post_id):
    post = get_object_or_404(Post, pk=post_id)
    form = CommentForm(request.POST or None)
    if form.is_valid():
    comment = Comment()
    comment.author = request.user
    comment.post = post
    comment.content=form.cleaned_data['content']
    comment.save()
    return HttpResponseRedirect(
    post.get_absolute_url())
    else:
    return render(request,
    'blog/post_detail.html',
    {'post': post, 'form': form})

    View full-size slide

  27. Config
    CLI Tools
    Module/Bundle
    Controller
    Model
    Views and Routes

    View full-size slide

  28. Model
    View Controller

    View full-size slide

  29. /**
    * Post
    *
    * @ORM\Table()
    * @ORM\Entity
    */
    class Post
    {
    /**
    * @var integer
    *
    * @ORM\Column(name="id", type="integer")
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    private $id;
    /**
    * @var string
    *
    * @ORM\Column(name="title", type="string", length=45)
    */
    private $title;

    View full-size slide

  30. /**
    * @ORM\OneToMany(targetEntity="Comment", mappedBy="post")
    */
    private $comments;
    /**
    * @ORM\ManyToOne(targetEntity="Post", inversedBy="comments")
    * @ORM\JoinColumn(name="post_id", referencedColumnName="id")
    */
    private $post;
    Post.php
    Comment.php

    View full-size slide

  31. Model
    View Controller

    View full-size slide

  32. {% extends "base.html.twig" %}
    {% block content %}
    {% for post in posts %}


    {{ post.title }}

    {{ post.content }}

    {{ post.comments.count }} comments

    {% endfor %}
    {% endblock %}

    View full-size slide

  33. $post = new Post();
    $form = $this->createFormBuilder($post)
    ->add('title', 'text')
    ->add('content', 'textarea')
    ->getForm();
    method="post">
    {{ form_widget(form) }}


    PostController.php
    detail.html.twig

    View full-size slide

  34. Model
    View Controller

    View full-size slide

  35. try_it_blog_homepage:
    pattern: /
    defaults: {
    _controller: TryItBlogBundle:Post:index }
    try_it_blog_post_create:
    pattern: publish/
    defaults: {
    _controller: TryItBlogBundle:Post:create }
    try_it_blog_post_detail:
    pattern: post/{post_id}/
    defaults: {
    _controller: TryItBlogBundle:Post:detail }
    try_it_blog_comment_create:
    pattern: post/{post_id}/comment/
    defaults: {
    _controller: TryItBlogBundle:Comment:create }

    View full-size slide

  36. class PostController extends Controller
    {
    public function indexAction()
    {
    $posts = $this->getDoctrine()
    ->getRepository('TryItBlogBundle:Post')
    ->findBy(array(), // ALL
    array('id' => 'desc'),
    7);
    return $this->render(
    'TryItBlogBundle:Post:index.html.twig',
    array('posts' => $posts));
    }

    View full-size slide

  37. public function createAction(Request $request)
    {
    /* $post and $form missing */
    if ($request->isMethod('POST')) {
    $form->bind($request);
    if ($form->isValid()) {
    $em = $this->getDoctrine()
    ->getManager();
    $em->persist($post);
    $em->flush();
    return $this->redirect($this
    ->generateUrl('try_it_blog_post_detail',
    array('post_id' => $post->getId())));
    }
    }
    return $this->render(
    'TryItBlogBundle:Post:create.html.twig',
    array('form' => $form->createView()));

    View full-size slide

  38. AJAX RESTful
    API

    View full-size slide

  39. Micro framework VS Framework

    View full-size slide

  40. Model
    View Controller

    View full-size slide

  41. Models.Comment = Backbone.Model.extend({
    });
    Collections.Comments =
    Backbone.Collection.extend({
    model: Models.Comment
    });
    Model
    Collection

    View full-size slide

  42. Models.Post = Backbone.Model.extend({
    defaults: {
    title: 'No title',
    content: 'No content',
    comments: new Collections.Comments()
    },
    initialize: function() {
    this.get('comments').on('all', function() {
    this.trigger('change')
    }, this);
    }
    });
    See fetch!

    View full-size slide

  43. Model
    View Controller

    View full-size slide

  44. Templates.Post = _.template([
    '{{ title }}',
    '',
    '{{ content }}',
    '',
    '',
    '
    Show comments',
    '
    Comment!',
    '',
    ].join(''));

    View full-size slide

  45. Model
    View Controller

    View full-size slide

  46. Views.Post = Backbone.View.extend({
    initialize: function() {
    this.model.on('all', this.render, this);
    this.render();
    },
    render: function() {
    this.$el.html(
    Templates.Post(this.model.toJSON()));
    var n_comments = this.model.get('comments')
    .length;
    this.$el.append($('')
    .html('' + n_comments + ' comments'));
    return this;
    },

    View full-size slide

  47. events: {
    'click .showComments': 'showComments',
    'click .comment': 'createComment'
    },
    showComments: function() {
    var comments = $('#comments');
    var body = comments.find('.modal-body').empty();
    this.model.get('comments').each(
    function(comment) {
    body.append(
    Templates.Comment(comment.toJSON()));
    });
    comments.modal('show');
    },
    createComment: function() {
    var view = new Views.CreateComment(
    { post: this.model });
    },

    View full-size slide

  48. PHP
    Python
    Ruby Java
    JavaScript
    MVC

    View full-size slide

  49. HTML5 / CSS3
    Bootstrap / Boilerplate
    Responsive
    Accessibility
    Developer’s tools
    Sessions
    Migrations
    Database performance
    NoSQL
    Cache
    Load balance
    Deploy
    Scalability
    Security
    ...

    View full-size slide

  50. Web Development
    https://www.udacity.com/course/cs253
    CS169.1x: Software as a Service
    https://www.edx.org/courses/BerkeleyX/CS169.1x/2013_March/about
    HTML5 Game Development
    https://www.udacity.com/course/cs255

    View full-size slide

  51. https://github.com/chernando/
    https://speakerdeck.com/chernando/hhgttwd

    View full-size slide

  52. So Long, and
    Thanks for
    All the Fish

    View full-size slide

  53. ABOUT
    This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0
    Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/
    3.0/.
    Product names, logos and trademarks of other companies which are referenced in this document
    remain the property of those other companies.

    View full-size slide