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 ...
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.
Confessions of Joe DeveloperPresentation Transcript
Confessions ofJoe Developer Daniel Greenfeld
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 Royhttp://www.flickr.com/photos/pydanny/4442245488
Why am I talking?
I’m stupid and lazy
I’m stupid
Daniel Greenfeld @pydannyI’m stupid
Daniel Greenfeld @pydanny I’m stupid• Can’t figure things out
Daniel Greenfeld @pydanny I’m stupid• Can’t figure things out• Can’t remember things
Daniel Greenfeld @pydanny I’m stupid• Can’t figure things out• Can’t remember things• Too stupid not to ask stupid questions
Daniel Greenfeld @pydanny I’m stupidCan’t figure things out
Daniel Greenfeld @pydanny I’m stupid Can’t figure things out• If I get stuck for more than 30 minutes...
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
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
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.
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.
Daniel Greenfeld @pydanny I’m stupidCan’t figure things out
Daniel Greenfeld @pydanny I’m stupid Can’t figure things out “Smart” people way# This sample gleefully taken from https://gist.github.com/973705import urllib2gh_url = https://api.github.comgh_user= usergh_pass = passreq = 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
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 fromimport urllib2 # https://gist.github.com/973705gh_url = https://api.github.comgh_user= usergh_pass = pass import requestsreq = 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_codeopener = urllib2.build_opener(auth_manager) print r.headers[content-type]urllib2.install_opener(opener)handler = urllib2.urlopen(req) # ------ # 200print handler.getcode()print handler.headers.getheader(content-type) # application/json# ------# 200# application/json
Daniel Greenfeld @pydannyI’m stupid ‘Smart way’ aka hard way
Daniel Greenfeld @pydanny I’m stupid# This sample gleefully taken from# https://gist.github.com/973705 ‘Smart way’import urllib2 akagh_url = https://api.github.comgh_user= usergh_pass = pass hard wayreq = 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
Daniel Greenfeld @pydanny I’m stupid # This sample gleefully taken from # https://gist.github.com/973705 ‘Smart way’ What import urllib2 akais 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
Daniel Greenfeld @pydanny I’m stupid # This sample gleefully taken from # https://gist.github.com/973705 ‘Smart way’ What import urllib2 akais 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
Daniel Greenfeld @pydanny I’m stupid # This sample gleefully taken from # https://gist.github.com/973705 ‘Smart way’ What import urllib2 akais 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
Daniel Greenfeld @pydanny I’m stupid # This sample gleefully taken from # https://gist.github.com/973705 ‘Smart way’ What import urllib2 akais 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
Daniel Greenfeld @pydanny I’m stupid ‘Stupid way’ akaCan’t figure things out easy way
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/973705import requestsr = requests.get(https://api.github.com, auth=(user, pass))print r.status_codeprint r.headers[content-type]# ------# 200# application/json
Daniel Greenfeld @pydanny I’m stupid ‘Stupid way’ akaHTTP Can’t figure things outGET 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
Daniel Greenfeld @pydanny I’m stupid ‘Stupid way’ akaHTTP Can’t figure things outGET 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_codePassword print r.headers[content-type] # ------ # 200 # application/json
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 fromimport urllib2 # https://gist.github.com/973705gh_url = https://api.github.comgh_user= usergh_pass = pass import requestsreq = 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_codeopener = urllib2.build_opener(auth_manager) print r.headers[content-type]urllib2.install_opener(opener)handler = urllib2.urlopen(req) # ------ # 200print handler.getcode()print handler.headers.getheader(content-type) # application/json# ------# 200# application/json
Daniel Greenfeld @pydanny I’m stupidToo stupid not to ask stupid questions
Daniel Greenfeld @pydanny I’m stupidToo stupid not to ask stupid questions • There are no stupid questions
Daniel Greenfeld @pydanny I’m stupidToo stupid not to ask stupid questions • There are no stupid questions • Don’t try and impress the people around you by not asking questions.
Daniel Greenfeld @pydanny I’m stupidToo stupid not to ask stupid questions You are at DjangoCon. If you don’t ask the question, you are wasting opportunity.
Daniel Greenfeld @pydanny I’m stupidToo 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.
Daniel Greenfeld @pydanny I’m stupidCan’t remember things
Daniel Greenfeld @pydanny I’m stupid Can’t remember things• Documentation makes me look good
Daniel Greenfeld @pydanny I’m stupid Can’t remember things• Documentation makes me look good• Docstrings are awesome
Daniel Greenfeld @pydanny I’m stupid Can’t remember things• Documentation makes me look good• Docstrings are awesome• Learn you some Restructured Text
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!
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
Daniel Greenfeld Joe Developer @pydanny Resources Where the code examples live!https://github.com/pydanny/django-party-pack http://django-party-pack.rtfd.org/
Daniel Greenfeld @pydanny I’m stupidhttp://readthedocs.org/docs/django-party-pack
Daniel Greenfeld @pydanny I’m stupidSphinxmakes me lookgood! http://readthedocs.org/docs/django-party-pack
Daniel Greenfeld @pydanny Docs/Sphinx Basics• pip install sphinx• make a docs directory• sphinx-quickstart• Follow instructions• Starting over is just removing your docs
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 testhttp://readthedocs.org/docs/django-party-pack/en/latest/_sources/install.txt
Daniel Greenfeld @pydanny pageheader 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
Daniel Greenfeld @pydanny pageheader 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
Daniel Greenfeld @pydanny pageheader 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
Daniel Greenfeld @pydanny I’m stupidhttp://readthedocs.org/docs/django-party-pack
Daniel Greenfeld @pydanny I’m stupidSphinxmakes me lookgood! http://readthedocs.org/docs/django-party-pack
Daniel Greenfeld @pydanny I’m stupid Sphinx makes me look good!http://readthedocs.org/docs/django-party-pack/en/latest/reference_polls.html
Daniel Greenfeld @pydanny I’m stupid Sphinx makes me look good!http://readthedocs.org/docs/django-party-pack/en/latest/reference_polls.html
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
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
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
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
Daniel Greenfeld @pydanny I’m stupid Sphinx makes me look good!http://readthedocs.org/docs/django-party-pack/en/latest/reference_polls.html
Daniel Greenfeld @pydanny I’m stupid Sphinx makes me look good!http://readthedocs.org/docs/django-party-pack/en/latest/reference_polls.html
Daniel Greenfeld @pydanny Sphinx walk-throughhttp://audreyr.posterous.com/how-to-create-sphinx-docs-the-python-github-r or http://bit.ly/audreyr-sphinx
I’m lazy
Daniel Greenfeld @pydannyI’m lazy
Daniel Greenfeld @pydanny I’m lazy• Don’t wanna do anything twice
Daniel Greenfeld @pydanny I’m lazy• Don’t wanna do anything twice• Don’t wanna debug code when I had it working before
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
Daniel Greenfeld @pydanny I’m lazyDon’t wanna do anything twice
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
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.
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.
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?
Daniel Greenfeld @pydanny I’m LazyDon’t wanna debug code when I had it working before
Daniel Greenfeld @pydanny I’m LazyDon’t wanna debug code when I had it working before • Manually testing code by watching it run is hard...
Daniel Greenfeld @pydanny I’m LazyDon’t wanna debug code when I had it working before • Manually testing code by watching it run is hard... • ...and boring...
Daniel Greenfeld @pydanny I’m LazyDon’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.
Daniel Greenfeld @pydanny I’m LazyDon’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.
Daniel Greenfeld @pydanny I’m LazyAre you testing enough?
Daniel Greenfeld @pydanny I’m Lazy Are you testing enough? Stick even the ‘basicstuff’ in the docs!
Daniel Greenfeld @pydanny I’m LazyAre you testing enough?
Daniel Greenfeld @pydanny I’m Lazy Are you testing enough?Yeah, some of the configuration is off. Will be fixed soon.
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
Daniel Greenfeldsettings.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_APPSexclude 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
testrunner.py Daniel Greenfeld @pydanny# Make our own testrunner that by default only tests our ownappsfrom django.conf import settingsfrom django.test.simple import DjangoTestSuiteRunnerfrom django_coverage.coverage_runner import CoverageRunnerclass 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!
Daniel Greenfeld @pydanny I’m LazyAre you testing enough?
Daniel Greenfeld @pydanny I’m Lazy Are you testing enough?Yeah, some of the configuration is off. Will be fixed soon.
Daniel Greenfeld @pydanny I’m LazyDon’t wanna upload zip files per document change
Daniel Greenfeld @pydanny I’m LazyDon’t wanna upload zip files per document change READ
Daniel Greenfeld @pydanny I’m LazyDon’t wanna upload zip files per document change READ THE
Daniel Greenfeld @pydanny I’m LazyDon’t wanna upload zip files per document change READ THE DOCS
Daniel Greenfeld @pydanny I’m LazyDon’t wanna upload zip files per document change READ THE DOCS .ORG
Daniel Greenfeld @pydanny I’m LazyDon’t wanna upload zip files per document change READ THE DOCS .ORG http://readthedocs.org / http://rtfd.org
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
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
Daniel Greenfeld @pydannyImport your project I’m Lazy Host your docs on http://rtfd.org
Daniel Greenfeld @pydanny I’m LazyHost your docs on http://rtfd.org
Daniel Greenfeld @pydanny I’m LazyHost your docs on http://rtfd.org
Daniel Greenfeld @pydanny I’m LazyHost your docs on http://rtfd.org
Daniel Greenfeld @pydanny I’m LazyHost your docs on http://rtfd.org
Daniel Greenfeld @pydanny I’m LazyHost your docs on http://rtfd.org Admin
Daniel Greenfeld @pydanny I’m LazyHost your docs on http://rtfd.org Admin Service Hook
Daniel Greenfeld @pydanny I’m LazyHost your docs on http://rtfd.org Admin Service Hook ReadTheDocs
Daniel Greenfeld @pydanny I’m LazyHost your docs on http://rtfd.org Admin Service Hook ReadTheDocs Active
Daniel Greenfeld @pydannyI’m Lazy django-party-pack-rtfd.org
Daniel Greenfeld @pydannyI’m Lazy pydanny-event-notes.rtfd.org
Daniel Greenfeld @pydannySphinx Trick! /django-party-pack /docs /conf.py Makes Sphinx play nicely with Django
Don’t be smart and lazy
Daniel Greenfeld @pydanny Django Worst PracticeMagical 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 ISMagical 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
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 ISMagical 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
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 ISMagical 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
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
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
I’m stupid and lazy
Daniel Greenfeld @pydannyTechnical Debthttp://bit.ly/technical-debt
Daniel Greenfeld @pydanny Technical DebtPostponed Activities http://bit.ly/technical-debt
Daniel Greenfeld @pydanny Technical DebtPostponed Activities • Documentation http://bit.ly/technical-debt
Daniel Greenfeld @pydanny Technical DebtPostponed Activities • Documentation • unshared knowledge • Tests • attending to TODO statements http://bit.ly/technical-debt
Daniel Greenfeld @pydanny Technical DebtPostponed Activities • Documentation • unshared knowledge • Tests • attending to TODO statements • Code too confusing to be modified easily http://bit.ly/technical-debt
Advocacy
Daniel Greenfeld @pydannyWhy?
Daniel Greenfeld @pydanny More funcommunityhttp://www.flickr.com/photos/pydanny/5851931370/
Daniel GreenfeldJane Developer @pydanny Advocacy
Daniel Greenfeld Jane Developer @pydanny Advocacy• Now is the time
Daniel Greenfeld Jane Developer @pydanny Advocacy• Now is the time• Empowerment through Education
Daniel Greenfeld Jane Developer @pydanny Advocacy• Now is the time• Empowerment through Education• Contribute to open source
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
Daniel Greenfeld Joe Developer @pydanny AdvocacyHow to get involved with PyLadies as a man
Daniel Greenfeld Joe Developer @pydanny AdvocacyHow to get involved with PyLadies as a man • Give your own time
Daniel Greenfeld Joe Developer @pydanny AdvocacyHow to get involved with PyLadies as a man • Give your own time • Honor your promised commitments
Daniel Greenfeld Joe Developer @pydanny AdvocacyHow to get involved with PyLadies as a man • Give your own time • Honor your promised commitments • Give kudos to the men who bring ladies!
Daniel Greenfeld Joe Developer @pydanny AdvocacyHow 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.
Daniel GreenfeldAcme Corporation @pydanny Advocacy http://en.wikipedia.org/wiki/File:Acme_anvil.gif
Daniel Greenfeld Acme Corporation @pydanny Advocacy How to get involved as a companyhttp://en.wikipedia.org/wiki/Acme_Corporation
Daniel Greenfeld Acme Corporation @pydanny Advocacy How to get involved as a companyhttp://en.wikipedia.org/wiki/Acme_Corporation
Daniel Greenfeld Acme Corporation @pydanny Advocacy How to get involved as a company • Sponsor because it’s the right thing to dohttp://en.wikipedia.org/wiki/Acme_Corporation
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 breakhttp://en.wikipedia.org/wiki/Acme_Corporation
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 noticehttp://en.wikipedia.org/wiki/Acme_Corporation
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 • Mozillahttp://en.wikipedia.org/wiki/Acme_Corporation
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.comhttp://en.wikipedia.org/wiki/Acme_Corporation
Daniel Greenfeld Joe/Jane Developer @pydanny Resources party-packhttps://github.com/pydanny/django-party-pack/ http://django-party-pack.rtfd.org/ http://bit.ly/audreyr-sphinx
Questions?
Let LinkedIn power your SlideShare experience
+
Let LinkedIn power your SlideShare experience
Customize SlideShare content based on your interests
We will import your LinkedIn profile and you will be visible on SlideShare.
Keep up to date when your LinkedIn contacts post on SlideShare
1–1 of 1 previous next