Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
DON                                  DO T                                THI                                   S!         ...
Who am I?Friday, 20 January, 12
Systems AnalystFriday, 20 January, 12
Senior Developer               and Team LeadFriday, 20 January, 12
Senior DeveloperFriday, 20 January, 12
What is this                         talk about?Friday, 20 January, 12
Common MistakesFriday, 20 January, 12
Common mistakes as a result                      of gaining more experience                              with DjangoFriday...
Common mistakes as a result                      of gaining more experience                              with Django      ...
Friday, 20 January, 12
Don’t be *this* guy.Friday, 20 January, 12
Defining Models                         without indexesFriday, 20 January, 12
DON’T forget                         your indexesFriday, 20 January, 12
ModelsFriday, 20 January, 12
Models                         They define your data.Friday, 20 January, 12
Models                         They don’t define behavior.Friday, 20 January, 12
Models                         They can’t read your mind.Friday, 20 January, 12
Even seasoned Django            developers forget about                    indexesFriday, 20 January, 12
Remember this?Friday, 20 January, 12
Remember this?Friday, 20 January, 12
DO add indexes                     to your Models.Friday, 20 January, 12
Over-IndexingFriday, 20 January, 12
DON’T index                         everythingFriday, 20 January, 12
What are indexes?Friday, 20 January, 12
What are indexes?                         They are pointers to your dataFriday, 20 January, 12
What are indexes?                         They are pointers to your data                                 ... in memoryFrid...
What are indexes?                         They are pointers to your data                                 ... in memory    ...
They slow down inserts,           updates and deletes.Friday, 20 January, 12
As a general rule, you                    want an index on                  anything you will use                     to l...
As a general rule, you                    want an index on                  anything you will use                     to l...
You need to assess your                specific needs.Friday, 20 January, 12
DO analyze                         your QuerySets                          to determine                         where inde...
Silly ShortcutsFriday, 20 January, 12
DON’T use                          locals() to                         populate your                            contextFri...
I PITY THE FOOL...        WHO HAS TO DEBUG          YOUR TEMPLATEFriday, 20 January, 12
It’s not clever.Friday, 20 January, 12
It’s just lazy.Friday, 20 January, 12
Every time you use                         locals() to populate your                          context, God kills a kitten....
def my_view(request):                         ! users = User.objects.filter(active=True)                         ! num_use...
def my_view(request):                         ! users = User.objects.filter(active=True)                         ! num_use...
context = {context: <Recursion on dict with id=175092300>,          ipdb: <module ipdb from /home/vagrant/.virtualenvs/wav...
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=4...
SERVER_SOFTWARE: WSGIServer/0.1 Python/2.6.5,              SHELL: /bin/bash,              SHLVL: 1,              SSH_CLIEN...
Weird stuff happens.Friday, 20 January, 12
Did you notice?       context: <Recursion on dict with id=175092300>Friday, 20 January, 12
Did you notice?       context: <Recursion on dict with id=175092300>             contextFriday, 20 January, 12
Did you notice?       context: <Recursion on dict with id=175092300>             context [‘context’]Friday, 20 January, 12
Did you notice?       context: <Recursion on dict with id=175092300>             context [‘context’] [‘context’]Friday, 20...
Did you notice?       context: <Recursion on dict with id=175092300>             context [‘context’] [‘context’] [‘context...
Did you notice?       context: <Recursion on dict with id=175092300>             context [‘context’] [‘context’] [‘context...
Please... do it this way!                         def my_view(request):                         ! users = User.objects.fil...
DO define your             context explicitlyFriday, 20 January, 12
Replacing the .all()                   method on QuerySetsFriday, 20 January, 12
DON’T replace             get_query_set()              with something               unexpected.Friday, 20 January, 12
The majority of                     developers and apps                     expect objects.all() to                      r...
That’s why it’s called .all()Friday, 20 January, 12
EXAMPLE                         class CustomQuerySet(QuerySet):                             def active(self):             ...
To get the active users:                         MyModel.objects.active()Friday, 20 January, 12
What about in the                            admin?Friday, 20 January, 12
What about in the                            admin?   class CustomModelAdmin(admin.ModelAdmin):             def queryset(s...
DO explicitly                          define your                          QuerySetsFriday, 20 January, 12
Creating new ways to                   do the same things.Friday, 20 January, 12
DON’T invent                          new Django                         conventions.Friday, 20 January, 12
Even the best Django                         developers make this mistakeFriday, 20 January, 12
Even the best Django                         developers make this mistakeFriday, 20 January, 12
Even the best Django                         developers make this mistake                                     are you sure...
Even the best Django                         developers make this mistake                               i think its a real...
Even the best Django                         developers make this mistake                                 your POST data d...
Even the best Django                         developers make this mistake                                oh... crapFriday,...
Even the best Django                         developers make this mistake                                        pwned you...
Even the best Django                         developers make this mistake                                    ...Friday, 20...
Even the best Django                         developers make this mistake                                   FOLLOW THE    ...
DO follow the        conventions       outlined by the     Django communityFriday, 20 January, 12
They have more                         experience than you                                 do.Friday, 20 January, 12
They have built                          more projects                         than you have.Friday, 20 January, 12
They know better                           than you do.Friday, 20 January, 12
Tell me I’m wrongFriday, 20 January, 12
Tell me I’m wrong                         ash.christopher@gmail.com                             @ashchristopherFriday, 20 ...
Upcoming SlideShare
Loading in …5
×

Django Don't Do This - DjangoToronto - January, 2012

8,217 views

Published on

Published in: Technology
  • Be the first to comment

Django Don't Do This - DjangoToronto - January, 2012

  1. 1. DON DO T THI S! ash.christopher@gmail.com @ashchristopherFriday, 20 January, 12
  2. 2. Who am I?Friday, 20 January, 12
  3. 3. Systems AnalystFriday, 20 January, 12
  4. 4. Senior Developer and Team LeadFriday, 20 January, 12
  5. 5. Senior DeveloperFriday, 20 January, 12
  6. 6. What is this talk about?Friday, 20 January, 12
  7. 7. Common MistakesFriday, 20 January, 12
  8. 8. Common mistakes as a result of gaining more experience with DjangoFriday, 20 January, 12
  9. 9. Common mistakes as a result of gaining more experience with Django (in no particular order)Friday, 20 January, 12
  10. 10. Friday, 20 January, 12
  11. 11. Don’t be *this* guy.Friday, 20 January, 12
  12. 12. Defining Models without indexesFriday, 20 January, 12
  13. 13. DON’T forget your indexesFriday, 20 January, 12
  14. 14. ModelsFriday, 20 January, 12
  15. 15. Models They define your data.Friday, 20 January, 12
  16. 16. Models They don’t define behavior.Friday, 20 January, 12
  17. 17. Models They can’t read your mind.Friday, 20 January, 12
  18. 18. Even seasoned Django developers forget about indexesFriday, 20 January, 12
  19. 19. Remember this?Friday, 20 January, 12
  20. 20. Remember this?Friday, 20 January, 12
  21. 21. DO add indexes to your Models.Friday, 20 January, 12
  22. 22. Over-IndexingFriday, 20 January, 12
  23. 23. DON’T index everythingFriday, 20 January, 12
  24. 24. What are indexes?Friday, 20 January, 12
  25. 25. What are indexes? They are pointers to your dataFriday, 20 January, 12
  26. 26. What are indexes? They are pointers to your data ... in memoryFriday, 20 January, 12
  27. 27. What are indexes? They are pointers to your data ... in memory ... or on disk!!!Friday, 20 January, 12
  28. 28. They slow down inserts, updates and deletes.Friday, 20 January, 12
  29. 29. As a general rule, you want an index on anything you will use to limit resultsFriday, 20 January, 12
  30. 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. 31. You need to assess your specific needs.Friday, 20 January, 12
  32. 32. DO analyze your QuerySets to determine where indexes are needed.Friday, 20 January, 12
  33. 33. Silly ShortcutsFriday, 20 January, 12
  34. 34. DON’T use locals() to populate your contextFriday, 20 January, 12
  35. 35. I PITY THE FOOL... WHO HAS TO DEBUG YOUR TEMPLATEFriday, 20 January, 12
  36. 36. It’s not clever.Friday, 20 January, 12
  37. 37. It’s just lazy.Friday, 20 January, 12
  38. 38. Every time you use locals() to populate your context, God kills a kitten.Friday, 20 January, 12
  39. 39. def my_view(request): ! users = User.objects.filter(active=True) ! num_users = len(users) ! message = None ! if num_users > 3: ! ! message = "Threes a crowd." context = locals() ! return render_to_response( /path/to/template.html, context)Friday, 20 January, 12
  40. 40. def my_view(request): ! users = User.objects.filter(active=True) ! num_users = len(users) ! message = None ! if num_users > 3: ! ! message = "Threes a crowd." context = locals() ! return render_to_response( /path/to/template.html, context) Thumbs down!Friday, 20 January, 12
  41. 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: "Threes 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. 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:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.fl 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:*.flac=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. 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 file <stderr>, mode w at 0xb77600d0>, wsgi.file_wrapper: <class django.core.servers.basehttp.FileWrapper>, wsgi.input: <socket._fileobject 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
  44. 44. Weird stuff happens.Friday, 20 January, 12
  45. 45. Did you notice? context: <Recursion on dict with id=175092300>Friday, 20 January, 12
  46. 46. Did you notice? context: <Recursion on dict with id=175092300> contextFriday, 20 January, 12
  47. 47. Did you notice? context: <Recursion on dict with id=175092300> context [‘context’]Friday, 20 January, 12
  48. 48. Did you notice? context: <Recursion on dict with id=175092300> context [‘context’] [‘context’]Friday, 20 January, 12
  49. 49. Did you notice? context: <Recursion on dict with id=175092300> context [‘context’] [‘context’] [‘context’]Friday, 20 January, 12
  50. 50. Did you notice? context: <Recursion on dict with id=175092300> context [‘context’] [‘context’] [‘context’] ...Friday, 20 January, 12
  51. 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 = "Threes a crowd." ! context = { ! ! message : message, ! } ! return render_to_response( /path/to/template.html, context)Friday, 20 January, 12
  52. 52. DO define your context explicitlyFriday, 20 January, 12
  53. 53. Replacing the .all() method on QuerySetsFriday, 20 January, 12
  54. 54. DON’T replace get_query_set() with something unexpected.Friday, 20 January, 12
  55. 55. The majority of developers and apps expect objects.all() to return ALL objects.Friday, 20 January, 12
  56. 56. That’s why it’s called .all()Friday, 20 January, 12
  57. 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. 58. To get the active users: MyModel.objects.active()Friday, 20 January, 12
  59. 59. What about in the admin?Friday, 20 January, 12
  60. 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 qsFriday, 20 January, 12
  61. 61. DO explicitly define your QuerySetsFriday, 20 January, 12
  62. 62. Creating new ways to do the same things.Friday, 20 January, 12
  63. 63. DON’T invent new Django conventions.Friday, 20 January, 12
  64. 64. Even the best Django developers make this mistakeFriday, 20 January, 12
  65. 65. Even the best Django developers make this mistakeFriday, 20 January, 12
  66. 66. Even the best Django developers make this mistake are you sure thats a good idea?Friday, 20 January, 12
  67. 67. Even the best Django developers make this mistake i think its a really good usage patternFriday, 20 January, 12
  68. 68. Even the best Django developers make this mistake your POST data doesnt necessarily exist.Friday, 20 January, 12
  69. 69. Even the best Django developers make this mistake oh... crapFriday, 20 January, 12
  70. 70. Even the best Django developers make this mistake pwned you!Friday, 20 January, 12
  71. 71. Even the best Django developers make this mistake ...Friday, 20 January, 12
  72. 72. Even the best Django developers make this mistake FOLLOW THE PATTERN, BITCHES!Friday, 20 January, 12
  73. 73. DO follow the conventions outlined by the Django communityFriday, 20 January, 12
  74. 74. They have more experience than you do.Friday, 20 January, 12
  75. 75. They have built more projects than you have.Friday, 20 January, 12
  76. 76. They know better than you do.Friday, 20 January, 12
  77. 77. Tell me I’m wrongFriday, 20 January, 12
  78. 78. Tell me I’m wrong ash.christopher@gmail.com @ashchristopherFriday, 20 January, 12

×