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 Slide

  2. 1,220,000,000
    results

    View Slide

  3. DON’T
    PANIC

    View Slide

  4. PHP
    Python
    Ruby Java
    JavaScript
    ?

    View Slide

  5. Model
    View Controller

    View Slide

  6. Model
    View Controller

    View Slide

  7. Object-Relational Mapping

    View Slide

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

    View Slide

  9. Model
    View Controller

    View Slide

  10. View Slide

  11. View Slide

  12. Model
    View Controller

    View Slide

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

    View Slide

  14. GET
    POST
    HTTP
    REQUEST

    View Slide

  15. View Slide

  16. Config
    CLI Tools
    Module/Application
    URLs

    View Slide

  17. Model
    View Controller
    Template
    MVT

    View Slide

  18. Model
    Template View

    View Slide

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

    View Slide

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

    View Slide

  21. Model
    Template View

    View Slide

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


    {{ post.title }}

    by {{ post.author }}

    {{ post.content }}

    {{ post.comments }} comments

    {% endfor %}
    {% endblock %}

    View Slide

  23. 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 Slide

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

    {% csrf_token %}

    forms.py
    post_create.html

    View Slide

  25. Model
    Template View

    View Slide

  26. 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 Slide

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

    View Slide

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


    {{ post.title }}

    by {{ post.author }}

    {{ post.content }}

    {{ post.comments }} comments

    {% endfor %}
    {% endblock %}

    View Slide

  29. 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 Slide

  30. View Slide

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

    View Slide

  32. Model
    View Controller

    View Slide

  33. /**
    * 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 Slide

  34. /**
    * @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 Slide

  35. Model
    View Controller

    View Slide

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


    {{ post.title }}

    {{ post.content }}

    {{ post.comments.count }} comments

    {% endfor %}
    {% endblock %}

    View Slide

  37. $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 Slide

  38. Model
    View Controller

    View Slide

  39. 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 Slide

  40. 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 Slide

  41. 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 Slide

  42. View Slide

  43. AJAX RESTful
    API

    View Slide

  44. Micro framework VS Framework

    View Slide

  45. Model
    View Controller

    View Slide

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

    View Slide

  47. 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 Slide

  48. Model
    View Controller

    View Slide

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

    View Slide

  50. Model
    View Controller

    View Slide

  51. 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 Slide

  52. 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 Slide

  53. View Slide

  54. Routes?

    View Slide

  55. PHP
    Python
    Ruby Java
    JavaScript
    MVC

    View Slide

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

    View Slide

  57. 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 Slide

  58. 42

    View Slide

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

    View Slide

  60. So Long, and
    Thanks for
    All the Fish

    View Slide

  61. 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 Slide