Two Scoops of Django Best Practices For Django 1.8 Daniel Roy Greenfeld Audrey Roy Greenfeld TwoScoopsofDjango:BestPracticesforDjango1.8 (cid:315)irdEdition,2015-05-20 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