Slide 1

Slide 1 text

@pydanny pydanny@cartwheelweb.com Keynote DjangoCircus 2013

Slide 2

Slide 2 text

@pydanny pydanny@cartwheelweb.com Daniel Greenfeld Hi everyone. My name is Daniel Greenfeld. I’m the guy with the unenviable task of being the keynote after Brandon Rhodes.

Slide 3

Slide 3 text

@pydanny pydanny@cartwheelweb.com @pydanny This is me.

Slide 4

Slide 4 text

@pydanny pydanny@cartwheelweb.com I work as a principal for Cartwheel Web, doing Python and Django. The company is named after cartwheels.

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

@pydanny pydanny@cartwheelweb.com Django conferences have a tradition. Django has a tradition.

Slide 7

Slide 7 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 8

Slide 8 text

@pydanny pydanny@cartwheelweb.com is Isn’t A Hate Django Talk. I’m not giving one of those talks. Why not?

Slide 9

Slide 9 text

@pydanny pydanny@cartwheelweb.com Why Not?

Slide 10

Slide 10 text

@pydanny pydanny@cartwheelweb.com Negative It’s Too Easy to be

Slide 11

Slide 11 text

@pydanny pydanny@cartwheelweb.com Example: “Class Based Views Suck” Saying this is easy. I used to say it all the time. Twitter, IRC, forums

Slide 12

Slide 12 text

@pydanny pydanny@cartwheelweb.com You Know What’s Hard?

Slide 13

Slide 13 text

@pydanny pydanny@cartwheelweb.com Working Stuff Delivering

Slide 14

Slide 14 text

@pydanny pydanny@cartwheelweb.com Rants are fun but...

Slide 15

Slide 15 text

@pydanny pydanny@cartwheelweb.com No one would remember Zed Shaw if he hadn’t written Learn Python the Hard Way* *Just one of many of his efforts.

Slide 16

Slide 16 text

@pydanny pydanny@cartwheelweb.com Contribute Get Your Hands Dirty and

Slide 17

Slide 17 text

@pydanny pydanny@cartwheelweb.com 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

Slide 18

Slide 18 text

@pydanny pydanny@cartwheelweb.com is Isn’t A Hate Django Talk. So no, this isn’t a rant about Django. Instead...

Slide 19

Slide 19 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 20

Slide 20 text

@pydanny pydanny@cartwheelweb.com Why is Django Awesome?

Slide 21

Slide 21 text

@pydanny pydanny@cartwheelweb.com Reason #1 Django is Everywhere

Slide 22

Slide 22 text

@pydanny pydanny@cartwheelweb.com 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

Slide 23

Slide 23 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 24

Slide 24 text

@pydanny pydanny@cartwheelweb.com Reason #2 Django is Powered by Python

Slide 25

Slide 25 text

@pydanny pydanny@cartwheelweb.com Python is Awesome

Slide 26

Slide 26 text

@pydanny pydanny@cartwheelweb.com Python has a Style Guide PEP-0008

Slide 27

Slide 27 text

@pydanny pydanny@cartwheelweb.com Python has Zen PEP-0020

Slide 28

Slide 28 text

@pydanny pydanny@cartwheelweb.com Most importantly...

Slide 29

Slide 29 text

@pydanny pydanny@cartwheelweb.com Python shares the same rst two letters as me. Python Pydanny

Slide 30

Slide 30 text

@pydanny pydanny@cartwheelweb.com Reason #3 Django has Awesome APIs

Slide 31

Slide 31 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 32

Slide 32 text

@pydanny pydanny@cartwheelweb.com Case Study: python-requests vs. django.test.client

Slide 33

Slide 33 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 34

Slide 34 text

@pydanny pydanny@cartwheelweb.com API Win Conventions

Slide 35

Slide 35 text

@pydanny pydanny@cartwheelweb.com forms.py models.py views.py templates/ Forms Models Views Templates

Slide 36

Slide 36 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 37

Slide 37 text

@pydanny pydanny@cartwheelweb.com 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!

Slide 38

Slide 38 text

@pydanny pydanny@cartwheelweb.com Pro-Tip

Slide 39

Slide 39 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 40

Slide 40 text

@pydanny pydanny@cartwheelweb.com pro-tip Overly Large Models Are Not

Slide 41

Slide 41 text

@pydanny pydanny@cartwheelweb.com 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])

Slide 42

Slide 42 text

@pydanny pydanny@cartwheelweb.com pro-tip Use Helper Functions

Slide 43

Slide 43 text

@pydanny pydanny@cartwheelweb.com 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)

Slide 44

Slide 44 text

@pydanny pydanny@cartwheelweb.com Django’s API Conventions Encourage clean design

Slide 45

Slide 45 text

@pydanny pydanny@cartwheelweb.com Content separation Presentation

Slide 46

Slide 46 text

@pydanny pydanny@cartwheelweb.com Means We Don’t Fight So Much over Architecture

Slide 47

Slide 47 text

@pydanny pydanny@cartwheelweb.com Get ings Done

Slide 48

Slide 48 text

Reason #4 Django has Awesome Views

Slide 49

Slide 49 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 50

Slide 50 text

@pydanny pydanny@cartwheelweb.com @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!

Slide 51

Slide 51 text

@pydanny pydanny@cartwheelweb.com Django Views are Functions HTTP Request HTTP Response Django View Function HttpResponse  =  view(HttpRequest())

Slide 52

Slide 52 text

@pydanny pydanny@cartwheelweb.com What about Class-Based Views?

Slide 53

Slide 53 text

@pydanny pydanny@cartwheelweb.com View.as_view() What the heck does this mean?

Slide 54

Slide 54 text

@pydanny pydanny@cartwheelweb.com 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

Slide 55

Slide 55 text

@pydanny pydanny@cartwheelweb.com HttpResponse  =   View.as_view(HttpRequest())

Slide 56

Slide 56 text

@pydanny pydanny@cartwheelweb.com Django Views are Functions HTTP Request HTTP Response Django View Class HttpResponse  =   View.as_view(HttpRequest())

Slide 57

Slide 57 text

Reason #5 Django has Awesome Longevity

Slide 58

Slide 58 text

@pydanny pydanny@cartwheelweb.com Slow Deprecation Stable APIs make frameworks much nicer. They don’t just add longevity, they keep users happy.

Slide 59

Slide 59 text

@pydanny pydanny@cartwheelweb.com 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!

Slide 60

Slide 60 text

Reason #6 Django has Awesome Features

Slide 61

Slide 61 text

@pydanny pydanny@cartwheelweb.com 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

Slide 62

Slide 62 text

@pydanny pydanny@cartwheelweb.com 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

Slide 63

Slide 63 text

@pydanny pydanny@cartwheelweb.com Django’s Admin is Awesome

Slide 64

Slide 64 text

@pydanny pydanny@cartwheelweb.com django.contrib.admin a.k.a. How to sell Django 101

Slide 65

Slide 65 text

@pydanny pydanny@cartwheelweb.com 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!

Slide 66

Slide 66 text

@pydanny pydanny@cartwheelweb.com Pro-Tip django.contrib.admin + NoSQL

Slide 67

Slide 67 text

@pydanny pydanny@cartwheelweb.com Don’t Extend django.contrib.admin

Slide 68

Slide 68 text

@pydanny pydanny@cartwheelweb.com Write it from scratch. Easier Stable

Slide 69

Slide 69 text

@pydanny pydanny@cartwheelweb.com 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

Slide 70

Slide 70 text

@pydanny pydanny@cartwheelweb.com github.com/pydanny/django-mongonaut

Slide 71

Slide 71 text

@pydanny pydanny@cartwheelweb.com 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

Slide 72

Slide 72 text

@pydanny pydanny@cartwheelweb.com github.com/pydanny/django-admin2

Slide 73

Slide 73 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 74

Slide 74 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 75

Slide 75 text

@pydanny pydanny@cartwheelweb.com Next reason...

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

@pydanny pydanny@cartwheelweb.com Dominating Hackathons * according to pydanny Not having to worry about wifi. Documentation in one place.

Slide 78

Slide 78 text

@pydanny pydanny@cartwheelweb.com Building Companies * according to pydanny

Slide 79

Slide 79 text

@pydanny pydanny@cartwheelweb.com Today in Django Real projects being done in unextended Django & Python Standard Python/Django Libraries No concept of the larger Python/Django World

Slide 80

Slide 80 text

@pydanny pydanny@cartwheelweb.com Really.

Slide 81

Slide 81 text

@pydanny pydanny@cartwheelweb.com Late 2012 Los Angeles based eco-service company US$5,000,000 funding

Slide 82

Slide 82 text

@pydanny pydanny@cartwheelweb.com No ird-Party Packages

Slide 83

Slide 83 text

@pydanny pydanny@cartwheelweb.com Lots of Pain

Slide 84

Slide 84 text

@pydanny pydanny@cartwheelweb.com Quite Pro table

Slide 85

Slide 85 text

@pydanny pydanny@cartwheelweb.com oughts People building stuff with new tools under tight deadlines...

Slide 86

Slide 86 text

@pydanny pydanny@cartwheelweb.com oughts Don’t always have time to investigate the community.

Slide 87

Slide 87 text

@pydanny pydanny@cartwheelweb.com Django’s “ Full Stack” is a Win

Slide 88

Slide 88 text

@pydanny pydanny@cartwheelweb.com On the ip side... They did a lot of work they didn’t need to do. What’s the solution?

Slide 89

Slide 89 text

@pydanny pydanny@cartwheelweb.com Reason #8 Django has ousands of Awesome ird-Party Packages

Slide 90

Slide 90 text

@pydanny pydanny@cartwheelweb.com How many Django speci c packages are there?

Slide 91

Slide 91 text

@pydanny pydanny@cartwheelweb.com >>>  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?

Slide 92

Slide 92 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 93

Slide 93 text

@pydanny pydanny@cartwheelweb.com Reason #9 Django has Awesome Documentation

Slide 94

Slide 94 text

@pydanny pydanny@cartwheelweb.com Culture of Documentation

Slide 95

Slide 95 text

@pydanny pydanny@cartwheelweb.com Setting the Bar

Slide 96

Slide 96 text

@pydanny pydanny@cartwheelweb.com Transcendental Django is Documentation

Slide 97

Slide 97 text

@pydanny pydanny@cartwheelweb.com Reason #10 Django is Awesomely Humble

Slide 98

Slide 98 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 99

Slide 99 text

@pydanny pydanny@cartwheelweb.com Shaped the Code Base

Slide 100

Slide 100 text

@pydanny pydanny@cartwheelweb.com Shaped the Core Team

Slide 101

Slide 101 text

@pydanny pydanny@cartwheelweb.com Shaped the Community

Slide 102

Slide 102 text

@pydanny pydanny@cartwheelweb.com Shaped Me I learned that inviting criticism of your work makes a difference. TSD is awesome because we ask people to be honest.

Slide 103

Slide 103 text

@pydanny pydanny@cartwheelweb.com Reason #11 Django has an Awesome Community

Slide 104

Slide 104 text

@pydanny pydanny@cartwheelweb.com For starters... “Django has brought more joy to my life than I thought was possible with a web framework.”

Slide 105

Slide 105 text

@pydanny pydanny@cartwheelweb.com e Awesome Generosity of Django’s Community

Slide 106

Slide 106 text

@pydanny pydanny@cartwheelweb.com Django’s Unwritten Rule of Generosity “ e more you help people in the Django/Python community, the more the community helps you.”

Slide 107

Slide 107 text

@pydanny pydanny@cartwheelweb.com Case Study

Slide 108

Slide 108 text

@pydanny pydanny@cartwheelweb.com http://2scoops.org

Slide 109

Slide 109 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 110

Slide 110 text

@pydanny pydanny@cartwheelweb.com 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.

Slide 111

Slide 111 text

@pydanny pydanny@cartwheelweb.com In return we asked:

Slide 112

Slide 112 text

@pydanny pydanny@cartwheelweb.com 1. Buy the book when possible.

Slide 113

Slide 113 text

@pydanny pydanny@cartwheelweb.com 2. Give to Charity.

Slide 114

Slide 114 text

@pydanny pydanny@cartwheelweb.com 3. Do something nice for someone.

Slide 115

Slide 115 text

@pydanny pydanny@cartwheelweb.com What happened?

Slide 116

Slide 116 text

“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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

“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.

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

“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...

Slide 122

Slide 122 text

“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.

Slide 123

Slide 123 text

@pydanny pydanny@cartwheelweb.com People Took Our eme and Did Good Deeds.

Slide 124

Slide 124 text

@pydanny pydanny@cartwheelweb.com ey were Awesome.

Slide 125

Slide 125 text

@pydanny pydanny@cartwheelweb.com A Call to Action

Slide 126

Slide 126 text

@pydanny pydanny@cartwheelweb.com Be Awesome. Change the world. That means make code, run events, write books. Do things that work, and make the world better.

Slide 127

Slide 127 text

@pydanny pydanny@cartwheelweb.com One More ing... Cartwheel here

Slide 128

Slide 128 text

@pydanny pydanny@cartwheelweb.com Finis