Weitere Ă€hnliche Inhalte KĂŒrzlich hochgeladen (20) Django Don't Do This - DjangoToronto - January, 20121. DON
DO T
THI
S!
ash.christopher@gmail.com
@ashchristopher
Friday, 20 January, 12
8. Common mistakes as a result
of gaining more experience
with Django
Friday, 20 January, 12
9. Common mistakes as a result
of gaining more experience
with Django
(in no particular order)
Friday, 20 January, 12
15. Models
They define your data.
Friday, 20 January, 12
16. Models
They donât define behavior.
Friday, 20 January, 12
17. Models
They canât read your mind.
Friday, 20 January, 12
26. What are indexes?
They are pointers to your data
... in memory
Friday, 20 January, 12
27. What are indexes?
They are pointers to your data
... in memory
... or on disk!!!
Friday, 20 January, 12
28. They slow down inserts,
updates and deletes.
Friday, 20 January, 12
29. As a general rule, you
want an index on
anything you will use
to limit results
Friday, 20 January, 12
30. As a general rule, you
want an index on
anything you will use
to limit results
... but generalizations break down quickly.
Friday, 20 January, 12
31. You need to assess your
specific needs.
Friday, 20 January, 12
32. DO analyze
your QuerySets
to determine
where indexes
are needed.
Friday, 20 January, 12
34. DONâT use
locals() to
populate your
context
Friday, 20 January, 12
35. I PITY THE FOOL...
WHO HAS TO DEBUG
YOUR TEMPLATE
Friday, 20 January, 12
38. Every time you use
locals() to populate your
context, God kills a kitten.
Friday, 20 January, 12
39. def my_view(request):
! users = User.objects.filter(active=True)
! num_users = len(users)
! message = None
! if num_users > 3:
! ! message = "Three's a crowd."
context = locals()
!
return render_to_response(
'/path/to/template.html', context)
Friday, 20 January, 12
40. def my_view(request):
! users = User.objects.filter(active=True)
! num_users = len(users)
! message = None
! if num_users > 3:
! ! message = "Three's a crowd."
context = locals()
!
return render_to_response(
'/path/to/template.html', context)
Thumbs down!
Friday, 20 January, 12
41. context = {'context': <Recursion on dict with id=175092300>,
'ipdb': <module 'ipdb' from '/home/vagrant/.virtualenvs/wave/lib/python2.6/site-packages/ipdb/
__init__.pyc'>,
'message': "Three's a crowd.",
'num_users': 9,
'pprint': <function pprint at 0x8a88f44>,
'request': <WSGIRequest
GET:<QueryDict: {}>,
POST:<QueryDict: {}>,
COOKIES:{'__utma': '111872281.606618788.1318529036.1326747382.1326750603.150',
'__utmc': '111872281',
'__utmz': '111872281.1318529036.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)',
'csrftoken': '********************************',
'sessionid': '********************************'},
META:{'CELERY_LOADER': 'djcelery.loaders.DjangoLoader',
'CONTENT_LENGTH': '',
'CONTENT_TYPE': 'text/plain',
'CSRF_COOKIE': '********************************',
'DJANGO_SETTINGS_MODULE': 'waveaccounting.settings',
'GATEWAY_INTERFACE': 'CGI/1.1',
'HOME': '/home/vagrant',
'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'HTTP_ACCEPT_CHARSET': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'HTTP_ACCEPT_ENCODING': 'gzip, deflate',
'HTTP_ACCEPT_LANGUAGE': 'en-us,en;q=0.5',
'HTTP_CONNECTION': 'keep-alive',
'HTTP_COOKIE': 'csrftoken=********************************;
__utma=111872281.606618788.1318529036.1326747382.1326750603.150;
__utmz=111872281.1318529036.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);
sessionid=********************************; __utmc=111872281',
'HTTP_HOST': 'localhost:8000',
'HTTP_USER_AGENT': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:9.0.1) Gecko/20100101 Firefox/9.0.1',
'LANG': 'en_US.UTF-8',
'LESSCLOSE': '/usr/bin/lesspipe %s %s',
'LESSOPEN': '| /usr/bin/lesspipe %s',
'LOGNAME': 'vagrant',
Friday, 20 January, 12
42. 'LS_COLORS':
'rs=0:di=01;34:ln=01;36:hl=44;37:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43
:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;3
1:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rp
m=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.
7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;3
5:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mo
v=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vo
b=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.ïŹc=01;35:*.avi=01;35:*.ïŹi=01;35:*.ïŹ
v=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.a
ac=00;36:*.au=00;36:*.ïŹac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;
36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:',
'MAIL': '/var/mail/vagrant',
'OLDPWD': '/home/vagrant',
'PATH': '/home/vagrant/.virtualenvs/wave/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/
ruby/bin/',
'PATH_INFO': u'/en/settings/business/1/',
'PIP_RESPECT_VIRTUALENV': 'true',
'PS1': '(wave)[e]0;u@h: wa]${debian_chroot:+($debian_chroot)}u@h:w$ ',
'PWD': '/home/vagrant/Projects/wa/waveaccounting',
'QUERY_STRING': '',
'REMOTE_ADDR': '10.0.2.2',
'REMOTE_HOST': '',
'REQUEST_METHOD': 'GET',
'RUN_MAIN': 'true',
'SCRIPT_NAME': u'',
'SERVER_NAME': 'lucid32',
'SERVER_PORT': '8000',
'SERVER_PROTOCOL': 'HTTP/1.1',
Friday, 20 January, 12
43. 'SERVER_SOFTWARE': 'WSGIServer/0.1 Python/2.6.5',
'SHELL': '/bin/bash',
'SHLVL': '1',
'SSH_CLIENT': '10.0.2.2 50056 22',
'SSH_CONNECTION': '10.0.2.2 50056 10.0.2.15 22',
'SSH_TTY': '/dev/pts/2',
'TERM': 'xterm-256color',
'TZ': 'America/Toronto',
'USER': 'vagrant',
'VIRTUALENVWRAPPER_HOOK_DIR': '/home/vagrant/.virtualenvs',
'VIRTUALENVWRAPPER_LOG_DIR': '/home/vagrant/.virtualenvs',
'VIRTUAL_ENV': '/home/vagrant/.virtualenvs/wave',
'WORKON_HOME': '/home/vagrant/.virtualenvs',
'_': '/home/vagrant/.virtualenvs/wave/bin/python',
'wsgi.errors': <open ïŹle '<stderr>', mode 'w' at 0xb77600d0>,
'wsgi.ïŹle_wrapper': <class 'django.core.servers.basehttp.FileWrapper'>,
'wsgi.input': <socket._ïŹleobject object at 0x9c602ec>,
'wsgi.multiprocess': False,
'wsgi.multithread': True,
'wsgi.run_once': False,
'wsgi.url_scheme': 'http',
'wsgi.version': (1, 0)}>,
'users': [<User: ash@waveaccounting.com>, <User: ash+2@waveaccounting.com>, <User: ash+3@waveaccounting.com>,
<User: ehabjan4@wavetest.com>, <User: foo@example.com>, <User: ash@example.com>, <User: ash@wavereceipts.com>,
<User: >, <User: james+compound@waveaccounting.com>]}
Friday, 20 January, 12
45. Did you notice?
'context': <Recursion on dict with id=175092300>
Friday, 20 January, 12
46. Did you notice?
'context': <Recursion on dict with id=175092300>
context
Friday, 20 January, 12
47. Did you notice?
'context': <Recursion on dict with id=175092300>
context [âcontextâ]
Friday, 20 January, 12
48. Did you notice?
'context': <Recursion on dict with id=175092300>
context [âcontextâ] [âcontextâ]
Friday, 20 January, 12
49. Did you notice?
'context': <Recursion on dict with id=175092300>
context [âcontextâ] [âcontextâ] [âcontextâ]
Friday, 20 January, 12
50. Did you notice?
'context': <Recursion on dict with id=175092300>
context [âcontextâ] [âcontextâ] [âcontextâ] ...
Friday, 20 January, 12
51. Please... do it this way!
def my_view(request):
! users = User.objects.filter(active=True)
! num_users = len(users)
! message = None
! if num_users > 3:
! ! message = "Three's a crowd."
! context = {
! ! 'message' : message,
! }
! return render_to_response(
'/path/to/template.html', context)
Friday, 20 January, 12
54. DONâT replace
get_query_set()
with something
unexpected.
Friday, 20 January, 12
55. The majority of
developers and apps
expect objects.all() to
return ALL objects.
Friday, 20 January, 12
57. EXAMPLE
class CustomQuerySet(QuerySet):
def active(self):
return self.filter(is_active=True)
class MyManager(models.Manager):
def get_query_set(self):
return CustomQuerySet(self.model)
Friday, 20 January, 12
58. To get the active users:
MyModel.objects.active()
Friday, 20 January, 12
60. What about in the
admin?
class CustomModelAdmin(admin.ModelAdmin):
def queryset(self, request):
âââ Only superusers can access all objects in the admin. âââ
qs = super(CustomModelAdmin, self).queryset(request)
if not request.user.is_superuser:
qs = qs.active()
return qs
Friday, 20 January, 12
64. Even the best Django
developers make this mistake
Friday, 20 January, 12
65. Even the best Django
developers make this mistake
Friday, 20 January, 12
66. Even the best Django
developers make this mistake
are you sure that's
a good idea?
Friday, 20 January, 12
67. Even the best Django
developers make this mistake
i think its a really good
usage pattern
Friday, 20 January, 12
68. Even the best Django
developers make this mistake
your POST data doesn't
necessarily exist.
Friday, 20 January, 12
69. Even the best Django
developers make this mistake
oh... crap
Friday, 20 January, 12
70. Even the best Django
developers make this mistake
pwned you!
Friday, 20 January, 12
71. Even the best Django
developers make this mistake
...
Friday, 20 January, 12
72. Even the best Django
developers make this mistake
FOLLOW THE
PATTERN, BITCHES!
Friday, 20 January, 12
73. DO follow the
conventions
outlined by the
Django community
Friday, 20 January, 12
78. Tell me Iâm wrong
ash.christopher@gmail.com
@ashchristopher
Friday, 20 January, 12