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

78
[email protected] @ashchristopher DONT DO THIS! Friday, 20 January, 12

description

 

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

Page 1: Django Don't Do This - DjangoToronto - January, 2012

[email protected]@ashchristopher

DONT DO THIS!

Friday, 20 January, 12

Page 2: Django Don't Do This - DjangoToronto - January, 2012

Who am I?

Friday, 20 January, 12

Page 3: Django Don't Do This - DjangoToronto - January, 2012

Systems Analyst

Friday, 20 January, 12

Page 4: Django Don't Do This - DjangoToronto - January, 2012

Senior Developer and Team Lead

Friday, 20 January, 12

Page 5: Django Don't Do This - DjangoToronto - January, 2012

Senior Developer

Friday, 20 January, 12

Page 6: Django Don't Do This - DjangoToronto - January, 2012

What is this talk about?

Friday, 20 January, 12

Page 7: Django Don't Do This - DjangoToronto - January, 2012

Common Mistakes

Friday, 20 January, 12

Page 8: Django Don't Do This - DjangoToronto - January, 2012

Common mistakes as a result of gaining more experience

with Django

Friday, 20 January, 12

Page 9: Django Don't Do This - DjangoToronto - January, 2012

Common mistakes as a result of gaining more experience

with Django

(in no particular order)

Friday, 20 January, 12

Page 10: Django Don't Do This - DjangoToronto - January, 2012

Friday, 20 January, 12

Page 11: Django Don't Do This - DjangoToronto - January, 2012

Don’t be *this* guy.

Friday, 20 January, 12

Page 12: Django Don't Do This - DjangoToronto - January, 2012

Defining Models without indexes

Friday, 20 January, 12

Page 13: Django Don't Do This - DjangoToronto - January, 2012

DON’T forget your indexes

Friday, 20 January, 12

Page 14: Django Don't Do This - DjangoToronto - January, 2012

Models

Friday, 20 January, 12

Page 15: Django Don't Do This - DjangoToronto - January, 2012

ModelsThey define your data.

Friday, 20 January, 12

Page 16: Django Don't Do This - DjangoToronto - January, 2012

ModelsThey don’t define behavior.

Friday, 20 January, 12

Page 17: Django Don't Do This - DjangoToronto - January, 2012

ModelsThey can’t read your mind.

Friday, 20 January, 12

Page 18: Django Don't Do This - DjangoToronto - January, 2012

Even seasoned Django developers forget about

indexes

Friday, 20 January, 12

Page 19: Django Don't Do This - DjangoToronto - January, 2012

Remember this?

Friday, 20 January, 12

Page 20: Django Don't Do This - DjangoToronto - January, 2012

Remember this?

Friday, 20 January, 12

Page 21: Django Don't Do This - DjangoToronto - January, 2012

DO add indexes to your Models.

Friday, 20 January, 12

Page 22: Django Don't Do This - DjangoToronto - January, 2012

Over-Indexing

Friday, 20 January, 12

Page 23: Django Don't Do This - DjangoToronto - January, 2012

DON’T index everything

Friday, 20 January, 12

Page 24: Django Don't Do This - DjangoToronto - January, 2012

What are indexes?

Friday, 20 January, 12

Page 25: Django Don't Do This - DjangoToronto - January, 2012

What are indexes?They are pointers to your data

Friday, 20 January, 12

Page 26: Django Don't Do This - DjangoToronto - January, 2012

What are indexes?They are pointers to your data

... in memory

Friday, 20 January, 12

Page 27: Django Don't Do This - DjangoToronto - January, 2012

What are indexes?They are pointers to your data

... in memory

... or on disk!!!

Friday, 20 January, 12

Page 28: Django Don't Do This - DjangoToronto - January, 2012

They slow down inserts, updates and deletes.

Friday, 20 January, 12

Page 29: Django Don't Do This - DjangoToronto - January, 2012

As a general rule, you want an index on

anything you will use to limit results

Friday, 20 January, 12

Page 30: Django Don't Do This - DjangoToronto - January, 2012

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

Page 31: Django Don't Do This - DjangoToronto - January, 2012

You need to assess your specific needs.

Friday, 20 January, 12

Page 32: Django Don't Do This - DjangoToronto - January, 2012

DO analyze your QuerySets

to determine where indexes

are needed.Friday, 20 January, 12

Page 33: Django Don't Do This - DjangoToronto - January, 2012

Silly Shortcuts

Friday, 20 January, 12

Page 34: Django Don't Do This - DjangoToronto - January, 2012

DON’T use locals() to

populate your context

Friday, 20 January, 12

Page 35: Django Don't Do This - DjangoToronto - January, 2012

I PITY THE FOOL...WHO HAS TO DEBUG

YOUR TEMPLATE

Friday, 20 January, 12

Page 36: Django Don't Do This - DjangoToronto - January, 2012

It’s not clever.

Friday, 20 January, 12

Page 37: Django Don't Do This - DjangoToronto - January, 2012

It’s just lazy.

Friday, 20 January, 12

Page 38: Django Don't Do This - DjangoToronto - January, 2012

Every time you use locals() to populate your

context, God kills a kitten.Friday, 20 January, 12

Page 39: Django Don't Do This - DjangoToronto - January, 2012

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

Page 40: Django Don't Do This - DjangoToronto - January, 2012

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

Page 41: Django Don't Do This - DjangoToronto - January, 2012

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': <WSGIRequestGET:<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

Page 42: Django Don't Do This - DjangoToronto - January, 2012

'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;31:*.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:*.rpm=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;35:*.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:*.mov=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:*.vob=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:*.flv=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:*.aac=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: \\w\\a\\]${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

Page 43: Django Don't Do This - DjangoToronto - January, 2012

'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: [email protected]>, <User: [email protected]>, <User: [email protected]>, <User: [email protected]>, <User: [email protected]>, <User: [email protected]>, <User: [email protected]>, <User: >, <User: [email protected]>]}

Friday, 20 January, 12

Page 44: Django Don't Do This - DjangoToronto - January, 2012

Weird stuff happens.

Friday, 20 January, 12

Page 45: Django Don't Do This - DjangoToronto - January, 2012

Did you notice? 'context': <Recursion on dict with id=175092300>

Friday, 20 January, 12

Page 46: Django Don't Do This - DjangoToronto - January, 2012

Did you notice? 'context': <Recursion on dict with id=175092300>

context

Friday, 20 January, 12

Page 47: Django Don't Do This - DjangoToronto - January, 2012

Did you notice? 'context': <Recursion on dict with id=175092300>

context [‘context’]

Friday, 20 January, 12

Page 48: Django Don't Do This - DjangoToronto - January, 2012

Did you notice? 'context': <Recursion on dict with id=175092300>

context [‘context’] [‘context’]

Friday, 20 January, 12

Page 49: Django Don't Do This - DjangoToronto - January, 2012

Did you notice? 'context': <Recursion on dict with id=175092300>

context [‘context’] [‘context’] [‘context’]

Friday, 20 January, 12

Page 50: Django Don't Do This - DjangoToronto - January, 2012

Did you notice? 'context': <Recursion on dict with id=175092300>

context [‘context’] [‘context’] [‘context’] ...

Friday, 20 January, 12

Page 51: Django Don't Do This - DjangoToronto - January, 2012

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

Page 52: Django Don't Do This - DjangoToronto - January, 2012

DO define your context explicitly

Friday, 20 January, 12

Page 53: Django Don't Do This - DjangoToronto - January, 2012

Replacing the .all() method on QuerySets

Friday, 20 January, 12

Page 54: Django Don't Do This - DjangoToronto - January, 2012

DON’T replace get_query_set()

with something unexpected.

Friday, 20 January, 12

Page 55: Django Don't Do This - DjangoToronto - January, 2012

The majority of developers and apps expect objects.all() to

return ALL objects.

Friday, 20 January, 12

Page 56: Django Don't Do This - DjangoToronto - January, 2012

That’s why it’s called .all()

Friday, 20 January, 12

Page 57: Django Don't Do This - DjangoToronto - January, 2012

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

Page 58: Django Don't Do This - DjangoToronto - January, 2012

To get the active users:

MyModel.objects.active()

Friday, 20 January, 12

Page 59: Django Don't Do This - DjangoToronto - January, 2012

What about in the admin?

Friday, 20 January, 12

Page 60: Django Don't Do This - DjangoToronto - January, 2012

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

Page 61: Django Don't Do This - DjangoToronto - January, 2012

DO explicitly define your QuerySets

Friday, 20 January, 12

Page 62: Django Don't Do This - DjangoToronto - January, 2012

Creating new ways to do the same things.

Friday, 20 January, 12

Page 63: Django Don't Do This - DjangoToronto - January, 2012

DON’T invent new Django

conventions.

Friday, 20 January, 12

Page 64: Django Don't Do This - DjangoToronto - January, 2012

Even the best Django developers make this mistake

Friday, 20 January, 12

Page 65: Django Don't Do This - DjangoToronto - January, 2012

Even the best Django developers make this mistake

Friday, 20 January, 12

Page 66: Django Don't Do This - DjangoToronto - January, 2012

are you sure that'sa good idea?are you sure that'sa good idea?are you sure that'sa good idea?are you sure that'sa good idea?

Even the best Django developers make this mistake

Friday, 20 January, 12

Page 67: Django Don't Do This - DjangoToronto - January, 2012

i think its a really goodusage patterni think its a really goodusage patterni think its a really goodusage patterni think its a really goodusage pattern

Even the best Django developers make this mistake

Friday, 20 January, 12

Page 68: Django Don't Do This - DjangoToronto - January, 2012

your POST data doesn'tnecessarily exist.your POST data doesn'tnecessarily exist.your POST data doesn'tnecessarily exist.your POST data doesn'tnecessarily exist.

Even the best Django developers make this mistake

Friday, 20 January, 12

Page 69: Django Don't Do This - DjangoToronto - January, 2012

oh... crapoh... crapoh... crapoh... crap

Even the best Django developers make this mistake

Friday, 20 January, 12

Page 70: Django Don't Do This - DjangoToronto - January, 2012

pwned you!pwned you!pwned you!pwned you!

Even the best Django developers make this mistake

Friday, 20 January, 12

Page 71: Django Don't Do This - DjangoToronto - January, 2012

............

Even the best Django developers make this mistake

Friday, 20 January, 12

Page 72: Django Don't Do This - DjangoToronto - January, 2012

FOLLOW THE PATTERN, BITCHES!FOLLOW THE PATTERN, BITCHES!FOLLOW THE PATTERN, BITCHES!FOLLOW THE PATTERN, BITCHES!

Even the best Django developers make this mistake

Friday, 20 January, 12

Page 73: Django Don't Do This - DjangoToronto - January, 2012

DO follow the conventions

outlined by the Django community

Friday, 20 January, 12

Page 74: Django Don't Do This - DjangoToronto - January, 2012

They have more experience than you

do.

Friday, 20 January, 12

Page 75: Django Don't Do This - DjangoToronto - January, 2012

They have built more projects than you have.

Friday, 20 January, 12

Page 76: Django Don't Do This - DjangoToronto - January, 2012

They know better than you do.

Friday, 20 January, 12

Page 77: Django Don't Do This - DjangoToronto - January, 2012

Tell me I’m wrong

Friday, 20 January, 12