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

DjangoCon Europe 2013 Keynote

DjangoCon Europe 2013 Keynote

Daniel Greenfeld

May 17, 2013
Tweet

More Decks by Daniel Greenfeld

Other Decks in Technology

Transcript

  1. @pydanny
    [email protected]
    Keynote
    DjangoCircus 2013

    View full-size slide

  2. @pydanny
    [email protected]
    Daniel Greenfeld
    Hi everyone. My name is Daniel Greenfeld. I’m the guy with the unenviable task of being the
    keynote after Brandon Rhodes.

    View full-size slide

  3. @pydanny
    [email protected]
    @pydanny
    This is me.

    View full-size slide

  4. @pydanny
    [email protected]
    I work as a principal for Cartwheel Web, doing Python and Django. The company is named
    after cartwheels.

    View full-size slide

  5. @pydanny
    [email protected]
    http://2scoops.org
    Danny: 128,546++
    Audrey: 121,871++
    Co-wrote a book. There is Audrey. She half of the book.

    View full-size slide

  6. @pydanny
    [email protected]
    Django conferences
    have a tradition.
    Django has a tradition.

    View full-size slide

  7. @pydanny
    [email protected]
    e
    Django
    Tradition of
    Invited Critical Talks
    This is where some luminary is invited to give a talk that takes Django to task in some way.

    View full-size slide

  8. @pydanny
    [email protected]
    is Isn’t A
    Hate
    Django
    Talk.
    I’m not giving one of those talks. Why not?

    View full-size slide

  9. @pydanny
    [email protected]
    Negative
    It’s Too Easy
    to be

    View full-size slide

  10. @pydanny
    [email protected]
    Example:
    “Class Based
    Views Suck”
    Saying this is easy. I used to say it all the time. Twitter, IRC, forums

    View full-size slide

  11. @pydanny
    [email protected]
    You Know
    What’s Hard?

    View full-size slide

  12. @pydanny
    [email protected]
    Working
    Stuff
    Delivering

    View full-size slide

  13. @pydanny
    [email protected]
    Rants are
    fun but...

    View full-size slide

  14. @pydanny
    [email protected]
    No one would
    remember Zed Shaw
    if he hadn’t written
    Learn Python the Hard Way*
    *Just one of many of his efforts.

    View full-size slide

  15. @pydanny
    [email protected]
    Contribute
    Get Your Hands
    Dirty and

    View full-size slide

  16. @pydanny
    [email protected]
    Running Events
    Writing Books
    Pull Requests
    Jannis used to say this all the time to me.
    This event is awesome.
    Learn Python the Hard Way. Two Scoops of Django

    View full-size slide

  17. @pydanny
    [email protected]
    is Isn’t A
    Hate
    Django
    Talk.
    So no, this isn’t a rant about Django. Instead...

    View full-size slide

  18. @pydanny
    [email protected]
    Django is Awesome
    ...it’s a celebration about what makes Django awesome. Which was the result of a lot of
    people delivering working stuff. Their hard work has made so much possible.

    View full-size slide

  19. @pydanny
    [email protected]
    Why is Django
    Awesome?

    View full-size slide

  20. @pydanny
    [email protected]
    Reason #1
    Django is Everywhere

    View full-size slide

  21. @pydanny
    [email protected]
    Django Everywhere
    NASA
    Disqus
    Google
    Grove.io
    HP
    IBM
    Instagram
    Mozilla
    Sony
    Cashstar
    BitBucket
    Canonical
    PBS
    National Geographic
    Microsoft
    Humble Bundle
    Django Circus
    djangocon.com
    PBS
    Pinterest
    Rdio
    e Onion
    Library of Congress
    Causes
    Politifact
    OpenStack
    Rackspace
    Discovery Channel
    Newspapers
    Lexis Nexis
    2scoops.org
    Lanyrd
    Gondor

    View full-size slide

  22. @pydanny
    [email protected]
    Django Everywhere
    NASA
    Disqus
    Google
    Grove.io
    HP
    IBM
    Instagram
    Mozilla
    Sony
    Cashstar
    BitBucket
    Canonical
    PBS
    National Geographic
    Microsoft
    Humble Bundle
    Django Circus
    djangocon.com
    PBS
    Pinterest
    Rdio
    e Onion
    Library of Congress
    Causes
    Politifact
    OpenStack
    Rackspace
    Discovery Channel
    Newspapers
    Lexis Nexis
    2scoops.org
    Lanyrd
    Gondor
    Django is used on
    many projects.
    NASA’s Nebula
    begat OpenStack.
    I started with Django while at NASA. One of NASA’s products is Nebula, the god-parent of
    OpenStack.

    View full-size slide

  23. @pydanny
    [email protected]
    Reason #2
    Django is Powered
    by Python

    View full-size slide

  24. @pydanny
    [email protected]
    Python is Awesome

    View full-size slide

  25. @pydanny
    [email protected]
    Python has a
    Style Guide
    PEP-0008

    View full-size slide

  26. @pydanny
    [email protected]
    Python has Zen
    PEP-0020

    View full-size slide

  27. @pydanny
    [email protected]
    Most importantly...

    View full-size slide

  28. @pydanny
    [email protected]
    Python shares the same
    rst two letters as me.
    Python
    Pydanny

    View full-size slide

  29. @pydanny
    [email protected]
    Reason #3
    Django has
    Awesome
    APIs

    View full-size slide

  30. @pydanny
    [email protected]
    API win:
    Understandable
    No funky names besides ‘django’
    models
    views
    templates
    forms
    settings
    admin
    messages
    caching
    logging
    sessions
    No funky names except for Django, which means we don’t have to spend much time memorizing colorful names for common objects.

    View full-size slide

  31. @pydanny
    [email protected]
    Case Study:
    python-requests
    vs.
    django.test.client

    View full-size slide

  32. @pydanny
    [email protected]
    python-requests
    vs.
    django.test.client
    >>> r = requests.get('http://127.0.0.1:8000')
    >>> r.status_code
    200
    >>> params = {'key1': 'value1', 'key2': 'value2'}
    >>> r = requests.get("http://127.0.0.1:8000", params)
    >>> r.status_code
    200
    >>> import requests
    >>> from django.test.client import Client
    >>> requests = Client()
    Can anyone recognize this code? It’s requests in action, right? Nope, it’s the django test
    client!
    Anyway, I think it’s says something when two popular toolsets have similar API designs.

    View full-size slide

  33. @pydanny
    [email protected]
    API Win
    Conventions

    View full-size slide

  34. @pydanny
    [email protected]
    forms.py
    models.py
    views.py
    templates/
    Forms
    Models
    Views
    Templates

    View full-size slide

  35. @pydanny
    [email protected]
    forms.py
    from  django  import  forms
    from  pies.models  import  Pie
     
     
    class  PieForm(forms.ModelForm):
     
           class  Meta:
                   model  =  Pie
                   fields  =  ('filling',  )
    No code names. No puns. No underscores. Intuitive.

    View full-size slide

  36. @pydanny
    [email protected]
    from  django.db  import  models
     
     
    class  Pie(models.Model):
     
           STATUS_UNBAKED,  STATUS_BAKED  =  0,  1
           FILLING_APPLE,  FILLING_MEAT  =  0,  1
           STATUS_CHOICES  =  (
                   (STATUS_UNBAKED,  "Unbaked"),
                   (STATUS_BAKED,  "Baked")
           )
           FILLING_CHOICES  =  (
                   (FILLING_APPLE,  "Apple"),
                   (FILLING_MEAT,  "Meat"),
           )
     
           status  =  models.IntegerField(choices=STATUS_CHOICES,  
                                                   default=STATUS_UNBAKED)
           filling  =  models.IntegerField(choices=FILLING_CHOICES)
     
           def  __unicode__(self):
                   return  "{status}  {filling}  pie".format(
                           status=self.get_status_display(),
                           filling=self.get_filling_display()
                   )
    models.py
    The Pie inherits right from Models. How awesome is that? What about model field definitions?
    Obvious!

    View full-size slide

  37. @pydanny
    [email protected]
    pro-tip
    While
    Fat Models
    are Great
    Fat models are when you move as much logic as possible from views to models, so that you
    can more readily re-use the same code in more than one view. Very commonly between
    HTML and JSON versions of views.

    View full-size slide

  38. @pydanny
    [email protected]
    pro-tip
    Overly Large
    Models
    Are
    Not

    View full-size slide

  39. @pydanny
    [email protected]
    Really.
    class  Package(BaseModel):
           title  =  models.CharField(_("Title"),  max_length="100")
           slug  =  models.SlugField(_("Slug"),  help_text="Enter  a  valid  'slug'  consisting  of  letters,  numbers,  underscores  or  
    hyphens.
    Values  will  be  converted  to  lowercase.",  unique=True)
           category  =  models.ForeignKey(Category,  verbose_name="Installation")
           repo_description  =  models.TextField(_("Repo  Description"),  blank=True)
           repo_url  =  models.URLField(_("repo  URL"),  help_text=repo_url_help_text,  blank=True,  unique=True,  verify_exists=True)
           repo_watchers  =  models.IntegerField(_("repo  watchers"),  default=0)
           repo_forks  =  models.IntegerField(_("repo  forks"),  default=0)
           repo_commits  =  models.IntegerField(_("repo  commits"),  default=0)
           pypi_url  =  models.URLField(_("PyPI  slug"),  help_text=pypi_url_help_text,  blank=True,  default='',  verify_exists=True)
           pypi_downloads  =  models.IntegerField(_("Pypi  downloads"),  default=0)
           participants  =  models.TextField(_("Participants"),
                                                   help_text="List  of  collaborats/participants  on  the  project",  blank=True)
           usage  =  models.ManyToManyField(User,  blank=True)
           created_by  =  models.ForeignKey(User,  blank=True,  null=True,  related_name="creator",  on_delete=models.SET_NULL)
           last_modified_by  =  models.ForeignKey(User,  blank=True,  null=True,  related_name="modifier",  on_delete=models.SET_NULL)
           @property
           def  pypi_version(self):
                   string_ver_list  =  self.version_set.values_list('number',  flat=True)
                   if  string_ver_list:
                           vers_list  =  [versioner(v)  for  v  in  string_ver_list]
                           latest  =  sorted(vers_list)[-­1]
                           return  str(latest)
                   return  ''
           @property
           def  pypi_name(self):
                   """  return  the  pypi  name  of  a  package"""
                   if  not  self.pypi_url.strip():
                           return  ""
                   name  =  self.pypi_url.replace("http://pypi.python.org/pypi/",  "")
                   if  "/"  in  name:
                           return  name[:name.index("/")]
                   return  name
           @property
           def  last_updated(self):
                   try:
                           last_commit  =  self.commit_set.latest('commit_date')
                           if  last_commit:
                                   return  last_commit.commit_date
                   except  ObjectDoesNotExist:
                           pass
                   return  None
           @property
           def  repo(self):
                   return  get_repo_for_repo_url(self.repo_url)
           @property
           def  active_examples(self):
                   return  self.packageexample_set.filter(active=True)
           @property
           def  license_latest(self):
                   try:
                           return  self.version_set.latest().license
                   except  Version.DoesNotExist:
                           return  "UNKNOWN"
           def  grids(self):
                   return  (x.grid  for  x  in  self.gridpackage_set.all())
           def  repo_name(self):
                   return  re.sub(self.repo.url_regex,  '',  self.repo_url)
           def  participant_list(self):
                   return  self.participants.split(',')
           def  get_usage_count(self):
                   return  self.usage.count()
           def  commits_over_52(self):
                   now  =  datetime.now()
                   commits  =  Commit.objects.filter(
                           package=self,
                           commit_date__gt=now  -­  timedelta(weeks=52),
                   ).values_list('commit_date',  flat=True)
                   weeks  =  [0]  *  52
                   for  cdate  in  commits:
                           age_weeks  =  (now  -­  cdate).days  //  7
                           if  age_weeks  <  52:
                                   weeks[age_weeks]  +=  1
                   return  ','.join(map(str,  reversed(weeks)))
           def  fetch_metadata(self,  *args,  **kwargs):
                   #  Get  the  downloads  from  pypi
                   if  self.pypi_url.strip()  and  self.pypi_url  !=  "http://pypi.python.org/pypi/":
                           total_downloads  =  0
                           for  release  in  fetch_releases(self.pypi_name):
                                   version,  created  =  Version.objects.get_or_create(
                                           package=self,
                                           number=release.version
                                   )
                                   #  add  to  total  downloads
                                   total_downloads  +=  release.downloads
                                   #  add  to  versions
                                   version.downloads  =  release.downloads
                                   if  hasattr(release,  "upload_time"):
                                           version.upload_time  =  release.upload_time
                                   version.license  =  release.license
                                   version.hidden  =  release._pypi_hidden
                                   version.save()
                           self.pypi_downloads  =  total_downloads
                   self.repo.fetch_metadata(self)
                   signal_fetch_latest_metadata.send(sender=self)
                   self.save()
           def  save(self,  *args,  **kwargs):
                   if  not  self.repo_description:
                           self.repo_description  =  ""
                   super(Package,  self).save(*args,  **kwargs)
           def  fetch_commits(self):
                   self.repo.fetch_commits(self)
           @property
           def  last_released(self):
                   versions  =  self.version_set.exclude(upload_time=None)
                   if  versions:
                           return  versions.latest()
                   return  None
           @property
           def  pypi_ancient(self):
                   release  =  self.last_released
                   if  release:
                           return  release.upload_time  <  datetime.now()  -­  timedelta(365)
                   return  None
           @property
           def  no_development(self):
                   commit_date  =  self.last_updated
                   if  commit_date  is  not  None:
                           return  commit_date  <  datetime.now()  -­  timedelta(365)
                   return  None
           class  Meta:
                   ordering  =  ['title']
                   get_latest_by  =  'id'
           def  __unicode__(self):
                   return  self.title
           @models.permalink
           def  get_absolute_url(self):
                   return  ("package",  [self.slug])

    View full-size slide

  40. @pydanny
    [email protected]
    pro-tip
    Use
    Helper
    Functions

    View full-size slide

  41. @pydanny
    [email protected]
    Using Helper Functions
    from  django.db  import  models
     
    from  pies  import  utils  as  pie_utils
     
     
    class  Pie(models.Model):
     
           #  snip  all  the  attributes
     
           def  is_savory(self):
                   return  pie_utils.is_savory(self.filling)
     
           @property
           def  cooking_time
                   return  pie_utils.cooking_time(self.filling)

    View full-size slide

  42. @pydanny
    [email protected]
    Django’s API Conventions
    Encourage
    clean
    design

    View full-size slide

  43. @pydanny
    [email protected]
    Content
    separation
    Presentation

    View full-size slide

  44. @pydanny
    [email protected]
    Means We Don’t
    Fight So Much over
    Architecture

    View full-size slide

  45. Reason #4
    Django has
    Awesome
    Views

    View full-size slide

  46. @pydanny
    [email protected]
    Django Views are Functions
    HTTP
    Request
    HTTP
    Response
    Django
    View
    Function
    HttpResponse  =  view(HttpRequest())
    Django is part of a group of Python frameworks that emerged around 2005 that embodied
    the readily-understood concept that HTTP requests could be handled via functions.

    View full-size slide

  47. @pydanny
    [email protected]
    @login_required
    def  update_package(request,  slug):
     
           package  =  get_object_or_404(Package,  slug=slug)
           package.fetch_metadata()
           package.fetch_commits()
           msg  =  "Package  updated  successfully"
           messages.add_message(request,  messages.INFO,  msg)
     
           return  HttpResponseRedirect(
           reverse("package",  kwargs={"slug":  package.slug})
    )
    Django
    Views are Functions
    #  Do  whatever  needs  to  be  done!
    #  Do  whatever  needs  to  be  done!
    #  Do  whatever  needs  to  be  done!

    View full-size slide

  48. @pydanny
    [email protected]
    Django Views are Functions
    HTTP
    Request
    HTTP
    Response
    Django
    View
    Function
    HttpResponse  =  view(HttpRequest())

    View full-size slide

  49. @pydanny
    [email protected]
    What about
    Class-Based Views?

    View full-size slide

  50. @pydanny
    [email protected]
    View.as_view()
    What the heck does this mean?

    View full-size slide

  51. @pydanny
    [email protected]
    class  View(object):
           @classonlymethod
           def  as_view(cls,  **initkwargs):
                   """
                   Main  entry  point  for  a  request-­response  process.
                   """
                   #  sanitize  keyword  arguments
                   for  key  in  initkwargs:
                           if  key  in  cls.http_method_names:
                                   raise  TypeError("You  tried  to  pass  in  the  %s  method  name  as  a  "
                                                                   "keyword  argument  to  %s().  Don't  do  that."
                                                                   %  (key,  cls.__name__))
                           if  not  hasattr(cls,  key):
                                   raise  TypeError("%s()  received  an  invalid  keyword  %r.  as_view  "
                                                                   "only  accepts  arguments  that  are  already  "
                                                                   "attributes  of  the  class."  %  (cls.__name__,  key))
                   def  view(request,  *args,  **kwargs):
                           self  =  cls(**initkwargs)
                           if  hasattr(self,  'get')  and  not  hasattr(self,  'head'):
                                   self.head  =  self.get
                           self.request  =  request
                           self.args  =  args
                           self.kwargs  =  kwargs
                           return  self.dispatch(request,  *args,  **kwargs)
                   #  take  name  and  docstring  from  class
                   update_wrapper(view,  cls,  updated=())
                   #  and  possible  attributes  set  by  decorators
                   #  like  csrf_exempt  from  dispatch
                   update_wrapper(view,  cls.dispatch,  assigned=())
                   return  view
    Returns a
    callable
    instance of
    the view
    Keyword
    control
    code
    For Python’s
    introspection
    tools

    View full-size slide

  52. @pydanny
    [email protected]
    HttpResponse  =  
    View.as_view(HttpRequest())

    View full-size slide

  53. @pydanny
    [email protected]
    Django Views are Functions
    HTTP
    Request
    HTTP
    Response
    Django
    View
    Class
    HttpResponse  =  
    View.as_view(HttpRequest())

    View full-size slide

  54. Reason #5
    Django has
    Awesome
    Longevity

    View full-size slide

  55. @pydanny
    [email protected]
    Slow
    Deprecation
    Stable APIs make frameworks much nicer. They don’t just add longevity, they keep users
    happy.

    View full-size slide

  56. @pydanny
    [email protected]
    from  django.db  import  models
     
     
    class  Pie(models.Model):
     
           STATUS_UNBAKED,  STATUS_BAKED  =  0,  1
           FILLING_APPLE,  FILLING_MEAT  =  0,  1
           STATUS_CHOICES  =  (
                   (STATUS_UNBAKED,  "Unbaked"),
                   (STATUS_BAKED,  "Baked")
           )
           FILLING_CHOICES  =  (
                   (FILLING_APPLE,  "Apple"),
                   (FILLING_MEAT,  "Meat"),
           )
     
           status  =  models.IntegerField(choices=STATUS_CHOICES,  
                                                   default=STATUS_UNBAKED)
           filling  =  models.IntegerField(choices=FILLING_CHOICES)
     
           def  __unicode__(self):
                   return  "{status}  {filling}  pie".format(
                           status=self.get_status_display(),
                           filling=self.get_filling_display()
                   )
    Django 1.5
    Django 1.4
    Django 1.3
    Django 1.2
    Django 1.1
    Django 1.0
    Much of the same code works across years of Django. Backporting Django is easy, it’s Python
    that’s changed!

    View full-size slide

  57. Reason #6
    Django has
    Awesome
    Features

    View full-size slide

  58. @pydanny
    [email protected]
    Django Features
    Admin
    Unicode
    XSS protection
    GeoDjango
    File Storage
    Prefetch related
    Aggregates
    Proxy Models
    Deferred Fields
    URL Namespaces
    New User Model
    Python 3
    Multi-DB
    Model validation
    CSRF protection
    Object-level perms
    Email backends
    Natural Keys
    Template Caching
    Class Based Views
    Logging
    Static les
    Save Subsets
    Streaming Response
    Tests
    Con gurable on_delete
    TemplateResponse
    RequestFactory
    assertNumQueries
    Time zones
    Select for Update
    Password Hashing
    Signed Cookies
    WSGI
    Documented
    Caching

    View full-size slide

  59. @pydanny
    [email protected]
    Admin
    Unicode
    XSS protection
    GeoDjango
    File Storage
    Prefetch related
    Aggregates
    Proxy Models
    Deferred Fields
    URL Namespaces
    New User Model
    Python 3
    Multi-DB
    Model validation
    CSRF protection
    Object-level perms
    Email backends
    Natural Keys
    Template Caching
    Class Based Views
    Logging
    Static les
    Save Subsets
    Streaming Response
    Tests
    Con gurable on_delete
    TemplateResponse
    RequestFactory
    assertNumQueries
    Time zones
    Select for Update
    Password Hashing
    Signed Cookies
    WSGI
    Documented
    Caching
    Django Features

    View full-size slide

  60. @pydanny
    [email protected]
    Django’s Admin is
    Awesome

    View full-size slide

  61. @pydanny
    [email protected]
    django.contrib.admin
    a.k.a.
    How to sell Django 101

    View full-size slide

  62. @pydanny
    [email protected]
    admin.py
    from  django.contrib  import  admin
     
    from  pies.models  import  Pie
     
    admin.site.register(Pie)
    Shortest Admin module possible.
    Remember it.
    Sweet, elegant, API awesomeness. What’s even better is there is a growing list of Django
    admin skins and themes being developed. If you are working on this sort of thing, keep it up
    please!

    View full-size slide

  63. @pydanny
    [email protected]
    Pro-Tip
    django.contrib.admin +
    NoSQL

    View full-size slide

  64. @pydanny
    [email protected]
    Don’t Extend
    django.contrib.admin

    View full-size slide

  65. @pydanny
    [email protected]
    Write it from
    scratch.
    Easier
    Stable

    View full-size slide

  66. @pydanny
    [email protected]
    MongoDB- avored
    #  myapp/mongoadmin.py
     
    #  Import  the  MongoAdmin  base  class
    from  mongonaut.sites  import  MongoAdmin
     
    #  Import  your  custom  models
    from  blog.models  import  Post
     
    #  Instantiate  the  MongoAdmin  class
    #  Then  attach  the  mongoadmin  to  your  model
    Post.mongoadmin  =  MongoAdmin()
    https://github.com/pydanny/django-mongonaut

    View full-size slide

  67. @pydanny
    [email protected]
    github.com/pydanny/django-mongonaut

    View full-size slide

  68. @pydanny
    [email protected]
    admin2
    #  myapp/admin2.py
     
    #  Import  the  Admin2  base  class
    from  admin2.sites  import  Admin2
     
    #  Import  your  custom  models
    from  blog.models  import  Post
     
    #  Instantiate  the  Admin2  class
    #  Then  attach  the  admin2  to  your  model
    Post.admin2  =  Admin2()
    https://github.com/pydanny/django-mongonaut

    View full-size slide

  69. @pydanny
    [email protected]
    github.com/pydanny/django-admin2

    View full-size slide

  70. @pydanny
    [email protected]
    Admin
    Unicode
    XSS protection
    GeoDjango
    File Storage
    Prefetch related
    Aggregates
    Proxy Models
    Deferred Fields
    URL Namespaces
    New User Model
    Python 3
    Multi-DB
    Model validation
    CSRF protection
    Object-level perms
    Email backends
    Natural Keys
    Template Caching
    Class Based Views
    Logging
    Static les
    Save Subsets
    Streaming Response
    Tests
    Con gurable on_delete
    TemplateResponse
    RequestFactory
    assertNumQueries
    Time zones
    Select for Update
    Password Hashing
    Signed Cookies
    WSGI
    Documented
    Caching
    Django Features
    Okay then, back to features.

    View full-size slide

  71. @pydanny
    [email protected]
    Admin
    Unicode
    XSS protection
    GeoDjango
    File Storage
    Prefetch related
    Aggregates
    Proxy Models
    Deferred Fields
    URL Namespaces
    New User Model
    Python 3
    Multi-DB
    Model validation
    CSRF protection
    Object-level perms
    Email backends
    Natural Keys
    Template Caching
    Class Based Views
    Logging
    Static les
    Save Subsets
    Streaming Response
    Tests
    Con gurable on_delete
    TemplateResponse
    RequestFactory
    assertNumQueries
    Time zones
    Select for Update
    Password Hashing
    Signed Cookies
    WSGI
    Documented
    Caching
    Django Features
    There’s a lot. So many that we just barely touch them in our book.

    View full-size slide

  72. @pydanny
    [email protected]
    Reason #7
    Django’s
    Full Stack
    is Awesome
    a.k.a.
    The section where the micro-framework fans go nuts.
    Seriously, hear me out.

    View full-size slide

  73. @pydanny
    [email protected]
    Dominating
    Hackathons
    * according to pydanny
    Not having to worry about wifi. Documentation in one place.

    View full-size slide

  74. @pydanny
    [email protected]
    Building
    Companies
    * according to pydanny

    View full-size slide

  75. @pydanny
    [email protected]
    Today in Django
    Real projects being done in
    unextended Django & Python
    Standard Python/Django Libraries
    No concept of the larger Python/Django World

    View full-size slide

  76. @pydanny
    [email protected]
    Late 2012
    Los Angeles based
    eco-service company
    US$5,000,000 funding

    View full-size slide

  77. @pydanny
    [email protected]
    No
    ird-Party
    Packages

    View full-size slide

  78. @pydanny
    [email protected]
    oughts
    People building stuff with
    new tools under tight
    deadlines...

    View full-size slide

  79. @pydanny
    [email protected]
    oughts
    Don’t always have time to
    investigate the community.

    View full-size slide

  80. @pydanny
    [email protected]
    Django’s

    Full Stack”
    is a Win

    View full-size slide

  81. @pydanny
    [email protected]
    On the ip side...
    They did a lot of work they didn’t need to do. What’s the solution?

    View full-size slide

  82. @pydanny
    [email protected]
    Reason #8
    Django
    has ousands
    of Awesome
    ird-Party Packages

    View full-size slide

  83. @pydanny
    [email protected]
    How many Django
    speci c packages are
    there?

    View full-size slide

  84. @pydanny
    [email protected]
    >>>  import  requests
    >>>  from  bs4  import  BeautifulSoup
    >>>  r  =  requests.get('https://pypi.python.org/pypi?
    %3Aaction=search&term=django&submit=search')
    >>>  soup  =  BeautifulSoup(r.content)
    >>>  t  =  soup.find("table",  class_="list")
    >>>  len(t.find_all('tr'))
    4581
    How many Django speci c
    packages are there?

    View full-size slide

  85. @pydanny
    [email protected]
    Django is also Python!
    PyPI has over
    30,000
    Packages!
    If even 20% are generic enough to be imported
    into Python projects that’s awesome.

    View full-size slide

  86. @pydanny
    [email protected]
    Reason #9
    Django has
    Awesome
    Documentation

    View full-size slide

  87. @pydanny
    [email protected]
    Culture
    of
    Documentation

    View full-size slide

  88. @pydanny
    [email protected]
    Transcendental
    Django is
    Documentation

    View full-size slide

  89. @pydanny
    [email protected]
    Reason #10
    Django is
    Awesomely
    Humble

    View full-size slide

  90. @pydanny
    [email protected]
    e
    Django
    Tradition of
    Invited Critical Talks
    • 2008 - Cal Henderson
    • 2010 - Eric Florenzano
    • 2011 - Glyph Lefkowitz, Steve Holden
    • 2012 - Kenneth Reitz, Justin Holmes
    At least this many talks, possibly more. Some were incredible, some were not.

    View full-size slide

  91. @pydanny
    [email protected]
    Shaped the
    Code Base

    View full-size slide

  92. @pydanny
    [email protected]
    Shaped the
    Core Team

    View full-size slide

  93. @pydanny
    [email protected]
    Shaped the
    Community

    View full-size slide

  94. @pydanny
    [email protected]
    Shaped
    Me
    I learned that inviting criticism of your work makes a difference.
    TSD is awesome because we ask people to be honest.

    View full-size slide

  95. @pydanny
    [email protected]
    Reason #11
    Django
    has an
    Awesome
    Community

    View full-size slide

  96. @pydanny
    [email protected]
    For starters...
    “Django has brought more joy to my life than
    I thought was possible with a web framework.”

    View full-size slide

  97. @pydanny
    [email protected]
    e Awesome
    Generosity of
    Django’s
    Community

    View full-size slide

  98. @pydanny
    [email protected]
    Django’s Unwritten Rule of Generosity
    “ e more you help people in
    the Django/Python community,
    the more the community helps you.”

    View full-size slide

  99. @pydanny
    [email protected]
    http://2scoops.org

    View full-size slide

  100. @pydanny
    [email protected]
    We didn’t do it alone.
    •9 General Technical Reviewers
    •3 Chapter Reviewers
    •116 Reader Contributors
    •2 Typesetting Experts
    While we stand on the shoulders of giants, over 125 people contributed directly to this book.

    View full-size slide

  101. @pydanny
    [email protected]
    Gave the PDF of the book
    to developers in need
    who emailed us.
    This was especially helpful for developers in nations outside the normal monetary exchange.

    View full-size slide

  102. @pydanny
    [email protected]
    In return
    we asked:

    View full-size slide

  103. @pydanny
    [email protected]
    1.
    Buy the book
    when possible.

    View full-size slide

  104. @pydanny
    [email protected]
    2.
    Give to Charity.

    View full-size slide

  105. @pydanny
    [email protected]
    3.
    Do something nice
    for someone.

    View full-size slide

  106. “As music is my main skill I
    have mentored a young
    student for free every Friday
    for an hour.”
    Ethan Lowman
    Instruction was a pattern... starting with outside skills

    View full-size slide

  107. “I added Python and
    Django to the technical
    curriculum where I teach.”
    Herman Gonzales, Christopher Ayode, Pratyush Mittal
    Education was also a theme...

    View full-size slide

  108. “I contributed to
    open source.”
    Jay, Nadia, Sam, Alex, Agustin, Guillaume, Paulo, Pedro,
    Roberto, Isaac, Nima, Eric, Hamid, Joe, Glan, Marc, Mark,
    Jared, Karl, Mohammed, Akshay, Ethan, Robert, Trung,
    Ivan, Cesar, Piotr, Andrii, Jin, June, Lucas, Samantha, Dan,
    Kenneth, Chris, Katherine, omas, Yoko, Gabriel, Keith,
    Renee, Edgar, Jamal, Christine, Alexandra, Eric, Steve,
    Carl, Mario, Francis, Antonio, Kapoor, Indra, David, Clay,
    Earnest, Pocholo, Matt, Daniela, Charles, Ananta, Vadim,
    Rashid, Jing, Tony, Neil, Mathieu, Cecilia, Aubrey, John,
    Cora,Fabio, Michael, Michelle, Alec, Sara, Sean, Ian, Bruce,
    Herman, Arne, Adam, Jeff, Allison, Ruth, Katy
    A lot of people contributed to open source efforts.

    View full-size slide

  109. “I was able to donate
    $15 to Python 3
    support in PyPy.”
    Juraj Bubniak
    Some people donated money.

    View full-size slide

  110. “I bought a homeless
    man dinner.”
    Alex Wochna
    Others supported causes like feeding the hungry.

    View full-size slide

  111. “I built a project for my
    church/mosque/temple/school.”
    Radic, Jaden, Luc, Wolfgang, Tobias, Richard, Ruth
    Lars, Jun, Bartek, Alex, Tyler, Pierre, Andreas, Julian
    ...working on worthy projects...

    View full-size slide

  112. “I helped develop
    evidenceupload.org, which was
    used to send 2 GB of data to the
    FBI after the Boston Bombings.”
    Keith Donaldson
    ... and participating in current events.

    View full-size slide

  113. @pydanny
    [email protected]
    People Took
    Our eme and Did
    Good Deeds.

    View full-size slide

  114. @pydanny
    [email protected]
    Be
    Awesome.
    Change the world. That means make code, run events, write books. Do things that work, and
    make the world better.

    View full-size slide

  115. @pydanny
    [email protected]
    One More ing...
    Cartwheel here

    View full-size slide