Admitting my flaws and turning them into virtues! This is a full length talk given it at DjangoCon US 2011, PyCon Australia 2011, and LA Django. The earliest version was a lightning talk given at the 2011 Hollywood hackathon.
2. Daniel Greenfeld
@pydanny
Who am I?
Daniel Greenfeld (@pydanny)
Pythonista at Cartwheel
Djangonaut at Revsys
Co-lead of djangopackages.com
& Packaginator (Open
Comparison)
Fiancé of Audrey Roy
http://www.flickr.com/photos/pydanny/4442245488
12. Daniel Greenfeld
@pydanny
I’m stupid
Can’t figure things out
• If I get stuck for more than 30 minutes...
13. Daniel Greenfeld
@pydanny
I’m stupid
Can’t figure things out
• If I get stuck for more than 30 minutes...
• Find libraries that do it for me
14. Daniel Greenfeld
@pydanny
I’m stupid
Can’t figure things out
• If I get stuck for more than 30 minutes...
• Find libraries that do it for me
• Ask on Twitter for answers
15. Daniel Greenfeld
@pydanny
I’m stupid
Can’t figure things out
• If I get stuck for more than 30 minutes...
• Find libraries that do it for me
• Ask on Twitter for answers
• Stack Overflow is also good, but watch
for trolls.
16. Daniel Greenfeld
@pydanny
I’m stupid
Can’t figure things out
• If I get stuck for more than 30 minutes...
• Find libraries that do it for me
• Ask on Twitter for answers
• Stack Overflow is also good, but watch
for trolls.
• IRC can be good, if you get a troll try a
different channel.
21. Daniel Greenfeld
@pydanny
I’m stupid
# This sample gleefully taken from
# https://gist.github.com/973705
‘Smart way’
import urllib2
aka
gh_url = 'https://api.github.com'
gh_user= 'user'
gh_pass = 'pass'
hard way
req = urllib2.Request(gh_url)
password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_manager.add_password(None, gh_url, gh_user, gh_pass)
auth_manager = urllib2.HTTPBasicAuthHandler(password_manager)
opener = urllib2.build_opener(auth_manager)
urllib2.install_opener(opener)
handler = urllib2.urlopen(req)
print handler.getcode()
print handler.headers.getheader('content-type')
# ------
# 200
# 'application/json'
22. Daniel Greenfeld
@pydanny
I’m stupid
# This sample gleefully taken from
# https://gist.github.com/973705
‘Smart way’
What import urllib2
aka
is this? gh_url = 'https://api.github.com'
gh_user= 'user'
gh_pass = 'pass'
hard way
req = urllib2.Request(gh_url)
password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_manager.add_password(None, gh_url, gh_user, gh_pass)
auth_manager = urllib2.HTTPBasicAuthHandler(password_manager)
opener = urllib2.build_opener(auth_manager)
urllib2.install_opener(opener)
handler = urllib2.urlopen(req)
print handler.getcode()
print handler.headers.getheader('content-type')
# ------
# 200
# 'application/json'
23. Daniel Greenfeld
@pydanny
I’m stupid
# This sample gleefully taken from
# https://gist.github.com/973705
‘Smart way’
What import urllib2
aka
is this? gh_url = 'https://api.github.com'
gh_user= 'user'
gh_pass = 'pass'
hard way
req = urllib2.Request(gh_url)
password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_manager.add_password(None, gh_url, gh_user, gh_pass)
auth_manager = urllib2.HTTPBasicAuthHandler(password_manager)
opener = urllib2.build_opener(auth_manager)
And urllib2.install_opener(opener)
this? handler = urllib2.urlopen(req)
print handler.getcode()
print handler.headers.getheader('content-type')
# ------
# 200
# 'application/json'
24. Daniel Greenfeld
@pydanny
I’m stupid
# This sample gleefully taken from
# https://gist.github.com/973705
‘Smart way’
What import urllib2
aka
is this? gh_url = 'https://api.github.com'
gh_user= 'user'
gh_pass = 'pass'
hard way
req = urllib2.Request(gh_url)
password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_manager.add_password(None, gh_url, gh_user, gh_pass)
auth_manager = urllib2.HTTPBasicAuthHandler(password_manager)
opener = urllib2.build_opener(auth_manager)
And urllib2.install_opener(opener)
What is an
this? install opener?
handler = urllib2.urlopen(req)
print handler.getcode()
print handler.headers.getheader('content-type')
# ------
# 200
# 'application/json'
25. Daniel Greenfeld
@pydanny
I’m stupid
# This sample gleefully taken from
# https://gist.github.com/973705
‘Smart way’
What import urllib2
aka
is this? gh_url = 'https://api.github.com'
gh_user= 'user'
gh_pass = 'pass'
hard way
req = urllib2.Request(gh_url)
password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_manager.add_password(None, gh_url, gh_user, gh_pass)
auth_manager = urllib2.HTTPBasicAuthHandler(password_manager)
opener = urllib2.build_opener(auth_manager)
And urllib2.install_opener(opener)
What is an
this? install opener?
handler = urllib2.urlopen(req)
print handler.getcode()
print handler.headers.getheader('content-type') Finally we make
# ------ the request!
# 200
# 'application/json'
26. Daniel Greenfeld
@pydanny
I’m stupid ‘Stupid way’
aka
Can’t figure things out
easy way
27. Daniel Greenfeld
@pydanny
I’m stupid ‘Stupid way’
aka
Can’t figure things out
easy way
# This sample joyfully taken from
# https://gist.github.com/973705
import requests
r = requests.get('https://api.github.com',
auth=('user', 'pass'))
print r.status_code
print r.headers['content-type']
# ------
# 200
# 'application/json'
28. Daniel Greenfeld
@pydanny
I’m stupid ‘Stupid way’
aka
HTTP Can’t figure things out
GET easy way
# This sample joyfully taken from
# https://gist.github.com/973705
import requests
r = requests.get('https://api.github.com',
auth=('user', 'pass'))
print r.status_code
print r.headers['content-type']
# ------
# 200
# 'application/json'
29. Daniel Greenfeld
@pydanny
I’m stupid ‘Stupid way’
aka
HTTP Can’t figure things out
GET easy way
# This sample joyfully taken from
# https://gist.github.com/973705
import requests
r = requests.get('https://api.github.com',
Username auth=('user', 'pass'))
+
print r.status_code
Password print r.headers['content-type']
# ------
# 200
# 'application/json'
30. Daniel Greenfeld
@pydanny
I’m stupid
Can’t figure things out
“Smart” people way PyDanny way
# This sample gleefully taken from https://gist.github.com/973705
# This sample joyfully taken from
import urllib2
# https://gist.github.com/973705
gh_url = 'https://api.github.com'
gh_user= 'user'
gh_pass = 'pass' import requests
req = urllib2.Request(gh_url)
r = requests.get('https://api.github.com',
password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() auth=('user', 'pass'))
password_manager.add_password(None, gh_url, gh_user, gh_pass)
auth_manager = urllib2.HTTPBasicAuthHandler(password_manager) print r.status_code
opener = urllib2.build_opener(auth_manager)
print r.headers['content-type']
urllib2.install_opener(opener)
handler = urllib2.urlopen(req) # ------
# 200
print handler.getcode()
print handler.headers.getheader('content-type') # 'application/json'
# ------
# 200
# 'application/json'
31. Daniel Greenfeld
@pydanny
I’m stupid
Too stupid not to ask stupid questions
32. Daniel Greenfeld
@pydanny
I’m stupid
Too stupid not to ask stupid questions
• There are no stupid questions
33. Daniel Greenfeld
@pydanny
I’m stupid
Too stupid not to ask stupid questions
• There are no stupid questions
• Don’t try and impress the people around
you by not asking questions.
34. Daniel Greenfeld
@pydanny
I’m stupid
Too stupid not to ask stupid questions
You are at DjangoCon.
If you don’t ask the question,
you are wasting opportunity.
35. Daniel Greenfeld
@pydanny
I’m stupid
Too stupid not to ask stupid questions
You are at DjangoCon.
A positive trait good tech leads often
look for is the ability to ask questions.
37. Daniel Greenfeld
@pydanny
I’m stupid
Can’t remember things
• Documentation makes me look good
38. Daniel Greenfeld
@pydanny
I’m stupid
Can’t remember things
• Documentation makes me look good
• Docstrings are awesome
39. Daniel Greenfeld
@pydanny
I’m stupid
Can’t remember things
• Documentation makes me look good
• Docstrings are awesome
• Learn you some Restructured Text
40. Daniel Greenfeld
@pydanny
I’m stupid
Can’t remember things
• Documentation makes me look good
• Docstrings are awesome
• Learn you some Restructured Text
• Write down even the slide bullets!
41. Daniel Greenfeld
@pydanny
I’m stupid
Can’t remember things
• Documentation makes me look good
• Docstrings are awesome
• Learn you some Restructured Text
• Write down even the slide bullets!
• https://github.com/pydanny/pydanny-event-notes
42. Daniel Greenfeld
Joe Developer
@pydanny
Resources
Where the code examples live!
https://github.com/pydanny/django-party-pack
http://django-party-pack.rtfd.org/
43. Daniel Greenfeld
@pydanny
I’m stupid
http://readthedocs.org/docs/django-party-pack
44. Daniel Greenfeld
@pydanny
I’m stupid
Sphinx
makes
me
look
good!
http://readthedocs.org/docs/django-party-pack
45. Daniel Greenfeld
@pydanny
Docs/Sphinx Basics
• pip install sphinx
• make a docs directory
• sphinx-quickstart
• Follow instructions
• Starting over is just removing your docs
46. Daniel Greenfeld
@pydanny
I’m stupid
Sphinx makes me look good!
=============
Installation
=============
.. note:: For things with **font like this** it means type it at the command line and hit enter.
The Basics
===========
0. **git clone https://pydanny@github.com/pydanny/django-party-pack.git**
1. Make sure you have virtualenv installed.
2. change directory to the directory that contains this README.rst file.
3. **virtualenv pollaxe** and then **source pollaxe/bin/activate**
4. **pip install -r requirements.txt**
5. **mkdir pollaxe/coverage**
Building the sphinx docs
=========================
1. change directory to docs
2. **make html**
Running django-coverage
========================
1. python manage.py test
http://readthedocs.org/docs/django-party-pack/en/latest/_sources/install.txt
47. Daniel Greenfeld
@pydanny
page
header
I’m stupid
Sphinx makes me look good!
=============
Installation
=============
.. note:: For things with **font like this** it means type it at the command line and hit enter.
The Basics
===========
0. **git clone https://pydanny@github.com/pydanny/django-party-pack.git**
1. Make sure you have virtualenv installed.
2. change directory to the directory that contains this README.rst file.
3. **virtualenv pollaxe** and then **source pollaxe/bin/activate**
4. **pip install -r requirements.txt**
5. **mkdir pollaxe/coverage**
Building the sphinx docs
=========================
1. change directory to docs
2. **make html**
Running django-coverage
========================
1. python manage.py test
http://readthedocs.org/docs/django-party-pack/en/latest/_sources/install.txt
48. Daniel Greenfeld
@pydanny
page
header
I’m stupid
Sphinx makes me look good!
=============
note Installation
=============
block .. note:: For things with **font like this** it means type it at the command line and hit enter.
The Basics
===========
0. **git clone https://pydanny@github.com/pydanny/django-party-pack.git**
1. Make sure you have virtualenv installed.
2. change directory to the directory that contains this README.rst file.
3. **virtualenv pollaxe** and then **source pollaxe/bin/activate**
4. **pip install -r requirements.txt**
5. **mkdir pollaxe/coverage**
Building the sphinx docs
=========================
1. change directory to docs
2. **make html**
Running django-coverage
========================
1. python manage.py test
http://readthedocs.org/docs/django-party-pack/en/latest/_sources/install.txt
49. Daniel Greenfeld
@pydanny
page
header
I’m stupid
Sphinx makes me look good!
=============
note Installation
=============
block .. note:: For things with **font like this** it means type it at the command line and hit enter.
The Basics
===========
0. **git clone https://pydanny@github.com/pydanny/django-party-pack.git**
1. Make sure you have virtualenv installed.
section 2.
3.
change directory to the directory that contains this README.rst file.
**virtualenv pollaxe** and then **source pollaxe/bin/activate**
headers
4. **pip install -r requirements.txt**
5. **mkdir pollaxe/coverage**
Building the sphinx docs
=========================
1. change directory to docs
2. **make html**
Running django-coverage
========================
1. python manage.py test
http://readthedocs.org/docs/django-party-pack/en/latest/_sources/install.txt
50. Daniel Greenfeld
@pydanny
I’m stupid
http://readthedocs.org/docs/django-party-pack
51. Daniel Greenfeld
@pydanny
I’m stupid
Sphinx
makes
me
look
good!
http://readthedocs.org/docs/django-party-pack
52. Daniel Greenfeld
@pydanny
I’m stupid
Sphinx makes me look good!
http://readthedocs.org/docs/django-party-pack/en/latest/reference_polls.html
53. Daniel Greenfeld
@pydanny
I’m stupid
Sphinx makes me look good!
http://readthedocs.org/docs/django-party-pack/en/latest/reference_polls.html
54. Daniel Greenfeld
@pydanny
I’m stupid
Sphinx makes me look good!
========================
Reference for Polls App
========================
The polls app is a copy of the Django tutorial with some mild PEP-8 cleanup.
``polls.models``
=================
.. automodule:: polls.models
:members:
``polls.views``
=================
.. automodule:: polls.views
:members:
``polls.tests``
=================
.. automodule:: polls.tests.test_models
:members:
:undoc-members:
.. automodule:: polls.tests.test_views
:members:
:undoc-members:
http://readthedocs.org/docs/django-party-pack/en/latest/reference_polls.html
55. Daniel Greenfeld
@pydanny
I’m stupid
Sphinx makes me look good!
========================
page Reference for Polls App
========================
header The polls app is a copy of the Django tutorial with some mild PEP-8 cleanup.
``polls.models``
=================
.. automodule:: polls.models
:members:
``polls.views``
=================
.. automodule:: polls.views
:members:
``polls.tests``
=================
.. automodule:: polls.tests.test_models
:members:
:undoc-members:
.. automodule:: polls.tests.test_views
:members:
:undoc-members:
http://readthedocs.org/docs/django-party-pack/en/latest/reference_polls.html
56. Daniel Greenfeld
@pydanny
I’m stupid
Sphinx makes me look good!
========================
page Reference for Polls App
========================
header The polls app is a copy of the Django tutorial with some mild PEP-8 cleanup.
``polls.models``
=================
auto-
.. automodule:: polls.models
:members:
model ``polls.views``
=================
.. automodule:: polls.views
:members:
``polls.tests``
=================
.. automodule:: polls.tests.test_models
:members:
:undoc-members:
.. automodule:: polls.tests.test_views
:members:
:undoc-members:
http://readthedocs.org/docs/django-party-pack/en/latest/reference_polls.html
57. Daniel Greenfeld
@pydanny
I’m stupid
Sphinx makes me look good!
========================
page Reference for Polls App
========================
header The polls app is a copy of the Django tutorial with some mild PEP-8 cleanup.
``polls.models``
=================
auto-
.. automodule:: polls.models
:members:
model ``polls.views``
=================
.. automodule:: polls.views
:members:
auto-model
``polls.tests``
=================
for undocumented
.. automodule:: polls.tests.test_models
:members:
items
:undoc-members:
.. automodule:: polls.tests.test_views
:members:
:undoc-members:
http://readthedocs.org/docs/django-party-pack/en/latest/reference_polls.html
58. Daniel Greenfeld
@pydanny
I’m stupid
Sphinx makes me look good!
http://readthedocs.org/docs/django-party-pack/en/latest/reference_polls.html
59. Daniel Greenfeld
@pydanny
I’m stupid
Sphinx makes me look good!
http://readthedocs.org/docs/django-party-pack/en/latest/reference_polls.html
60. Daniel Greenfeld
@pydanny
Sphinx walk-through
http://audreyr.posterous.com/how-to-create-sphinx-docs-the-python-github-r
or
http://bit.ly/audreyr-sphinx
63. Daniel Greenfeld
@pydanny
I’m lazy
• Don’t wanna do anything twice
64. Daniel Greenfeld
@pydanny
I’m lazy
• Don’t wanna do anything twice
• Don’t wanna debug code when I had it
working before
65. Daniel Greenfeld
@pydanny
I’m lazy
• Don’t wanna do anything twice
• Don’t wanna debug code when I had it
working before
• Don’t wanna upload zip files per document
change
66. Daniel Greenfeld
@pydanny
I’m lazy
Don’t wanna do anything twice
67. Daniel Greenfeld
@pydanny
I’m lazy
Don’t wanna do anything twice
• If I write the same code twice I stick it in a
function
68. Daniel Greenfeld
@pydanny
I’m lazy
Don’t wanna do anything twice
• If I write the same code twice I stick it in a
function
• Then I stick the function into a util module.
69. Daniel Greenfeld
@pydanny
I’m lazy
Don’t wanna do anything twice
• If I write the same code twice I stick it in a
function
• Then I stick the function into a util module.
• Then I put it on Github so I don’t lose it.
70. Daniel Greenfeld
@pydanny
I’m lazy
Don’t wanna do anything twice
• If I write the same code twice I stick it in a
function
• Then I stick the function into a util module.
• Then I put it on Github so I don’t lose it.
• Isn’t this kinda the whole thing behind Open
Source?
71. Daniel Greenfeld
@pydanny
I’m Lazy
Don’t wanna debug code when I had it working before
72. Daniel Greenfeld
@pydanny
I’m Lazy
Don’t wanna debug code when I had it working before
• Manually testing code by watching it run is
hard...
73. Daniel Greenfeld
@pydanny
I’m Lazy
Don’t wanna debug code when I had it working before
• Manually testing code by watching it run is
hard...
• ...and boring...
74. Daniel Greenfeld
@pydanny
I’m Lazy
Don’t wanna debug code when I had it working before
• Manually testing code by watching it run is
hard...
• ...and boring...
• ...and hence is error prone.
75. Daniel Greenfeld
@pydanny
I’m Lazy
Don’t wanna debug code when I had it working before
• Manually testing code by watching it run is
hard...
• ...and boring...
• ...and hence is error prone.
• Meaning you have to do more work.
79. Daniel Greenfeld
@pydanny
I’m Lazy
Are you testing enough?
Yeah, some of the configuration is off. Will be fixed soon.
80. Daniel Greenfeld
@pydanny
Coverage Tricks
• coverage.py is great
• django-coverage runs coverage.py for Django
• But you only want to test your own apps
88. Daniel Greenfeld
settings.py
@pydanny
import os.path
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
Super PREREQ_APPS = (
'django.contrib.auth',
userful 'django.contrib.contenttypes',
'django.contrib.sessions',
django or third- 'django.contrib.sites',
'django.contrib.messages',
My custom
party-apps 'django.contrib.admin', apps
'django-debug-toolbar’,
)
PROJECT_APPS = (
INSTALLED_APPS 'polls',
)
INSTALLED_APPS = PREREQ_APPS + PROJECT_APPS
exclude this stuff COVERAGE_MODULE_EXCLUDES = [
'tests$', 'settings$', 'urls$', 'locale$',
'migrations', 'fixtures', 'admin$',
]
Output results See next page!
COVERAGE_MODULE_EXCLUDES += PREREQ_APPS
here COVERAGE_REPORT_HTML_OUTPUT_DIR = "coverage"
HTML_OUTPUT_DIR = os.path.join(PROJECT_ROOT, "coverage")
TEST_RUNNER = 'testrunner.OurCoverageRunner'
89. testrunner.py Daniel Greenfeld
@pydanny
# Make our own testrunner that by default only tests our own
apps
from django.conf import settings
from django.test.simple import DjangoTestSuiteRunner
from django_coverage.coverage_runner import CoverageRunner
class OurTestRunner(DjangoTestSuiteRunner):
def build_suite(self, test_labels, *args, **kwargs):
return super(OurTestRunner,self).build_suite(test_labels
or settings.PROJECT_APPS, *args, **kwargs)
class OurCoverageRunner(OurTestRunner, CoverageRunner):
pass
This only runs the tests on apps we
want tested and skips the rest!
91. Daniel Greenfeld
@pydanny
I’m Lazy
Are you testing enough?
Yeah, some of the configuration is off. Will be fixed soon.
92. Daniel Greenfeld
@pydanny
I’m Lazy
Don’t wanna upload zip files per document change
93. Daniel Greenfeld
@pydanny
I’m Lazy
Don’t wanna upload zip files per document change
READ
94. Daniel Greenfeld
@pydanny
I’m Lazy
Don’t wanna upload zip files per document change
READ
THE
95. Daniel Greenfeld
@pydanny
I’m Lazy
Don’t wanna upload zip files per document change
READ
THE
DOCS
96. Daniel Greenfeld
@pydanny
I’m Lazy
Don’t wanna upload zip files per document change
READ
THE
DOCS
.ORG
97. Daniel Greenfeld
@pydanny
I’m Lazy
Don’t wanna upload zip files per document change
READ
THE
DOCS
.ORG
http://readthedocs.org / http://rtfd.org
98. Daniel Greenfeld
@pydanny
I’m stupid
Can’t remember things
• Documentation makes me look good
• Docstrings are awesome
• Learn you some Restructured Text
• Write down even the slide bullets!
• https://github.com/pydanny/pydanny-event-notes
99. Daniel Greenfeld
@pydanny
I’m stupid
Can’t remember things
• Documentation makes me look good
• Docstrings are awesome
• Learn you some Restructured Text
• Write down even the slide bullets!
• https://github.com/pydanny/pydanny-event-notes
• http://pydanny-event-notes.rtfd.org
100. Daniel Greenfeld
@pydanny
Import your
project
I’m Lazy
Host your docs on http://rtfd.org
101. Daniel Greenfeld
@pydanny
I’m Lazy
Host your docs on http://rtfd.org
102. Daniel Greenfeld
@pydanny
I’m Lazy
Host your docs on http://rtfd.org
103. Daniel Greenfeld
@pydanny
I’m Lazy
Host your docs on http://rtfd.org
104. Daniel Greenfeld
@pydanny
I’m Lazy
Host your docs on http://rtfd.org
105. Daniel Greenfeld
@pydanny
I’m Lazy
Host your docs on http://rtfd.org
Admin
106. Daniel Greenfeld
@pydanny
I’m Lazy
Host your docs on http://rtfd.org
Admin
Service Hook
107. Daniel Greenfeld
@pydanny
I’m Lazy
Host your docs on http://rtfd.org
Admin
Service Hook
ReadTheDocs
108. Daniel Greenfeld
@pydanny
I’m Lazy
Host your docs on http://rtfd.org
Admin
Service Hook
ReadTheDocs
Active
113. Daniel Greenfeld
@pydanny
Django Worst Practice
Magical
INSTALLED_APPS += [p for p in os.listdir(BASE) if os.path.isdirr(p)]
settings MIDDLEWARE_CLASSES = [...]
def callback(arg, dirname, fnames):
code if 'middleware.py' in fnames:
m = '%s.middleware' % os.path.split(dirnaame)[-1] THIS
MIDDLEWARE_CLASSES.append(m)
urlpatterns = patterns('', ...)
CODE IS
Magical
for app in settings.INSTALLED_APPS:
if not app.startswith('django'): BROKEN
p = url('^%s/' % app, include('%s.urls') % app)
urls urlpatterns += patterns('', p)
code
http://www.slideshare.net/jacobian/the-best-and-worst-of-django
114. Daniel Greenfeld
@pydanny
Django Worst Practice
‘Magical configuration code’
Magical
INSTALLED_APPS += [p for p in os.listdir(BASE) if os.path.isdirr(p)]
settings MIDDLEWARE_CLASSES = [...]
def callback(arg, dirname, fnames):
code if 'middleware.py' in fnames:
m = '%s.middleware' % os.path.split(dirnaame)[-1] THIS
MIDDLEWARE_CLASSES.append(m)
urlpatterns = patterns('', ...)
CODE IS
Magical
for app in settings.INSTALLED_APPS:
if not app.startswith('django'): BROKEN
p = url('^%s/' % app, include('%s.urls') % app)
urls urlpatterns += patterns('', p)
code
http://www.slideshare.net/jacobian/the-best-and-worst-of-django
115. Daniel Greenfeld
@pydanny
Django Worst Practice
‘Magical configuration code’
Magical
INSTALLED_APPS += [p for p in os.listdir(BASE) if os.path.isdirr(p)]
settings MIDDLEWARE_CLASSES = [...]
def callback(arg, dirname, fnames):
code if 'middleware.py' in fnames:
m = '%s.middleware' % os.path.split(dirnaame)[-1] THIS
MIDDLEWARE_CLASSES.append(m)
urlpatterns = patterns('', ...)
CODE IS
Magical
for app in settings.INSTALLED_APPS:
if not app.startswith('django'): BROKEN
p = url('^%s/' % app, include('%s.urls') % app)
urls urlpatterns += patterns('', p)
code
Ugh.
http://www.slideshare.net/jacobian/the-best-and-worst-of-django
116. Daniel Greenfeld
@pydanny
Fixed Django Practice
urlpatterns = patterns("",
PREREQ_APPS = [
# Django url(r"^$", homepage, name="home"),
"django.contrib.admin", url(r"^accounts/", include("accounts.urls")),
"django.contrib.auth", url(r"^admin/", include(admin.site.urls)),
"django.contrib.contenttypes", url(r"^about/", include("about.urls")),
"django.contrib.sessions", url(r"^profiles/", include("profiles.urls")),
"django.contrib.sites", url(r"^notices/", include("notification.urls")),
"django.contrib.messages", ...
"django.contrib.humanize", MIDDLEWARE_CLASSES = [
)
"django.contrib.flatpages", "django.middleware.common.CommonMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
# external "django.middleware.csrf.CsrfViewMiddleware",
"notification", # must be first "django.contrib.auth.middleware.AuthenticationMiddleware",
"staticfiles", "reversion.middleware.RevisionMiddleware",
"uni_form", "django.contrib.messages.middleware.MessageMiddleware",
... ...
] ]
Explicit is better
This isn’t that much typing, is it?
then Implicit
117. Daniel Greenfeld
@pydanny
Fixed Django Practice
urlpatterns = patterns("",
PREREQ_APPS = [
# Django url(r"^$", homepage, name="home"),
"django.contrib.admin", url(r"^accounts/", include("accounts.urls")),
"django.contrib.auth", url(r"^admin/", include(admin.site.urls)),
"django.contrib.contenttypes", url(r"^about/", include("about.urls")),
"django.contrib.sessions", url(r"^profiles/", include("profiles.urls")),
"django.contrib.sites", url(r"^notices/", include("notification.urls")),
"django.contrib.messages", ...
"django.contrib.humanize", MIDDLEWARE_CLASSES = [
)
"django.contrib.flatpages", "django.middleware.common.CommonMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
# external "django.middleware.csrf.CsrfViewMiddleware",
"notification", # must be first "django.contrib.auth.middleware.AuthenticationMiddleware",
"staticfiles", "reversion.middleware.RevisionMiddleware",
"uni_form", "django.contrib.messages.middleware.MessageMiddleware",
... ...
] ]
Python’s design is predicated on the proposition that
code is more often read than written.
http://www.slideshare.net/jacobian/the-best-and-worst-of-django/44
124. Daniel Greenfeld
@pydanny
Technical Debt
Postponed Activities
• Documentation
• unshared knowledge
• Tests
• attending to TODO statements
http://bit.ly/technical-debt
125. Daniel Greenfeld
@pydanny
Technical Debt
Postponed Activities
• Documentation
• unshared knowledge
• Tests
• attending to TODO statements
• Code too confusing to be modified easily
http://bit.ly/technical-debt
130. Daniel Greenfeld
Jane Developer
@pydanny
Advocacy
• Now is the time
131. Daniel Greenfeld
Jane Developer
@pydanny
Advocacy
• Now is the time
• Empowerment through Education
132. Daniel Greenfeld
Jane Developer
@pydanny
Advocacy
• Now is the time
• Empowerment through Education
• Contribute to open source
133. Daniel Greenfeld
Jane Developer
@pydanny
Advocacy
• Now is the time
• Empowerment through Education
• Contribute to open source
• If you don’t step up then no one will
134. Daniel Greenfeld
Joe Developer
@pydanny
Advocacy
How to get involved with PyLadies as a man
135. Daniel Greenfeld
Joe Developer
@pydanny
Advocacy
How to get involved with PyLadies as a man
• Give your own time
136. Daniel Greenfeld
Joe Developer
@pydanny
Advocacy
How to get involved with PyLadies as a man
• Give your own time
• Honor your promised commitments
137. Daniel Greenfeld
Joe Developer
@pydanny
Advocacy
How to get involved with PyLadies as a man
• Give your own time
• Honor your promised commitments
• Give kudos to the men who bring ladies!
138. Daniel Greenfeld
Joe Developer
@pydanny
Advocacy
How to get involved with PyLadies as a man
• Give your own time
• Honor your promised commitments
• Give kudos to the men who bring ladies!
• Step back: Don’t try to run things.
140. Daniel Greenfeld
Acme Corporation
@pydanny
Advocacy
How to get involved as a company
http://en.wikipedia.org/wiki/Acme_Corporation
141. Daniel Greenfeld
Acme Corporation
@pydanny
Advocacy
How to get involved as a company
http://en.wikipedia.org/wiki/Acme_Corporation
142. Daniel Greenfeld
Acme Corporation
@pydanny
Advocacy
How to get involved as a company
• Sponsor because it’s the right thing to do
http://en.wikipedia.org/wiki/Acme_Corporation
143. Daniel Greenfeld
Acme Corporation
@pydanny
Advocacy
How to get involved as a company
• Sponsor because it’s the right thing to do
• Sponsor because you get a tax break
http://en.wikipedia.org/wiki/Acme_Corporation
144. Daniel Greenfeld
Acme Corporation
@pydanny
Advocacy
How to get involved as a company
• Sponsor because it’s the right thing to do
• Sponsor because you get a tax break
• Sponsor because good developers notice
http://en.wikipedia.org/wiki/Acme_Corporation
145. Daniel Greenfeld
Acme Corporation
@pydanny
Advocacy
How to get involved as a company
• Sponsor because it’s the right thing to do
• Sponsor because you get a tax break
• Sponsor because good developers notice
• Mozilla
http://en.wikipedia.org/wiki/Acme_Corporation
146. Daniel Greenfeld
Acme Corporation
@pydanny
Advocacy
How to get involved as a company
• Sponsor because it’s the right thing to do
• Sponsor because you get a tax break
• Sponsor because good developers notice
• Mozilla
• cars.com
http://en.wikipedia.org/wiki/Acme_Corporation