64
Django Best Practices

Django best practices

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Django best practices

Django Best Practices

Page 2: Django best practices

Disclaimer

● This talk should take approximately 1 month● I don't always take my own advice● I'm not an expert● I'm going to forget something● You have a different opinion than me

Page 3: Django best practices

A note on personal philosophy

● Organization makes chaos manageable○ PEP8○ Code standards○ DRY○ Hierarchical organization lets me understand what I

need to to solve the problem in front of me

Page 4: Django best practices

A note on personal philosophy

● Provide value with as few LOC as possible○ "Everything should be made as simple as possible,

but not simpler"● "Unix Philosophy"

○ Read "The Art of Unix Programming"○ Things should fail noisily○ Don't surprise me

Page 5: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 6: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 7: Django best practices

README

● Your project should have a README○ Seriously○ You want to go on vacation

● Format it in some way that's easy to read○ duh

● What should probably be there○ Installation instructions○ Design decisions○ Contribution information (or put this in a Contributing file)

Page 8: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 9: Django best practices

Requirements

● We use pip, with pretty results● Pin your versions

Page 10: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 11: Django best practices

Continuous Integration

● Run your tests regularly● We use circleci

○ Pretty simple○ Integrates with github○ still working out their own bugs

● Other options○ Buildbot○ Jenkins○ TravisCI○ Codeship.io

Page 12: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 13: Django best practices

Fabric

● Useful for deployment to remote machines○ Supports parallel remote execution

● Nice python replacement for○ Bash scripts○ Makefiles○ Duct Tape

Page 14: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 15: Django best practices

Things that shouldn't be in the REPO

● Generated Files● Data files● .pyc files● Backup files● Cat pictures

○ Ok, maybe cat pictures

Page 16: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 17: Django best practices

virtualenv

● Oh my god use it● Keeps your projects from stepping on each

other● World Peace● Kittens

Page 18: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 19: Django best practices

Documentation

● IMHO lots of docs in the root make a project hard to navigate

● Plaintext format that can generate html docs preferred○ ReStructured Text○ Sphinx

Page 20: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 21: Django best practices

Project Configuration

● Non-sensitive configuration files● Avoid putting these in root, again

hierarchical structure

Page 22: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 23: Django best practices

Newrelic

● Makes my life so much better● Monitoring

○ Exceptions○ Response Time / Profiling○ Database profiling

● Alternatives○ Sentry (FOSS)○ App Dynamics

Page 24: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 25: Django best practices

Root project urls

● If at all possible should only include app's url patterns

from django.conf.urls import patterns, url, include

urlpatterns = patterns(

'project',

url(r'achievements/', include('achievements.urls'))

)

Page 26: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 27: Django best practices

WSGI

● How your webserver actually hooks into your app

● WSGI middlewares can go here○ Haven't ever found a user for them

Page 28: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 29: Django best practices

Settings

● Recently we've started using environment variables with some success

● We've also used approaches where we have a settings directory who's __init__.py file determins appropriate settings for environment

● Try to be organized, honestly, just use ENV

Page 30: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 31: Django best practices

Unpackaged dependencies

● Whenever possible use pip / setuptools● Put django snippets / projects that aren't in

pypi in lib/● If you're going to do something dirty try to be

organized about it

Page 32: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 33: Django best practices

Project specific Code

● As much as possible bundle code into reusable apps

● Things that might have to go here○ Custom test runners○ Project middlewares○ Project template context processors○ Functions that don't make sense elsewhere○ dbrouters

Page 34: Django best practices

Project StructureREADME.mdrequirements.txtcircle.ymlfabfile.py.gitignorevenv/docs/conf/ newrelic.iniproject_name/ __init__.py urls.py wsgi.py settings/ lib/ base/ apps/

Page 35: Django best practices

Django Applications

● Re-usuable apps make Django awesome○ Use relative imports○ Try to not include anything project specific

● Combine / split projects○ Possible with proper organization :)

Page 36: Django best practices

App Directory Structureapp_name/ tests.py models.py urls.py admin.py views.py api.py tasks.py migrations/ management/ __init__.py commands/ command_name.py static/ app_name/ js/ css/ img/ templates/ app_name/

Page 37: Django best practices

Application Tests

● You should have tests○ TDD/BDD if possible○ IMHO your model tests / design give better ROI○ If you find a bug write a test to reproduce, fix○ Seriously testing will save you time○ Really○ Please

Page 38: Django best practices

App Directory Structureapp_name/ tests.py models.py urls.py admin.py views.py api.py tasks.py migrations/ management/ __init__.py commands/ command_name.py static/ app_name/ js/ css/ img/ templates/ app_name/

Page 39: Django best practices

Models

● Models are the lifeblood of your apps○ Start with model design first○ Design your data model well and views will come

naturally● Model Managers are pretty awesome

○ Your views (controllers) should be able to call 1/2 model manager methods in order to get what it needs otherwise code needs to be refactored into a model manager

● Querysets can be subclassed as well○ can make view / task code much much easier○ DRY

Page 40: Django best practices

App Directory Structureapp_name/ tests.py models.py urls.py admin.py views.py api.py tasks.py migrations/ management/ __init__.py commands/ command_name.py static/ app_name/ js/ css/ img/ templates/ app_name/

Page 41: Django best practices

Application Urls

● All views accessible in an app should be bundled into an app level urls file

● Use named url patterns to separate patterns from controllers.

Page 42: Django best practices

App Directory Structureapp_name/ tests.py models.py urls.py admin.py views.py api.py tasks.py migrations/ management/ __init__.py commands/ command_name.py static/ app_name/ js/ css/ img/ templates/ app_name/

Page 43: Django best practices

Django Admin

● Major win● Use django admin for as much as you can● Most aspects are subclassable/extentable● Your business guys don't need shiny UI

Page 44: Django best practices

App Directory Structureapp_name/ tests.py models.py urls.py admin.py views.py api.py tasks.py migrations/ management/ __init__.py commands/ command_name.py static/ app_name/ js/ css/ img/ templates/ app_name/

Page 45: Django best practices

Application Views

● Make the views as simple as possible○ Template views can probably be functions that call

render○ If a view has lots of model calls that code can

probably go into a manager■ Manager are easier to test■ If managers have lots of interdependencies your

data model probably needs to be refactored● Use django shortcuts when possible● IMHO template logic is ok to a point if it

simplifies view code, but don't go overboard

Page 46: Django best practices

App Directory Structureapp_name/ tests.py models.py urls.py admin.py views.py api.py tasks.py migrations/ management/ __init__.py commands/ command_name.py static/ app_name/ js/ css/ img/ templates/ app_name/

Page 47: Django best practices

Tasty Pie

● Don't re-invent the wheel● Tastypie is useful for most (but not all)

RESTful applications● The code is already tested● You don't need as much control over JSON

structure as you think.● This is a separate talk, but be aware of it.

Page 48: Django best practices

App Directory Structureapp_name/ tests.py models.py urls.py admin.py views.py api.py tasks.py migrations/ management/ __init__.py commands/ command_name.py static/ app_name/ js/ css/ img/ templates/ app_name/

Page 49: Django best practices

Background / Async in Django

● There are lots of choices for this● ZMQ

○ Lots of options for routing○ VERY flexible○ VERY fast○ VERY cool○ Django z-tasks looks promising○ BUT

■ Have to write your own workers■ Have to write your own logging / monitoring■ Have to understand a fair amount to make it work

correctly.■ SO...

Page 50: Django best practices

Celery

● Should be your default choice for async● Very simple python API

○ Async tasks○ Tasks in the future○ Cron replacement

● Workers are already written● Integrated with new relic

○ Ops have been much easier for us○ Traceback monitoring major win

Page 51: Django best practices

App Directory Structureapp_name/ tests.py models.py urls.py admin.py views.py api.py tasks.py forms.py migrations/ management/ __init__.py commands/ command_name.py static/ app_name/ js/ css/ img/ templates/ app_name/

Page 52: Django best practices

Django Forms

● Model Forms○ DRY○ Handles validation in a declarative way○ Will make your life better

● Django crispy forms○ More control

Page 53: Django best practices

App Directory Structureapp_name/ tests.py models.py urls.py admin.py views.py api.py tasks.py migrations/ management/ __init__.py commands/ command_name.py static/ app_name/ js/ css/ img/ templates/ app_name/

Page 54: Django best practices

South

● Reproducible migrations○ Schema migrations○ Data migrations○ Test runner○ Probably going to be included in Django 1.6○ Migration dependencies can be defined

Page 55: Django best practices

App Directory Structureapp_name/ tests.py models.py urls.py admin.py views.py api.py tasks.py migrations/ management/ __init__.py commands/ command_name.py static/ app_name/ js/ css/ img/ templates/ app_name/

Page 56: Django best practices

Management Commands

● We used to use these for cron jobs○ Celery beat is nicer now

● Helpful for project wide scripts that require django context

Page 57: Django best practices

App Directory Structureapp_name/ tests.py models.py urls.py admin.py views.py api.py tasks.py migrations/ management/ __init__.py commands/ command_name.py static/ app_name/ js/ css/ img/ templates/ app_name/

Page 58: Django best practices

Static Files

● Namespace your static files○ app_name/static/app_name○ avoids collisions○ common static files can go in the base of the project

Page 59: Django best practices

App Directory Structureapp_name/ tests.py models.py urls.py admin.py views.py api.py tasks.py migrations/ management/ __init__.py commands/ command_name.py static/ app_name/ js/ css/ img/ templates/ app_name/

Page 60: Django best practices

Application templates

● Same as static files, namespace them● Use template inheritance

○ DRY● Use named url patterns in your templates● Don't go overboard with template logic

○ If you must check out template includes○ Huge templates are hard to read

● Lots of view code data munging can be replaced with template filters.

● Django templates are really controllers○ Let templates act like views, handle presentation.

Page 61: Django best practices

Other things you should be aware of

● Middlewares● Class Based Views● Template Context Processors● Custom Template Tags

Page 62: Django best practices

Django Apps that make me happy

● Django Extensions○ Werkzeug

● South○ Probably coming to Django 1.6

Page 63: Django best practices

Tools you should use

● Code Quality○ PEP8○ Pyflakes○ Pychecker○ jshint○ jslint

● Development Environment○ ack-grep○ emacs :)

● Infrastructure○ PGbouncer

Page 64: Django best practices

What did I forget?