A Scenic Drive through the Django Request-Response Cycle

A Scenic Drive through the Django Request-Response Cycle

Ever wonder how a request gets from your computer, out to the internet, and then back as a response? I did, so I decided to talk about it.

This is the story of how pressing "Enter" on a curl command gets you something back.

Eb091ce308a085ec2ef5b6f10592cb62?s=128

Dan Langer

April 12, 2014
Tweet

Transcript

  1. THE DJANGO REQUEST-RESPONSE CYCLE A Scenic Drive Though Daniel Langer

    daniel@langer.me @dlanger
  2. DANIEL LANGER Je m’appelle Handmade in Toronto

  3. THE DJANGO REQUEST-RESPONSE CYCLE A Scenic Drive Though

  4. LOTS OF THESE Django has http://www.safetysign.com/images/catlog/product/large/J6014.png

  5. CLIENT

  6. THE REQUEST

  7. THE REQUEST $ curl -v http://www.daniellanger.com/hello/mtl/

  8. THE REQUEST $ curl -v http://www.daniellanger.com/hello/mtl/ > GET /hello/mtl/ HTTP/1.1

    > Host: www.daniellanger.com > Accept: */*
  9. http://www.google.com/about/datacenters/gallery/#/all/5 THE INTERNET http://www.google.com/about/datacenters/gallery/#/all/5

  10. THE WEB SERVER http://bit.ly/1jPAhEC

  11. INTERFACE? mod_python FastCGI CGI

  12. WEB SERVER GATEWAY INTERFACE PEP 333 December 2007 Phillip Eby

  13. WEB SERVER GATEWAY INTERFACE def simple_app(environ, start_response): response_headers = [('Content-type',

    'text/plain')] start_response(‘200 OK’, response_headers) return ['Hello world!\n']
  14. DJANGO SPEAKS WSGI class WSGIHandler(base.BaseHandler): def __call__(self, environ, start_response): [...]

    response = self.get_response(request) [...] start_response(status, response_headers) return response
  15. DJANGO.CORE.HANDLERS.BASEHANDLER 1. Request middleware 2. Resolve request.path_info 3. View middleware

    4. View 5. Response middleware * Exception middleware (maybe)
  16. MIDDLEWARE? A small digression

  17. MIDDLEWARE A small digression “[A] light, low-level ‘plugin’ system for

    globally altering Django’s input or output.” - https://docs.djangoproject.com/en/dev/topics/http/middleware/
  18. MIDDLEWARE A small digression MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', [...]

    )
  19. DJANGO.CORE.HANDLERS.BASEHANDLER 1. Request middleware 2. Resolve request.path_info 3. View middleware

    4. View 5. Response middleware * Exception middleware (maybe)
  20. REQUEST MIDDLEWARE class PyConRequestMiddleware(object): def process_request(self, request): return None #

    or HttpResponse
  21. BREAK TIME http://bit.ly/1mNlxWE

  22. CLIENT WEB SERVER WSGI REQUEST Middleware

  23. DJANGO.CORE.HANDLERS.BASEHANDLER 1. Request middleware 2. Resolve request.path_info 3. View middleware

    4. View 5. Response middleware * Exception middleware (maybe)
  24. DJANGO.CORE.URLRESOLVERS http://www.daniellanger.com/hello/mtl/

  25. DJANGO.CORE.URLRESOLVERS http://www.daniellanger.com/hello/mtl/ urlpatterns = patterns('' url(r'^hello/mtl/$', HiMtlView, name=‘hi__mtl’), url(r'^hello/(?P<city>\w+)/$', HiCityView,

    name=‘hi_city’), )
  26. DJANGO.CORE.URLRESOLVERS http://www.daniellanger.com/hello/mtl/ urlpatterns = patterns('' url(r'^hello/(?P<city>\w+)/$', HiCityView, name=‘hi_city’), url(r'^hello/mtl/$', HiMtlView,

    name=‘hi__mtl’), ]
  27. DJANGO.CORE.URLRESOLVERS urlpatterns = patterns('' url(r'^hello/(?P<city>\w+)/$', HiCityView, name=‘hi_city’), ) {% url

    ‘hi_city’ city=ottawa %} reverse(‘hi_city’, kwargs={‘city’: ‘ottawa’}) # Both return http://www.daniellanger.com/hello/ottawa/
  28. DJANGO.CORE.URLRESOLVERS urlpatterns = patterns('' url(r'^cdn_hi/(?P<city>\w+)/$', HiCityView, name=‘hi_city’), ) {% url

    ‘hi_city’ city=ottawa %} reverse(‘hi_city’, kwargs={‘city’: ‘ottawa’}) # Both return http://www.daniellanger.com/cdn_hi/ottawa/
  29. DJANGO.CORE.URLRESOLVERS http://www.daniellanger.com/hello/mtl/ urlpatterns = patterns('' url(r'^hello/mtl/$', HiMtlView, name=‘hi__mtl’), url(r'^hello/(?P<city>\w+)/$', HiCityView,

    name=‘hi_city’), )
  30. DJANGO.CORE.HANDLERS.BASEHANDLER 1. Request middleware 2. Resolve request.path_info 3. View middleware

    4. View 5. Response middleware * Exception middleware (maybe)
  31. DJANGO.CORE.HANDLERS.BASEHANDLER 1. Request middleware 2. Resolve request.path_info 3. View middleware

    4. View 5. Response middleware * Exception middleware (maybe)
  32. VIEWS def HiMtlView(request): html = “Bonjour <b>Mtl</b>!” return HttpResponse(html)

  33. RESPONSES? HttpResponse HttpResponseRedirect JsonResponse StreamingHttpResponse

  34. VIEWS def HiMtlView(request): html = “Bonjour <b>Mtl</b>!” return HttpResponse(html)

  35. CLASS-BASED VIEWS from django.views.generic import View class HiMtlView(View): def get(self,

    request): html = “Bonjour <b>Mtl</b>!” return HttpResponse(html)
  36. TEMPLATES IN VIEWS from django.shortcuts import render def HiMtlView(request): context

    = {‘city’: ‘Montreal’} return render(request, ‘hello.html’, context) # hello.html Bonjour <b>{{ city }}</b>!
  37. TEMPLATES IN VIEWS def HiMtlView(request): context = {‘city’: ‘Montreal’} return

    render(request, ‘hello.html’, context) # hello.html Bonjour <b>{{ city }}</b> (from {{ request_city }}!)
  38. TEMPLATES IN VIEWS def HiMtlView(request): context = { ‘city’: ‘Montreal’,

    ‘request_city’: GeoIP.get_city(request)} return render(request, ‘hello.html’, context) # hello.html Bonjour <b>{{ city }}</b> (from {{ request_city }}!)
  39. CONTEXT PROCESSORS def HiMtlView(request): context = { ‘city’: ‘Montreal’, ‘request_city’:

    GeoIP.get_city(request)} return render(request, ‘hello.html’, context) # hello.html Bonjour <b>{{ city }}</b> (from {{ request_city }}!)
  40. CONTEXT PROCESSORS def request_city(request) return { ‘request_city’: GeoIP.get_city(request), }

  41. CONTEXT PROCESSORS def HiMtlView(request): context = {‘city’: ‘Montreal’} return render(request,

    ‘hello.html’, context) # hello.html Bonjour <b>{{ city }}</b> (from {{ request_city }}!)
  42. The Doe Corporation presents PAUSE PAUSE- CAFE http://www.roadfood.com/photos/20865.jpg

  43. CLIENT WEB SERVER WSGI URL RESOLUTION VIEW REQUEST Middleware VIEW

    Middleware
  44. DJANGO.CORE.HANDLERS.BASEHANDLER 1. Request middleware 2. Resolve request.path_info 3. View middleware

    4. View 5. Response middleware * Exception middleware (maybe)
  45. RESPONSE MIDDLEWARE class PyConResponseMiddleware(object): def process_response(self, request, response): return None

    # or HttpResponse
  46. MIDDLEWARE class PyConMiddleware(object): def process_request(self, request): return None # or

    HttpResponse def process_response(self, request, response): return response # or new HttpResponse
  47. MIDDLEWARE MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'PyConMiddleware', [...] )

  48. DJANGO.CORE.HANDLERS.BASEHANDLER 1. Request middleware 2. Resolve request.path_info 3. View middleware

    4. View 5. Response middleware * Exception middleware (maybe)
  49. EXCEPTION MIDDLEWARE class PyConMiddleware(object): def process_exception(self, request, exception): return None

    # or HttpResponse
  50. WEB SERVER GATEWAY INTERFACE class WSGIHandler(base.BaseHandler): def __call__(self, environ, start_response):

    [...] response = self.get_response(request) [...] start_response(status, response_headers) return response
  51. THE RESPONSE $ curl -v http://www.daniellanger.com/hello/mtl/ > GET /hello/mtl/ HTTP/1.1

    > Host: www.daniellanger.com > Accept: */* < HTTP/1.1 200 OK < Server: nginx < Content-Type: text/html;charset=UTF-8 < Content-Length: 33 Bonjour Montreal! (from Toronto)
  52. CLIENT WEB SERVER WSGI URL RESOLUTION VIEW WSGI WEB SERVER

    CLIENT REQUEST Middleware RESPONSE Middleware VIEW Middleware EXCEPTION Middleware
  53. @dlanger