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

7,688 views
7,617 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
7,688
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
20
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

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

×