Table Of ContentTwo Scoops of Django
Best Practices For Django 1.8
Daniel Roy Greenfeld
Audrey Roy Greenfeld
TwoScoopsofDjango:BestPracticesforDjango1.8
(cid:315)irdEdition,2015-05-25
byDanielRoyGreenfeldandAudreyRoyGreenfeld
Copyright⃝c 2013-2015DanielRoyGreenfeld,AudreyRoyGreenfeld,andTwoScoopsPress.
Allrightsreserved.(cid:315)isbookmaynotbereproducedinanyform,inwholeorinpart,withoutwrittenpermissionfromthe
authors,exceptinthecaseofbriefquotationsembodiedinarticlesorreviews.
LimitofLiabilityandDisclaimerofWarranty:(cid:315)eauthorshaveusedtheirbesteffortsinpreparingthisbook,andthe
informationprovidedherein“asis.”(cid:315)einformationprovidedissoldwithoutwarranty,eitherexpressorimplied.Neitherthe
authorsnorCartwheelWebwillbeheldliableforanydamagestobecausedeitherdirectlyorindirectlybythecontentsof
thisbook.
Trademarks:Ratherthanindicatingeveryoccurrenceofatrademarkednameassuch,thisbookusesthenamesonlyinan
editorialfashionandtothebene(cid:320)tofthetrademarkownerwithnointentionofinfringementofthetrademark.
FirstPrinting,April2015
Formoreinformation,visithttps://twoscoopspress.com.
iii
iv
Dedication
For Malcolm Tredinnick
1971-2013
We miss you.
http://2scoops.co/malcolm-tredinnick-memorial
v
About the Dedication
MalcolmTredinnickwasn’tjustaDjangocoredeveloperandreviewerof“TwoScoopsofDjango:
BestPracticesforDjango1.5.”Tous,hewasmuch,muchmore.
DanielhadworkedwithMalcolmTredinnickinthesummerof2010,butwe(cid:320)rstmethiminperson
atDjangoCon2010.Hewasfunnyandcharming,sharplyopinionatedbutalwaysagentleman;we
instantlybecameclosefriends.
In2012,whenweco-organizedthe(cid:320)rstPyConPhilippines,assoonaswetoldhimaboutit,Mal-
colminstantlydeclaredhewascoming.Hegavetwomemorabletalksandrananimpromptuall-day
Djangotutorial.HealsopushedandencouragedthelocalcommunitytoworkonFilipinolanguage
translationsforDjango,includingTagalog,Tausug,Cebuano,andmore.
Aftertheconference,westartedworkingonabookaboutDjangobestpractices.Wegatheredfriends
andcolleaguestohelpusastechnicalreviewers.MalcolmTredinnickbecamethemostactiveofthem.
Hewasourmentorandforcedustodigdeeperandworkharder.Hedidthiswhileworkingaday
jobastheleaderofacombinedRailsandHaskellteam;Malcolmwasatrueprogramminglanguage
polyglot.
Forourbook,heprovidedsomuchassistanceandguidancewetriedto(cid:320)gureoutawaytoinclude
him in the author credits. When we told him about our dilemma, he laughed it off saying, “For a
book called ‘Two Scoops’, you can’t have three authors.” We suggested he share credit with us on
a second book, and he refused, saying he preferred to just comment on our work. He said that he
wantedpeopletohaveproperreferences,andforhim,simplyreviewingourworkwascontributing
tothegreatergood.Eventuallythetwoofusquietlyplannedtosomehowcoercehimintobeinga
co-authoronafuturework.
Aftermonthsofeffort,wereleasedthe(cid:320)rstiterationonJanuary17th,2013.Malcolmsteppedback
fromTwoScoopsofDjango,butwestayedintouch.SinceMalcolmwasunabletoattendPyCon
US2013weweren’tsurewhenwewouldmeethimagain.
Twomonthslater,onMarch17th,2013,Malcolmpassedaway.
We knew Malcolm for less than three years and yet he made an incredible difference in our lives.
We’veheardmanysimilarstoriesinthecommunityaboutMalcolm;Hewasafriendandmentorto
countlessothersaroundtheworld.Hislastlessontouswentbeyondcodeorwriting,hetaughtus
tonevertakeforgrantedfriends,family,mentors,andteachers.
Contents
Dedication v
AbouttheDedication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vi
Authors’Notes xxvii
AFewWordsFromDanielRoyGreenfeld . . . . . . . . . . . . . . . . . . . . . . . . . xxvii
AFewWordsFromAudreyRoyGreenfeld . . . . . . . . . . . . . . . . . . . . . . . . xxviii
Introduction xxix
AWordAboutOurRecommendations . . . . . . . . . . . . . . . . . . . . . . . . . . xxix
WhyTwoScoopsofDjango? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxx
BeforeYouBegin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxxi
(cid:315)isbookisintendedforDjango1.8andPython2.7.x/3.3.3+ . . . . . . . . . . . . xxxi
EachChapterStandsOnItsOwn . . . . . . . . . . . . . . . . . . . . . . . . . . xxxi
ConventionsUsedin(cid:315)isBook. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxxii
CoreConcepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxxiii
KeepItSimple,Stupid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxxiii
FatModels,UtilityModules,(cid:315)inViews,StupidTemplates . . . . . . . . . . . . xxxiv
StartWithDjangoByDefault . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxxiv
BeFamiliarwithDjango’sDesignPhilosophies . . . . . . . . . . . . . . . . . . . xxxiv
(cid:315)eTwelve-FactorApp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxxv
OurWritingConcepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxxv
ProvidetheBestMaterial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxxv
StandontheShouldersofGiants . . . . . . . . . . . . . . . . . . . . . . . . . . . xxxv
ListentoOurReadersandReviewers . . . . . . . . . . . . . . . . . . . . . . . . xxxvi
PublishErrata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxxvi
1 CodingStyle 1
1.1 (cid:315)eImportanceofMakingYourCodeReadable . . . . . . . . . . . . . . . . . . 1
vii
Contents
1.2 PEP8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.1 (cid:315)e79-CharacterLimit . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 (cid:315)eWordonImports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.4 UseExplicitRelativeImports . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.5 AvoidUsingImport* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.6 DjangoCodingStyle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.6.1 ConsidertheDjangoCodingStyleGuidelines . . . . . . . . . . . . . . . 9
1.6.2 UseUnderscoresinURLPatternNamesRather(cid:315)anDashes. . . . . . . 9
1.6.3 UseUnderscoresinTemplateBlockNamesRather(cid:315)anDashes . . . . . 10
1.7 ChooseJS,HTML,andCSSStyleGuides . . . . . . . . . . . . . . . . . . . . . 10
1.7.1 JavaScriptStyleGuides . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.7.2 HTMLandCSSStyleGuides . . . . . . . . . . . . . . . . . . . . . . . 11
1.8 NeverCodetotheIDE(OrTextEditor) . . . . . . . . . . . . . . . . . . . . . . 11
1.9 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2 (cid:315)eOptimalDjangoEnvironmentSetup 13
2.1 UsetheSameDatabaseEngineEverywhere . . . . . . . . . . . . . . . . . . . . 13
2.1.1 YouCan’tExamineanExactCopyofProductionDataLocally . . . . . . 13
2.1.2 DifferentDatabasesHaveDifferentFieldTypes/Constraints . . . . . . . 14
2.1.3 FixturesAreNotaMagicSolution . . . . . . . . . . . . . . . . . . . . . 15
2.2 UsePipandVirtualenv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.3 InstallDjangoandOtherDependenciesviaPip . . . . . . . . . . . . . . . . . . 17
2.4 UseaVersionControlSystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.5 Optional:IdenticalEnvironments . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.5.1 VagrantandVirtualBox . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.6 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3 HowtoLayOutDjangoProjects 21
3.1 Django1.8’sDefaultProjectLayout. . . . . . . . . . . . . . . . . . . . . . . . . 21
3.2 OurPreferredProjectLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.2.1 TopLevel:RepositoryRoot. . . . . . . . . . . . . . . . . . . . . . . . . 23
3.2.2 SecondLevel:ProjectRoot . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.2.3 (cid:315)irdLevel:Con(cid:320)gurationRoot . . . . . . . . . . . . . . . . . . . . . . 23
3.3 SampleProjectLayout. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.4 WhatAbouttheVirtualenv? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.5 GoingBeyondstartproject . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
viii