121

Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running
Page 2: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

1.1

1.2

1.3

1.4

1.5

1.6

1.7

1.8

1.9

1.10

1.11

1.12

1.13

1.14

1.15

1.16

1.17

1.18

1.19

1.20

1.21

1.22

1.23

1.24

TableofContentsIntroduction

Installation

HowtheInternetworks

Introductiontocommandline

Pythoninstallation

Codeeditor

IntroductiontoPython

WhatisDjango?

Djangoinstallation

YourfirstDjangoproject!

Djangomodels

Djangoadmin

Deploy!

Djangourls

Djangoviews-timetocreate!

IntroductiontoHTML

DjangoORM(Querysets)

Dynamicdataintemplates

Djangotemplates

CSS-makeitpretty

Templateextending

Extendyourapplication

DjangoForms

What'snext?

2

Page 3: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

DjangoGirlsTutorial

ThisworkislicensedundertheCreativeCommonsAttribution-ShareAlike4.0InternationalLicense.Toviewacopyofthislicense,visithttps://creativecommons.org/licenses/by-sa/4.0/

IntroductionHaveyoueverfeltthattheworldismoreandmoreabouttechnologyandyouaresomehowleftbehind?Haveyoueverwonderedhowtocreateawebsitebuthaveneverhadenoughmotivationtostart?Haveyoueverthoughtthatthesoftwareworldistoocomplicatedforyoutoeventrydoingsomethingonyourown?

Well,wehavegoodnewsforyou!Programmingisnotashardasitseemsandwewanttoshowyouhowfunitcanbe.

Thistutorialwillnotmagicallyturnyouintoaprogrammer.Ifyouwanttobegoodatit,youneedmonthsorevenyearsoflearningandpractice.Butwewanttoshowyouthatprogrammingorcreatingwebsitesisnotascomplicatedasitseems.Wewilltrytoexplaindifferentbitsandpiecesaswellaswecan,soyouwillnotfeelintimidatedbytechnology.

Wehopethatwe'llbeabletomakeyoulovetechnologyasmuchaswedo!

Whatwillyoulearnduringthetutorial?Onceyou'vefinishedthetutorial,youwillhaveasimple,workingwebapplication:yourownblog.Wewillshowyouhowtoputitonline,sootherswillseeyourwork!

Itwill(moreorless)looklikethis:

Introduction

3

Page 4: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Ifyouworkwiththetutorialonyourownanddon'thaveacoachwhowillhelpyouincaseofanyproblem,wehavea

chatsystemforyou: .Weaskedourcoachesandpreviousattendeestobetherefromtimetotimeandhelpotherswiththetutorial!Don'tbeafraidtoaskyourquestionthere!

OK,let'sstartatthebeginning…

FollowingthetutorialathomeItisamazingtotakepartinaDjangoGirlsworkshop,butweareawarethatitisnotalwayspossibletoattendone.Thisiswhyweencourageyoutotryfollowingthistutorialathome.Forreadersathomewearecurrentlypreparingvideosthatwillmakeiteasiertofollowthetutorialonyourown.Itisstillaworkinprogress,butmoreandmorethingswillbecoveredsoonattheCodingisforgirlsYouTubechannel.

Ineverychapteralreadycovered,thereisalinkthatpointstothecorrectvideo.

AboutandcontributingThistutorialismaintainedbyDjangoGirls.Ifyoufindanymistakesorwanttoupdatethetutorialpleasefollowthecontributingguidelines.

Wouldyouliketohelpustranslatethetutorialtootherlanguages?

Introduction

4

Page 5: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Currently,translationsarebeingkeptoncrowdin.complatformat:

https://crowdin.com/project/django-girls-tutorial

Ifyourlanguageisnotlistedoncrowdin,pleaseopenanewissueinformingusofthelanguagesowecanaddit.

Introduction

5

Page 6: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Ifyou'redoingthetutorialathomeIfyou'redoingthetutorialathome,notatoneoftheDjangoGirlsevents,youcancompletelyskipthischapternowandgostraighttotheHowtheInternetworks?chapter.

Thisisbecausewecoverthesethingsinthewholetutorialanyway,andthisisjustanadditionalpagethatgathersalloftheinstallationinstructionsinoneplace.TheDjangoGirlseventincludesone"Installationevening"whereweinstalleverythingsowedon'tneedtobotherwithitduringtheworkshop,sothisisusefulforus.

Ifyoufindituseful,youcanfollowthroughthischaptertoo.Butifyouwanttostartlearningthingsbeforeinstallingabunchofstuffonyourcomputer,skipthischapterandwewillexplaintheinstallationparttoyoulateron.

Goodluck!

InstallationIntheworkshopyouwillbebuildingablog,andthereareafewsetuptasksinthetutorialwhichwouldbegoodtoworkthroughbeforehandsothatyouarereadytostartcodingontheday.

Chromebooksetup(ifyou'reusingone)Youcanskiprightoverthissectionifyou'renotusingaChromebook.Ifyouare,yourinstallationexperiencewillbealittledifferent.Youcanignoretherestoftheinstallationinstructions.

Cloud9

Cloud9isatoolthatgivesyouacodeeditorandaccesstoacomputerrunningontheinternetwhereyoucaninstall,write,andrunsoftware.Forthedurationofthetutorial,Cloud9willactasyourlocalmachine.You'llstillberunningcommandsinaterminalinterfacejustlikeyourclassmatesonOSX,Ubuntu,orWindows,butyourterminalwillbeconnectedtoacomputerrunningsomewhereelsethatCloud9setsupforyou.

1. InstallCloud9fromtheChromewebstore2. Gotoc9.io3. Signupforanaccount4. ClickCreateaNewWorkspace5. Nameitdjango-girls6. SelecttheBlank(secondfromtherightonthebottomrowwithorangelogo)

Nowyoushouldseeaninterfacewithasidebar,abigmainwindowwithsometext,andasmallwindowatthebottomthatlookssomethinglike:

Cloud9

yourusername:~/workspace$

Thisbottomareaisyourterminal,whereyouwillgivethecomputerCloud9haspreparedforyouinstructions.Youcanresizethatwindowtomakeitabitbigger.

VirtualEnvironment

Installation

6

Page 7: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Avirtualenvironment(alsocalledavirtualenv)islikeaprivateboxwecanstuffusefulcomputercodeintoforaprojectwe'reworkingon.Weusethemtokeepthevariousbitsofcodewewantforourvariousprojectsseparatesothingsdon'tgetmixedupbetweenprojects.

InyourterminalatthebottomoftheCloud9interface,runthefollowing:

Cloud9

sudoaptinstallpython3.5-venv

Ifthisstilldoesn'twork,askyourcoachforsomehelp.

Next,run:

Cloud9

mkdirdjangogirls

cddjangogirls

python3.5-mvenvmyvenv

sourcemyvenv/bin/activate

pipinstalldjango~=1.9.0

(notethatonthelastlineweuseatildefollowedbyanequalsign:~=).

Github

MakeaGithubaccount.

PythonAnywhere

TheDjangoGirlstutorialincludesasectiononwhatiscalledDeployment,whichistheprocessoftakingthecodethatpowersyournewwebapplicationandmovingittoapubliclyaccessiblecomputer(calledaserver)sootherpeoplecanseeyourwork.

ThispartisalittleoddwhendoingthetutorialonaChromebooksincewe'realreadyusingacomputerthatisontheinternet(asopposedto,say,alaptop).However,it'sstilluseful,aswecanthinkofourCloud9workspaceasaplaceorour"inprogress"workandPythonAnywhereasaplacetoshowoffourstuffasitbecomesmorecomplete.

Thus,signupforanewPythonAnywhereaccountatwww.pythonanywhere.com.

InstallPythonForreadersathome:thischapteriscoveredintheInstallingPython&CodeEditorvideo.

ThissectionisbasedonatutorialbyGeekGirlsCarrots(https://github.com/ggcarrots/django-carrots)

DjangoiswritteninPython.WeneedPythontodoanythinginDjango.Let'sstartbyinstallingit!WewantyoutoinstallPython3.5,soifyouhaveanyearlierversion,youwillneedtoupgradeit.

WindowsYoucandownloadPythonforWindowsfromthewebsitehttps://www.python.org/downloads/release/python-351/.Afterdownloadingthe*.msifile,youshouldrunit(double-clickonit)andfollowtheinstructionsthere.Itisimportanttorememberthepath(thedirectory)whereyouinstalledPython.Itwillbeneededlater!

Onethingtowatchoutfor:onthesecondscreenoftheinstallationwizard,marked"Customize",makesureyouscrolldowntothe"Addpython.exetothePath"optionandselect"Willbeinstalledonlocalharddrive",asshownhere:

Installation

7

Page 8: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Inupcomingsteps,you'llbeusingtheWindowsCommandLine(whichwe'llalsotellyouabout).Fornow,ifyouneedtotypeinsomecommands,gotoStartmenu→AllPrograms→Accessories→CommandPrompt.(OnnewerversionsofWindows,youmighthavetosearchfor"CommandPrompt"sinceit'ssometimeshidden.)

Linux

ItisverylikelythatyoualreadyhavePythoninstalledoutofthebox.Tocheckifyouhaveitinstalled(andwhichversionitis),openaconsoleandtypethefollowingcommand:

command-line

$python3--version

Python3.5.1

Ifyouhaveadifferent'microversion'ofPythoninstalled,e.g.3.5.0,thenyoudon'thavetoupgrade.Ifyoudon'thavePythoninstalled,orifyouwantadifferentversion,youcaninstallitasfollows:

DebianorUbuntu

Typethiscommandintoyourconsole:

command-line

$sudoapt-getinstallpython3.5

Fedora(upto21)

Usethiscommandinyourconsole:

command-line

Installation

8

Page 9: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

$sudoyuminstallpython3

Fedora(22+)Usethiscommandinyourconsole:

command-line

$sudodnfinstallpython3

openSUSE

Usethiscommandinyourconsole:

command-line

$sudozypperinstallpython3

OSXBeforeyouinstallPythononOSX,youshouldensureyourMacsettingsallowinstallingpackagesthataren'tfromtheAppStore.GotoSystemPreferences(it'sintheApplicationsfolder),click"Security&Privacy,"andthenthe"General"tab.Ifyour"Allowappsdownloadedfrom:"issetto"MacAppStore,"changeitto"MacAppStoreandidentifieddevelopers."

Youneedtogotothewebsitehttps://www.python.org/downloads/release/python-351/anddownloadthePythoninstaller:

DownloadtheMacOSX64-bit/32-bitinstallerfile,Doubleclickpython-3.5.1-macosx10.6.pkgtoruntheinstaller.

VerifytheinstallationwassuccessfulbyopeningtheTerminalapplicationandrunningthepython3command:

command-line

$python3--version

Python3.5.1

Ifyouhaveanydoubts,orifsomethingwentwrongandyouhavenoideawhattodonext,pleaseaskyourcoach!Sometimesthingsdon'tgosmoothlyandit'sbettertoaskforhelpfromsomeonewithmoreexperience.

SetupvirtualenvandinstallDjangoPartofthissectionisbasedontutorialsbyGeekGirlsCarrots(https://github.com/ggcarrots/django-carrots).

Partofthissectionisbasedonthedjango-marcadortutoriallicensedundertheCreativeCommonsAttribution-ShareAlike4.0InternationalLicense.Thedjango-marcadortutorialiscopyrightedbyMarkusZapke-Gründemannetal.

Virtualenvironment

Installation

9

Page 10: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

BeforeweinstallDjangowewillgetyoutoinstallanextremelyusefultooltohelpkeepyourcodingenvironmenttidyonyourcomputer.It'spossibletoskipthisstep,butit'shighlyrecommended.Startingwiththebestpossiblesetupwillsaveyoualotoftroubleinthefuture!

So,let'screateavirtualenvironment(alsocalledavirtualenv).VirtualenvwillisolateyourPython/Djangosetuponaper-projectbasis.Thismeansthatanychangesyoumaketoonewebsitewon'taffectanyothersyou'realsodeveloping.Neat,right?

Allyouneedtodoisfindadirectoryinwhichyouwanttocreatethevirtualenv;yourhomedirectory,forexample.OnWindowsitmightlooklikeC:\Users\Name\(whereNameisthenameofyourlogin).

NOTE:OnWindows,makesurethatthisdirectorydoesnotcontainaccentedorspecialcharacters;ifyourusernamecontainsaccentedcharacters,useadifferentdirectory,forexampleC:\djangogirls.

Forthistutorialwewillbeusinganewdirectorydjangogirlsfromyourhomedirectory:

command-line

$mkdirdjangogirls

$cddjangogirls

Wewillmakeavirtualenvcalledmyvenv.Thegeneralcommandwillbeintheformat:

command-line

$python3-mvenvmyvenv

Windows

Tocreateanewvirtualenv,youneedtoopentheconsole(wetoldyouaboutthatafewchaptersago–remember?)andrunC:\Python35\python-mvenvmyvenv.Itwilllooklikethis:

command-line

C:\Users\Name\djangogirls>C:\Python35\python-mvenvmyvenv

whereC:\Python35\pythonisthedirectoryinwhichyoupreviouslyinstalledPythonandmyvenvisthenameofyourvirtualenv.Youcanuseanyothername,butsticktolowercaseandusenospaces,accentsorspecialcharacters.Itisalsogoodideatokeepthenameshort–you'llbereferencingitalot!

LinuxandOSX

CreatingavirtualenvonbothLinuxandOSXisassimpleasrunningpython3-mvenvmyvenv.Itwilllooklikethis:

command-line

$python3-mvenvmyvenv

myvenvisthenameofyourvirtualenv.Youcanuseanyothername,butsticktolowercaseandusenospaces.Itisalsogoodideatokeepthenameshortasyou'llbereferencingitalot!

Installation

10

Page 11: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

NOTE:OnsomeversionsofDebian/Ubuntuyoumayreceivethefollowingerror:

command-line

Thevirtualenvironmentwasnotcreatedsuccessfullybecauseensurepipisnotavailable.OnDebian/Ubuntusys

tems,youneedtoinstallthepython3-venvpackageusingthefollowingcommand.

apt-getinstallpython3-venv

Youmayneedtousesudowiththatcommand.Afterinstallingthepython3-venvpackage,recreateyourvirtual

environment.

Inthiscase,followtheinstructionsaboveandinstallthepython3-venvpackage:

command-line

$sudoapt-getinstallpython3-venv

NOTE:OnsomeversionsofDebian/Ubuntuinitiatingthevirtualenvironmentlikethiscurrentlygivesthefollowingerror:

command-line

Error:Command'['/home/eddie/Slask/tmp/venv/bin/python3','-Im','ensurepip','--upgrade','--default-pip']'

returnednon-zeroexitstatus1

Togetaroundthis,usethevirtualenvcommandinstead.

command-line

$sudoapt-getinstallpython-virtualenv

$virtualenv--python=python3.5myvenv

NOTE:Ifyougetanerrorlike

command-line

E:Unabletolocatepackagepython3-venv

theninsteadrun:

command-line

sudoaptinstallpython3.5-venv

WorkingwithvirtualenvThecommandabovewillcreateadirectorycalledmyvenv(orwhatevernameyouchose)thatcontainsourvirtualenvironment(basicallyabunchofdirectoryandfiles).

WindowsStartyourvirtualenvironmentbyrunning:

command-line

C:\Users\Name\djangogirls>myvenv\Scripts\activate

Installation

11

Page 12: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

NOTE:onWindows10youmightgetanerrorintheWindowsPowerShellsaysexecutionofscriptsisdisabledonthissystem.InthosecasesopenanotherWindowsPowerShellandRunasAdministratortrydoingthisbeforecontinue:

command-line

C:\WINDOWS\system32>Set-ExecutionPolicy-ExecutionPolicyRemoteSigned

ExecutionPolicyChange

Theexecutionpolicyhelpsprotectyoufromscriptsthatyoudonottrust.Changingtheexecutionpolicym

ightexposeyoutothesecurityrisksdescribedintheabout_Execution_Policieshelptopicathttp://go.micros

oft.com/fwlink/?LinkID=135170.Doyouwanttochangetheexecutionpolicy?[Y]Yes[A]YestoAll[N]No[L

]NotoAll[S]Suspend[?]Help(defaultis"N"):A

LinuxandOSX

Startyourvirtualenvironmentbyrunning:

command-line

$sourcemyvenv/bin/activate

Remembertoreplacemyvenvwithyourchosenvirtualenvname!

NOTE:sometimessourcemightnotbeavailable.Inthosecasestrydoingthisinstead:

command-line

$.myvenv/bin/activate

Youwillknowthatyouhavevirtualenvstartedwhenyouseethatthepromptinyourconsoleisprefixedwith(myvenv).

Whenworkingwithinavirtualenvironment,pythonwillautomaticallyrefertothecorrectversionsoyoucanusepythoninsteadofpython3.

OK,wehaveallimportantdependenciesinplace.WecanfinallyinstallDjango!

InstallingDjangoNowthatyouhaveyourvirtualenvstarted,youcaninstallDjango.

Beforewedothat,weshouldmakesurewehavethelatestversionofpip,thesoftwarethatweusetoinstallDjango.Intheconsole,runpipinstall--upgradepip.

Thenrunpipinstalldjango~=1.9.0(notethatweuseatildefollowedbyanequalsign:~=)toinstallDjango.

command-line

(myvenv)~$pipinstalldjango~=1.9.0

Downloading/unpackingdjango==1.9

Installingcollectedpackages:django

Successfullyinstalleddjango

Cleaningup...

onWindows

Installation

12

Page 13: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

IfyougetanerrorwhencallingpiponWindowsplatform,pleasecheckifyourprojectpathnamecontainsspaces,accentsorspecialcharacters(forexample,C:\Users\UserName\djangogirls).Ifitdoes,pleaseconsiderusinganotherplacewithoutspaces,accentsorspecialcharacters(suggestion:C:\djangogirls).Createanewvirtualenvinthenewdirectory,thendeletetheoldoneandtrytheabovecommandagain.(Movingthevirtualenvdirectorywon'tworksincevirtualenvusesabsolutepaths.)

onWindows8andWindows10

YourcommandlinemightfreezeafterwhenyoutrytoinstallDjango.Ifthishappens,insteadoftheabovecommanduse:

command-line

C:\Users\Name\djangogirls>python-mpipinstalldjango~=1.9.0

onLinux

IfyougetanerrorwhencallingpiponUbuntu12.04pleaserunpython-mpipinstall-U--force-reinstallpiptofixthepipinstallationinthevirtualenv.

That'sit!You'renow(finally)readytocreateaDjangoapplication!

InstallacodeeditorTherearealotofdifferenteditorsanditlargelyboilsdowntopersonalpreference.MostPythonprogrammersusecomplexbutextremelypowerfulIDEs(IntegratedDevelopmentEnvironments),suchasPyCharm.Asabeginner,however,that'sprobablylesssuitable;ourrecommendationsareequallypowerful,butalotsimpler.

Oursuggestionsarebelow,butfeelfreetoaskyourcoachwhattheirpreferencesare–it'llbeeasiertogethelpfromthem.

GeditGeditisanopen-source,freeeditor,availableforalloperatingsystems.

Downloadithere

SublimeText2SublimeTextisaverypopulareditorwithafreeevaluationperiod.It'seasytoinstallanduse,andit'savailableforalloperatingsystems.

Downloadithere

AtomAtomisanextremelynewcodeeditorcreatedbyGitHub.It'sfree,open-source,easytoinstallandeasytouse.It'savailableforWindows,OSXandLinux.

Downloadithere

Whyareweinstallingacodeeditor?Youmightbewonderingwhyweareinstallingthisspecialcodeeditorsoftware,ratherthanusingsomethinglikeWordorNotepad.

Installation

13

Page 14: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Thefirstreasonisthatcodeneedstobeplaintext,andtheproblemwithprogramslikeWordandTexteditisthattheydon'tactuallyproduceplaintext,theyproducerichtext(withfontsandformatting),usingcustomformatslikeRTF(RichTextFormat).

Thesecondreasonisthatcodeeditorsarespecialisedforeditingcode,sotheycanprovidehelpfulfeatureslikehighlightingcodewithcolouraccordingtoitsmeaning,orautomaticallyclosingquotesforyou.

We'llseeallthisinactionlater.Soon,you'llcometothinkofyourtrustyoldcodeeditorasoneofyourfavouritetools.:)

InstallGitWindows

YoucandownloadGitfromgit-scm.com.Youcanhit"next"onallstepsexceptforone;inthefifthstepentitled"AdjustingyourPATHenvironment",choose"UseGitandoptionalUnixtoolsfromtheWindowsCommandPrompt"(thebottomoption).Otherthanthat,thedefaultsarefine.CheckoutWindows-style,commitUnix-stylelineendingsisgood.

MacOS

DownloadGitfromgit-scm.comandjustfollowtheinstructions.

Linux

Ifitisn'tinstalledalready,gitshouldbeavailableviayourpackagemanager,sotry:

DebianorUbuntu

command-line

$sudoapt-getinstallgit

Fedora(upto21)

command-line

$sudoyuminstallgit

Fedora(22+)

command-line

$sudodnfinstallgit

openSUSE

command-line

$sudozypperinstallgit

CreateaGitHubaccountGotoGitHub.comandsignupforanew,freeuseraccount.

Installation

14

Page 15: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

CreateaPythonAnywhereaccountNextit'stimetosignupforafree"Beginner"accountonPythonAnywhere.

www.pythonanywhere.com

Whenchoosingyourusernamehere,bearinmindthatyourblog'sURLwilltaketheformyourusername.pythonanywhere.com,sochooseeitheryourownnickname,oranameforwhatyourblogisallabout.

StartreadingCongratulations,youareallsetupandreadytogo!Ifyoustillhavesometimebeforetheworkshop,itwouldbeusefultostartreadingafewofthebeginningchapters:

Howtheinternetworks

Introductiontothecommandline

IntroductiontoPython

WhatisDjango?

Enjoytheworkshop!Whenyoubegintheworkshop,you'llbeabletogostraighttoYourfirstDjangoproject!becauseyoualreadycoveredthematerialintheearlierchapters.

Installation

15

Page 16: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

HowtheInternetworksForreadersathome:thischapteriscoveredintheHowtheInternetWorksvideo.

Thischapterisinspiredbythetalk"HowtheInternetworks"byJessicaMcKellar(http://web.mit.edu/jesstess/www/).

WebetyouusetheInterneteveryday.Butdoyouactuallyknowwhathappenswhenyoutypeanaddresslikehttps://djangogirls.orgintoyourbrowserandpressenter?

Thefirstthingyouneedtounderstandisthatawebsiteisjustabunchoffilessavedonaharddisk.Justlikeyourmovies,music,orpictures.However,thereisonepartthatisuniqueforwebsites:theyincludecomputercodecalledHTML.

Ifyou'renotfamiliarwithprogrammingitcanbehardtograspHTMLatfirst,butyourwebbrowsers(likeChrome,Safari,Firefox,etc.)loveit.Webbrowsersaredesignedtounderstandthiscode,followitsinstructions,andpresentthesefilesthatyourwebsiteismadeof,exactlythewayyouwant.

Aswitheveryfile,weneedtostoreHTMLfilessomewhereonaharddisk.FortheInternet,weusespecial,powerfulcomputerscalledservers.Theydon'thaveascreen,mouseorakeyboard,becausetheirmainpurposeistostoredataandserveit.That'swhythey'recalledservers–becausetheyserveyoudata.

OK,butyouwanttoknowhowtheInternetlooks,right?

Wedrewyouapicture!Itlookslikethis:

Lookslikeamess,right?Infactitisanetworkofconnectedmachines(theabove-mentionedservers).Hundredsofthousandsofmachines!Many,manykilometersofcablesaroundtheworld!YoucanvisitaSubmarineCableMapwebsite(http://submarinecablemap.com)toseehowcomplicatedthenetis.Hereisascreenshotfromthewebsite:

HowtheInternetworks

16

Page 17: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Itisfascinating,isn'tit?Butobviously,itisnotpossibletohaveawirebetweeneverymachineconnectedtotheInternet.So,toreachamachine(forexample,theonewherehttps://djangogirls.orgissaved)weneedtopassarequestthroughmany,manydifferentmachines.

Itlookslikethis:

HowtheInternetworks

17

Page 18: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Imaginethatwhenyoutypehttps://djangogirls.org,yousendaletterthatsays:"DearDjangoGirls,Iwanttoseethedjangogirls.orgwebsite.Sendittome,please!"

Yourlettergoestothepostofficeclosesttoyou.Thenitgoestoanotherthatisabitnearertoyouraddressee,thentoanother,andanotheruntilitisdeliveredatitsdestination.Theonlyuniquethingisthatifyousendmanyletters(datapackets)tothesameplace,theycouldgothroughtotallydifferentpostoffices(routers).Thisdependsonhowtheyaredistributedateachoffice.

HowtheInternetworks

18

Page 19: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Yes,itisassimpleasthat.Yousendmessagesandyouexpectsomeresponse.Ofcourse,insteadofpaperandpenyouusebytesofdata,buttheideaisthesame!

Insteadofaddresseswithastreetname,city,zipcodeandcountryname,weuseIPaddresses.YourcomputerfirstaskstheDNS(DomainNameSystem)totranslatedjangogirls.orgintoanIPaddress.Itworksalittlebitlikeold-fashionedphonebookswhereyoucanlookupthenameofthepersonyouwanttocontactandfindtheirphonenumberandaddress.

Whenyousendaletter,itneedstohavecertainfeaturestobedeliveredcorrectly:anaddress,astamp,etc.Youalsousealanguagethatthereceiverunderstands,right?Thesameappliestothedatapacketsyousendtoseeawebsite.WeuseaprotocolcalledHTTP(HypertextTransferProtocol).

So,basically,whenyouhaveawebsite,youneedtohaveaserver(machine)whereitlives.Whentheserverreceivesanincomingrequest(inaletter),itsendsbackyourwebsite(inanotherletter).

SincethisisaDjangotutorial,youmightaskwhatDjangodoes.Whenyousendaresponse,youdon'talwayswanttosendthesamethingtoeverybody.Itissomuchbetterifyourlettersarepersonalized,especiallyforthepersonthathasjustwrittentoyou,right?Djangohelpsyouwithcreatingthesepersonalized,interestingletters.:)

Enoughtalk–timetocreate!

HowtheInternetworks

19

Page 20: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Introductiontothecommand-lineinterfaceForreadersathome:thischapteriscoveredintheYournewfriend:CommandLinevideo.

It'sexciting,right?!You'llwriteyourfirstlineofcodeinjustafewminutes!:)

Letusintroduceyoutoyourfirstnewfriend:thecommandline!

Thefollowingstepswillshowyouhowtousetheblackwindowallhackersuse.Itmightlookabitscaryatfirstbutreallyit'sjustapromptwaitingforcommandsfromyou.

Pleasenotethatthroughoutthisbookweusetheterms'directory'and'folder'interchangeablybuttheyareoneandthesamething.

Whatisthecommandline?Thewindow,whichisusuallycalledthecommandlineorcommand-lineinterface,isatext-basedapplicationforviewing,handling,andmanipulatingfilesonyourcomputer.It'smuchlikeWindowsExplorerorFinderontheMac,butwithoutthegraphicalinterface.Othernamesforthecommandlineare:cmd,CLI,prompt,consoleorterminal.

Openthecommand-lineinterfaceTostartsomeexperimentsweneedtoopenourcommand-lineinterfacefirst.

Windows

GotoStartmenu→AllPrograms→Accessories→CommandPrompt.

MacOSX

Applications→Utilities→Terminal.

Linux

It'sprobablyunderApplications→Accessories→Terminal,butthatmaydependonyoursystem.Ifit'snotthere,justGoogleit.:)

PromptYounowshouldseeawhiteorblackwindowthatiswaitingforyourcommands.

Ifyou'reonMacorLinux,youprobablysee$,justlikethis:

command-line

$

OnWindows,it'sa>sign,likethis:

command-line

>

Introductiontocommandline

20

Page 21: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Eachcommandwillbeprependedbythissignandonespace,butyoudon'thavetotypeit.Yourcomputerwilldoitforyou.:)

Justasmallnote:inyourcasetheremaybesomethinglikeC:\Users\ola>orOlas-MacBook-Air:~ola$beforethepromptsign,andthisis100%OK.

Thepartuptoandincludingthe$orthe>iscalledthecommandlineprompt,orpromptforshort.Itpromptsyoutoinputsomethingthere.

Inthetutorial,whenwewantyoutotypeinacommand,wewillincludethe$or>,andoccasionallymoretotheleft.Youcanignoretheleftpartandjusttypeinthecommandwhichstartsaftertheprompt.

Yourfirstcommand(YAY!)Let'sstartwithsomethingsimple.Typethiscommand:

command-line

$whoami

or

command-line

>whoami

Andthenhitenter.Thisisourresult:

command-line

$whoami

olasitarska

Asyoucansee,thecomputerhasjustprintedyourusername.Neat,huh?:)

Trytotypeeachcommand;donotcopy-paste.You'llremembermorethisway!

BasicsEachoperatingsystemhasaslightlydifferentsetofcommandsforthecommandline,somakesuretofollowinstructionsforyouroperatingsystem.Let'strythis,shallwe?

CurrentdirectoryIt'dbenicetoknowwherearewenow,right?Let'ssee.Typethiscommandandhitenter:

command-line

$pwd

/Users/olasitarska

Ifyou'reonWindows:

command-line

Introductiontocommandline

21

Page 22: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

>cd

C:\Users\olasitarska

You'llprobablyseesomethingsimilaronyourmachine.Onceyouopenthecommandlineyouusuallystartatyouruser'shomedirectory.

Note:'pwd'standsfor'printworkingdirectory'.

Listfilesanddirectories

Sowhat'sinit?It'dbecooltofindout.Let'ssee:

command-line

$ls

Applications

Desktop

Downloads

Music

...

Windows:

command-line

>dir

DirectoryofC:\Users\olasitarska

05/08/201407:28PM<DIR>Applications

05/08/201407:28PM<DIR>Desktop

05/08/201407:28PM<DIR>Downloads

05/08/201407:28PM<DIR>Music

...

ChangecurrentdirectoryNow,let'sgotoourDesktopdirectory:

command-line

$cdDesktop

Windows:

command-line

>cdDesktop

Checkifit'sreallychanged:

command-line

$pwd

/Users/olasitarska/Desktop

Windows:

command-line

Introductiontocommandline

22

Page 23: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

>cd

C:\Users\olasitarska\Desktop

Hereitis!

PROtip:ifyoutypecdDandthenhittabonyourkeyboard,thecommandlinewillautomaticallyfillintherestofthenamesoyoucannavigatefaster.Ifthereismorethanonefolderstartingwith"D",hitthetabbuttontwicetogetalistofoptions.

Createdirectory

Howaboutcreatingapracticedirectoryonyourdesktop?Youcandoitthisway:

command-line

$mkdirpractice

Windows:

command-line

>mkdirpractice

Thislittlecommandwillcreateafolderwiththenamepracticeonyourdesktop.Youcancheckifit'stherejustbylookingonyourDesktoporbyrunningalsordircommand!Tryit.:)

PROtip:Ifyoudon'twanttotypethesamecommandsoverandover,trypressingtheuparrowanddownarrowonyourkeyboardtocyclethroughrecentlyusedcommands.

Exercise!Asmallchallengeforyou:inyournewlycreatedpracticedirectory,createadirectorycalledtest.(Usethecdandmkdircommands.)

Solution:command-line

$cdpractice

$mkdirtest

$ls

test

Windows:

command-line

>cdpractice

>mkdirtest

>dir

05/08/201407:28PM<DIR>test

Congrats!:)

Introductiontocommandline

23

Page 24: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Cleanup

Wedon'twanttoleaveamess,solet'sremoveeverythingwediduntilthatpoint.

First,weneedtogetbacktoDesktop:

command-line

$cd..

Windows:

command-line

>cd..

Using..withthecdcommandwillchangeyourcurrentdirectorytotheparentdirectory(thatis,thedirectorythatcontainsyourcurrentdirectory).

Checkwhereyouare:

command-line

$pwd

/Users/olasitarska/Desktop

Windows:

command-line

>cd

C:\Users\olasitarska\Desktop

Nowtimetodeletethepracticedirectory:

Attention:Deletingfilesusingdel,rmdirorrmisirrecoverable,meaningthedeletedfileswillbegoneforever!Sobeverycarefulwiththiscommand.

command-line

$rm-rpractice

Windows:

command-line

>rmdir/Spractice

practice,Areyousure<Y/N>?Y

Done!Tobesureit'sactuallydeleted,let'scheckit:

command-line

$ls

Windows:

command-line

Introductiontocommandline

24

Page 25: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

>dir

ExitThat'sitfornow!Youcansafelyclosethecommandlinenow.Let'sdoitthehackerway,alright?:)

command-line

$exit

Windows:

command-line

>exit

Cool,huh?:)

SummaryHereisasummaryofsomeusefulcommands:

Command(Windows)

Command(MacOS/Linux) Description Example

exit exit closethewindow exit

cd cd changedirectory cdtest

dir ls listdirectories/files dir

copy cp copyfile copyc:\test\test.txtc:\windows\test.txt

move mv movefile movec:\test\test.txtc:\windows\test.txt

mkdir mkdir createanewdirectory mkdirtestdirectory

rmdir(ordel) rm deleteafile delc:\test\test.txt

rmdir\S rm-r deleteadirectory rm-rtestdirectory

Thesearejustaveryfewofthecommandsyoucanruninyourcommandline,butyou'renotgoingtouseanythingmorethanthattoday.

Ifyou'recurious,ss64.comcontainsacompletereferenceofcommandsforalloperatingsystems.

Ready?Let'sdiveintoPython!

Introductiontocommandline

25

Page 26: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Let’sstartwithPythonWe'refinallyhere!

Butfirst,letustellyouwhatPythonis.Pythonisaverypopularprogramminglanguagethatcanbeusedforcreatingwebsites,games,scientificsoftware,graphics,andmuch,muchmore.

Pythonoriginatedinthelate1980sanditsmaingoalistobereadablebyhumanbeings(notonlymachines!).Thisiswhyitlooksmuchsimplerthanotherprogramminglanguages.Thismakesiteasytolearn,butdon'tworry–Pythonisalsoreallypowerful!

PythoninstallationIfyou'reusingaChromebook,skipthischapterandmakesureyoufollowtheChromebookSetupinstructions.

NoteIfyoualreadyworkedthroughtheInstallationsteps,there'snoneedtodothisagain–youcanskipstraightaheadtothenextchapter!

Forreadersathome:thischapteriscoveredintheInstallingPython&CodeEditorvideo.

ThissectionisbasedonatutorialbyGeekGirlsCarrots(https://github.com/ggcarrots/django-carrots)

DjangoiswritteninPython.WeneedPythontodoanythinginDjango.Let'sstartbyinstallingit!WewantyoutoinstallPython3.5,soifyouhaveanyearlierversion,youwillneedtoupgradeit.

WindowsYoucandownloadPythonforWindowsfromthewebsitehttps://www.python.org/downloads/release/python-351/.Afterdownloadingthe*.msifile,youshouldrunit(double-clickonit)andfollowtheinstructionsthere.Itisimportanttorememberthepath(thedirectory)whereyouinstalledPython.Itwillbeneededlater!

Onethingtowatchoutfor:onthesecondscreenoftheinstallationwizard,marked"Customize",makesureyouscrolldowntothe"Addpython.exetothePath"optionandselect"Willbeinstalledonlocalharddrive",asshownhere:

Pythoninstallation

26

Page 27: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Inupcomingsteps,you'llbeusingtheWindowsCommandLine(whichwe'llalsotellyouabout).Fornow,ifyouneedtotypeinsomecommands,gotoStartmenu→AllPrograms→Accessories→CommandPrompt.(OnnewerversionsofWindows,youmighthavetosearchfor"CommandPrompt"sinceit'ssometimeshidden.)

Linux

ItisverylikelythatyoualreadyhavePythoninstalledoutofthebox.Tocheckifyouhaveitinstalled(andwhichversionitis),openaconsoleandtypethefollowingcommand:

command-line

$python3--version

Python3.5.1

Ifyouhaveadifferent'microversion'ofPythoninstalled,e.g.3.5.0,thenyoudon'thavetoupgrade.Ifyoudon'thavePythoninstalled,orifyouwantadifferentversion,youcaninstallitasfollows:

DebianorUbuntu

Typethiscommandintoyourconsole:

command-line

$sudoapt-getinstallpython3.5

Fedora(upto21)

Usethiscommandinyourconsole:

command-line

Pythoninstallation

27

Page 28: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

$sudoyuminstallpython3

Fedora(22+)Usethiscommandinyourconsole:

command-line

$sudodnfinstallpython3

openSUSE

Usethiscommandinyourconsole:

command-line

$sudozypperinstallpython3

OSXBeforeyouinstallPythononOSX,youshouldensureyourMacsettingsallowinstallingpackagesthataren'tfromtheAppStore.GotoSystemPreferences(it'sintheApplicationsfolder),click"Security&Privacy,"andthenthe"General"tab.Ifyour"Allowappsdownloadedfrom:"issetto"MacAppStore,"changeitto"MacAppStoreandidentifieddevelopers."

Youneedtogotothewebsitehttps://www.python.org/downloads/release/python-351/anddownloadthePythoninstaller:

DownloadtheMacOSX64-bit/32-bitinstallerfile,Doubleclickpython-3.5.1-macosx10.6.pkgtoruntheinstaller.

VerifytheinstallationwassuccessfulbyopeningtheTerminalapplicationandrunningthepython3command:

command-line

$python3--version

Python3.5.1

Ifyouhaveanydoubts,orifsomethingwentwrongandyouhavenoideawhattodonext,pleaseaskyourcoach!Sometimesthingsdon'tgosmoothlyandit'sbettertoaskforhelpfromsomeonewithmoreexperience.

Pythoninstallation

28

Page 29: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

CodeeditorForreadersathome:thischapteriscoveredintheInstallingPython&CodeEditorvideo.

You'reabouttowriteyourfirstlineofcode,soit'stimetodownloadacodeeditor!

Ifyou'reusingaChromebook,skipthischapterandmakesureyoufollowtheChromebookSetupinstructions.

NoteYoumighthavedonethisearlierintheInstallationchapter–ifso,youcanskiprightaheadtothenextchapter!

Therearealotofdifferenteditorsanditlargelyboilsdowntopersonalpreference.MostPythonprogrammersusecomplexbutextremelypowerfulIDEs(IntegratedDevelopmentEnvironments),suchasPyCharm.Asabeginner,however,that'sprobablylesssuitable;ourrecommendationsareequallypowerful,butalotsimpler.

Oursuggestionsarebelow,butfeelfreetoaskyourcoachwhattheirpreferencesare–it'llbeeasiertogethelpfromthem.

GeditGeditisanopen-source,freeeditor,availableforalloperatingsystems.

Downloadithere

SublimeText2SublimeTextisaverypopulareditorwithafreeevaluationperiod.It'seasytoinstallanduse,andit'savailableforalloperatingsystems.

Downloadithere

AtomAtomisanextremelynewcodeeditorcreatedbyGitHub.It'sfree,open-source,easytoinstallandeasytouse.It'savailableforWindows,OSXandLinux.

Downloadithere

Whyareweinstallingacodeeditor?Youmightbewonderingwhyweareinstallingthisspecialcodeeditorsoftware,ratherthanusingsomethinglikeWordorNotepad.

Thefirstreasonisthatcodeneedstobeplaintext,andtheproblemwithprogramslikeWordandTexteditisthattheydon'tactuallyproduceplaintext,theyproducerichtext(withfontsandformatting),usingcustomformatslikeRTF(RichTextFormat).

Thesecondreasonisthatcodeeditorsarespecialisedforeditingcode,sotheycanprovidehelpfulfeatureslikehighlightingcodewithcolouraccordingtoitsmeaning,orautomaticallyclosingquotesforyou.

We'llseeallthisinactionlater.Soon,you'llcometothinkofyourtrustyoldcodeeditorasoneofyourfavouritetools.:)

Codeeditor

29

Page 30: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Codeeditor

30

Page 31: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

IntroductiontoPythonPartofthischapterisbasedontutorialsbyGeekGirlsCarrots(https://github.com/ggcarrots/django-carrots).

Let'swritesomecode!

PythonpromptForreadersathome:thispartiscoveredinthePythonBasics:Integers,Strings,Lists,VariablesandErrorsvideo.

TostartplayingwithPython,weneedtoopenupacommandlineonyourcomputer.Youshouldalreadyknowhowtodothat–youlearneditintheIntrotoCommandLinechapter.

Onceyou'reready,followtheinstructionsbelow.

WewanttoopenupaPythonconsole,sotypeinpythononWindowsorpython3onMacOS/Linuxandhitenter.

command-line

$python3

Python3.5.1(...)

Type"help","copyright","credits"or"license"formoreinformation.

>>>

YourfirstPythoncommand!AfterrunningthePythoncommand,thepromptchangedto>>>.ForusthismeansthatfornowwemayonlyusecommandsinthePythonlanguage.Youdon'thavetotypein>>>–Pythonwilldothatforyou.

IfyouwanttoexitthePythonconsoleatanypoint,justtypeexit()orusetheshortcutCtrl+ZforWindowsandCtrl+DforMac/Linux.Thenyouwon'tsee>>>anylonger.

Fornow,wedon'twanttoexitthePythonconsole.Wewanttolearnmoreaboutit.Let'sstartwithsomethingreallysimple.Forexample,trytypingsomemath,like2+3andhitenter.

command-line

>>>2+3

5

Nice!Seehowtheanswerpoppedout?Pythonknowsmath!Youcouldtryothercommandslike:

4*5

5-1

40/2

Havefunwiththisforalittlewhileandthengetbackhere.:)

Asyoucansee,Pythonisagreatcalculator.Ifyou'rewonderingwhatelseyoucando…

StringsHowaboutyourname?Typeyourfirstnameinquoteslikethis:

command-line

IntroductiontoPython

31

Page 32: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

>>>"Ola"

'Ola'

You'venowcreatedyourfirststring!It'sasequenceofcharactersthatcanbeprocessedbyacomputer.Thestringmustalwaysbeginandendwiththesamecharacter.Thismaybesingle(')ordouble(")quotes(thereisnodifference!)ThequotestellPythonthatwhat'sinsideofthemisastring.

Stringscanbestrungtogether.Trythis:

command-line

>>>"Hithere"+"Ola"

'HithereOla'

Youcanalsomultiplystringswithanumber:

command-line

>>>"Ola"*3

'OlaOlaOla'

Ifyouneedtoputanapostropheinsideyourstring,youhavetwowaystodoit.

Usingdoublequotes:

command-line

>>>"Runnin'downthehill"

"Runnin'downthehill"

orescapingtheapostrophewithabackslash(\):

command-line

>>>'Runnin\'downthehill'

"Runnin'downthehill"

Nice,huh?Toseeyournameinuppercaseletters,simplytype:

command-line

>>>"Ola".upper()

'OLA'

Youjustusedtheuppermethodonyourstring!Amethod(likeupper())isasequenceofinstructionsthatPythonhastoperformonagivenobject("Ola")onceyoucallit.

Ifyouwanttoknowthenumberofletterscontainedinyourname,thereisafunctionforthattoo!

command-line

>>>len("Ola")

3

Wonderwhysometimesyoucallfunctionswitha.attheendofastring(like"Ola".upper())andsometimesyoufirstcallafunctionandplacethestringinparentheses?Well,insomecases,functionsbelongtoobjects,likeupper(),whichcanonlybeperformedonstrings.Inthiscase,wecallthefunctionamethod.Othertimes,functionsdon'tbelongtoanything

IntroductiontoPython

32

Page 33: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

specificandcanbeusedondifferenttypesofobjects,justlikelen().That'swhywe'regiving"Ola"asaparametertothelenfunction.

Summary

OK,enoughofstrings.Sofaryou'velearnedabout:

theprompt–typingcommands(code)intothePythonpromptresultsinanswersinPythonnumbersandstrings–inPythonnumbersareusedformathandstringsfortextobjectsoperators–like+and\*,combinevaluestoproduceanewonefunctions–likeupper()andlen(),performactionsonobjects.

Thesearethebasicsofeveryprogramminglanguageyoulearn.Readyforsomethingharder?Webetyouare!

ErrorsLet'strysomethingnew.Canwegetthelengthofanumberthesamewaywecouldfindoutthelengthofourname?Typeinlen(304023)andhitenter:

command-line

>>>len(304023)

Traceback(mostrecentcalllast):

File"<stdin>",line1,in<module>

TypeError:objectoftype'int'hasnolen()

Wegotourfirsterror!Itsaysthatobjectsoftype"int"(integers,wholenumbers)havenolength.Sowhatcanwedonow?Maybewecanwriteournumberasastring?Stringshavealength,right?

command-line

>>>len(str(304023))

6

Itworked!Weusedthestrfunctioninsideofthelenfunction.str()convertseverythingtostrings.

ThestrfunctionconvertsthingsintostringsTheintfunctionconvertsthingsintointegers

Important:wecanconvertnumbersintotext,butwecan'tnecessarilyconverttextintonumbers–whatwouldint('hello')beanyway?

VariablesAnimportantconceptinprogrammingisvariables.Avariableisnothingmorethananameforsomethingsoyoucanuseitlater.Programmersusethesevariablestostoredata,maketheircodemorereadableandsotheydon'thavetokeeprememberingwhatthingsare.

Let'ssaywewanttocreateanewvariablecalledname:

command-line

>>>name="Ola"

Yousee?It'seasy!It'ssimply:nameequalsOla.

IntroductiontoPython

33

Page 34: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Asyou'venoticed,yourprogramdidn'treturnanythinglikeitdidbefore.Sohowdoweknowthatthevariableactuallyexists?Simplyenternameandhitenter:

command-line

>>>name

'Ola'

Yippee!Yourfirstvariable!:)Youcanalwayschangewhatitrefersto:

command-line

>>>name="Sonja"

>>>name

'Sonja'

Youcanuseitinfunctionstoo:

command-line

>>>len(name)

5

Awesome,right?Ofcourse,variablescanbeanything–numberstoo!Trythis:

command-line

>>>a=4

>>>b=6

>>>a*b

24

Butwhatifweusedthewrongname?Canyouguesswhatwouldhappen?Let'stry!

command-line

>>>city="Tokyo"

>>>ctiy

Traceback(mostrecentcalllast):

File"<stdin>",line1,in<module>

NameError:name'ctiy'isnotdefined

Anerror!Asyoucansee,PythonhasdifferenttypesoferrorsandthisoneiscalledaNameError.Pythonwillgiveyouthiserrorifyoutrytouseavariablethathasn'tbeendefinedyet.Ifyouencounterthiserrorlater,checkyourcodetoseeifyou'vemistypedanynames.

Playwiththisforawhileandseewhatyoucando!

TheprintfunctionTrythis:

command-line

>>>name='Maria'

>>>name

'Maria'

>>>print(name)

Maria

IntroductiontoPython

34

Page 35: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Whenyoujusttypename,thePythoninterpreterrespondswiththestringrepresentationofthevariable'name',whichisthelettersM-a-r-i-a,surroundedbysinglequotes,''.Whenyousayprint(name),Pythonwill"print"thecontentsofthevariabletothescreen,withoutthequotes,whichisneater.

Aswe'llseelater,print()isalsousefulwhenwewanttoprintthingsfrominsidefunctions,orwhenwewanttoprintthingsonmultiplelines.

ListsBesidestringsandintegers,Pythonhasallsortsofdifferenttypesofobjects.Nowwe'regoingtointroduceonecalledlist.Listsareexactlywhatyouthinktheyare:objectswhicharelistsofotherobjects.:)

Goaheadandcreatealist:

command-line

>>>[]

[]

Yes,thislistisempty.Notveryuseful,right?Let'screatealistoflotterynumbers.Wedon'twanttorepeatourselvesallthetime,sowewillputitinavariable,too:

command-line

>>>lottery=[3,42,12,19,30,59]

Allright,wehavealist!Whatcanwedowithit?Let'sseehowmanylotterynumbersthereareinalist.Doyouhaveanyideawhichfunctionyoushoulduseforthat?Youknowthisalready!

command-line

>>>len(lottery)

6

Yes!len()cangiveyouanumberofobjectsinalist.Handy,right?Maybewewillsortitnow:

command-line

>>>lottery.sort()

Thisdoesn'treturnanything,itjustchangedtheorderinwhichthenumbersappearinthelist.Let'sprintitoutagainandseewhathappened:

command-line

>>>print(lottery)

[3,12,19,30,42,59]

Asyoucansee,thenumbersinyourlistarenowsortedfromthelowesttohighestvalue.Congrats!

Maybewewanttoreversethatorder?Let'sdothat!

command-line

>>>lottery.reverse()

>>>print(lottery)

[59,42,30,19,12,3]

IntroductiontoPython

35

Page 36: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Easy,right?Ifyouwanttoaddsomethingtoyourlist,youcandothisbytypingthiscommand:

command-line

>>>lottery.append(199)

>>>print(lottery)

[59,42,30,19,12,3,199]

Ifyouwanttoshowonlythefirstnumber,youcandothisbyusingindexes.Anindexisthenumberthatsayswhereinalistanitemoccurs.Programmersprefertostartcountingat0,sothefirstobjectinyourlistisatindex0,thenextoneisat1,andsoon.Trythis:

command-line

>>>print(lottery[0])

59

>>>print(lottery[1])

42

Asyoucansee,youcanaccessdifferentobjectsinyourlistbyusingthelist'snameandtheobject'sindexinsideofsquarebrackets.

Todeletesomethingfromyourlistyouwillneedtouseindexesaswelearntaboveandthepop()method.Let'stryanexampleandreinforcewhatwelearntpreviously;wewillbedeletingthefirstnumberofourlist.

command-line

>>>print(lottery)

[59,42,30,19,12,3,199]

>>>print(lottery[0])

59

>>>lottery.pop(0)

>>>print(lottery)

[42,30,19,12,3,199]

Thatworkedlikeacharm!

Forextrafun,trysomeotherindexes:6,7,1000,-1,-6or-1000.Seeifyoucanpredicttheresultbeforetryingthecommand.Dotheresultsmakesense?

YoucanfindalistofallavailablelistmethodsinthischapterofthePythondocumentation:https://docs.python.org/3/tutorial/datastructures.html

DictionariesForreadersathome:thispartiscoveredinthePythonBasics:Dictionariesvideo.

Adictionaryissimilartoalist,butyouaccessvaluesbylookingupakeyinsteadofanumericindex.Akeycanbeanystringornumber.Thesyntaxtodefineanemptydictionaryis:

command-line

>>>{}

{}

Thisshowsthatyoujustcreatedanemptydictionary.Hurray!

Now,trywritingthefollowingcommand(trysubstitutingyourowninformation,too):

command-line

IntroductiontoPython

36

Page 37: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

>>>participant={'name':'Ola','country':'Poland','favorite_numbers':[7,42,92]}

Withthiscommand,youjustcreatedavariablenamedparticipantwiththreekey–valuepairs:

Thekeynamepointstothevalue'Ola'(astringobject),countrypointsto'Poland'(anotherstring),andfavorite_numberspointsto[7,42,92](alistwiththreenumbersinit).

Youcancheckthecontentofindividualkeyswiththissyntax:

command-line

>>>print(participant['name'])

Ola

See,it'ssimilartoalist.Butyoudon'tneedtoremembertheindex–justthename.

WhathappensifweaskPythonthevalueofakeythatdoesn'texist?Canyouguess?Let'stryitandsee!

command-line

>>>participant['age']

Traceback(mostrecentcalllast):

File"<stdin>",line1,in<module>

KeyError:'age'

Look,anothererror!ThisoneisaKeyError.Pythonishelpfulandtellsyouthatthekey'age'doesn'texistinthisdictionary.

Whenshouldyouuseadictionaryoralist?Well,that'sagoodpointtoponder.Justhaveasolutioninmindbeforelookingattheanswerinthenextline.

Doyoujustneedanorderedsequenceofitems?Goforalist.Doyouneedtoassociatevalueswithkeys,soyoucanlookthemupefficiently(bykey)lateron?Useadictionary.

Dictionaries,likelists,aremutable,meaningthattheycanbechangedaftertheyarecreated.Youcanaddnewkey–valuepairstoadictionaryafteritiscreated,likethis:

command-line

>>>participant['favorite_language']='Python'

Likelists,usingthelen()methodonthedictionariesreturnsthenumberofkey–valuepairsinthedictionary.Goaheadandtypeinthiscommand:

command-line

>>>len(participant)

4

Ihopeitmakessenseuptonow.:)Readyforsomemorefunwithdictionaries?Readonforsomeamazingthings.

Youcanusethepop()methodtodeleteaniteminthedictionary.Say,ifyouwanttodeletetheentrycorrespondingtothekey'favorite_numbers',justtypeinthefollowingcommand:

command-line

>>>participant.pop('favorite_numbers')

>>>participant

{'country':'Poland','favorite_language':'Python','name':'Ola'}

IntroductiontoPython

37

Page 38: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Asyoucanseefromtheoutput,thekey–valuepaircorrespondingtothe'favorite_numbers'keyhasbeendeleted.

Aswellasthis,youcanalsochangeavalueassociatedwithanalready-createdkeyinthedictionary.Typethis:

command-line

>>>participant['country']='Germany'

>>>participant

{'country':'Germany','favorite_language':'Python','name':'Ola'}

Asyoucansee,thevalueofthekey'country'hasbeenalteredfrom'Poland'to'Germany'.:)Exciting?Hurrah!Youjustlearntanotheramazingthing.

Summary

Awesome!Youknowalotaboutprogrammingnow.Inthislastpartyoulearnedabout:

errors–younowknowhowtoreadandunderstanderrorsthatshowupifPythondoesn'tunderstandacommandyou'vegivenitvariables–namesforobjectsthatallowyoutocodemoreeasilyandtomakeyourcodemorereadablelists–listsofobjectsstoredinaparticularorderdictionaries–objectsstoredaskey–valuepairs

Excitedforthenextpart?:)

ComparethingsForreadersathome:thispartiscoveredinthePythonBasics:Comparisonsvideo.

Abigpartofprogramminginvolvescomparingthings.What'stheeasiestthingtocompare?Numbers,ofcourse.Let'sseehowthatworks:

command-line

>>>5>2

True

>>>3<1

False

>>>5>2*2

True

>>>1==1

True

>>>5!=2

True

WegavePythonsomenumberstocompare.Asyoucansee,notonlycanPythoncomparenumbers,butitcanalsocomparemethodresults.Nice,huh?

Doyouwonderwhyweputtwoequalsigns==nexttoeachothertocompareifnumbersareequal?Weuseasingle=forassigningvaluestovariables.Youalways,alwaysneedtoputtwoofthem–==–ifyouwanttocheckifthingsareequaltoeachother.Wecanalsostatethatthingsareunequaltoeachother.Forthat,weusethesymbol!=,asshownintheexampleabove.

GivePythontwomoretasks:

command-line

IntroductiontoPython

38

Page 39: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

>>>6>=12/2

True

>>>3<=2

False

>and<areeasy,butwhatdo>=and<=mean?Readthemlikethis:

x>ymeans:xisgreaterthanyx<ymeans:xislessthanyx<=ymeans:xislessthanorequaltoyx>=ymeans:xisgreaterthanorequaltoy

Awesome!Wannadoonemore?Trythis:

command-line

>>>6>2and2<3

True

>>>3>2and2<1

False

>>>3>2or2<1

True

YoucangivePythonasmanynumberstocompareasyouwant,anditwillgiveyouananswer!Prettysmart,right?

and–ifyouusetheandoperator,bothcomparisonshavetobeTrueinorderforthewholecommandtobeTrueor–ifyouusetheoroperator,onlyoneofthecomparisonshastobeTrueinorderforthewholecommandtobeTrue

Haveyouheardoftheexpression"comparingapplestooranges"?Let'strythePythonequivalent:

command-line

>>>1>'django'

Traceback(mostrecentcalllast):

File"<stdin>",line1,in<module>

TypeError:unorderabletypes:int()>str()

Hereyouseethatjustlikeintheexpression,Pythonisnotabletocompareanumber(int)andastring(str).Instead,itshowsaTypeErrorandtellsusthetwotypescan'tbecomparedtogether.

BooleanIncidentally,youjustlearnedaboutanewtypeofobjectinPython.It'scalledBoolean,anditisprobablytheeasiesttypethereis.

ThereareonlytwoBooleanobjects:

TrueFalse

ButforPythontounderstandthis,youneedtoalwayswriteitas'True'(firstletteruppercased,withtherestoftheletterlowercased).true,TRUE,andtRUEwon'twork–onlyTrueiscorrect.(Thesameappliesto'False'aswell,ofcourse.)

Booleanscanbevariables,too!Seehere:

command-line

IntroductiontoPython

39

Page 40: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

>>>a=True

>>>a

True

Youcanalsodoitthisway:

command-line

>>>a=2>5

>>>a

False

PracticeandhavefunwithBooleansbytryingtorunthefollowingcommands:

TrueandTrue

FalseandTrue

Trueor1==1

1!=2

Congrats!Booleansareoneofthecoolestfeaturesinprogramming,andyoujustlearnedhowtousethem!

Saveit!Forreadersathome:thispartiscoveredinthePythonBasics:Savingfilesand"If"statementvideo.

Sofarwe'vebeenwritingallourpythoncodeintheinterpreter,whichlimitsustoenteringonelineofcodeatatime.Normalprogramsaresavedinfilesandexecutedbyourprogramminglanguageinterpreterorcompiler.Sofarwe'vebeenrunningourprogramsonelineatatimeinthePythoninterpreter.We'regoingtoneedmorethanonelineofcodeforthenextfewtasks,sowe'llquicklyneedto:

ExitthePythoninterpreterOpenupourcodeeditorofchoiceSavesomecodeintoanewpythonfileRunit!

ToexitfromthePythoninterpreterthatwe'vebeenusing,simplytypetheexit()function

command-line

>>>exit()

$

Thiswillputyoubackintothecommandprompt.

Earlier,wepickedoutacodeeditorfromthecodeeditorsection.We'llneedtoopentheeditornowandwritesomecodeintoanewfile:

editor

print('Hello,Djangogirls!')

Obviously,you'reaprettyseasonedPythondevelopernow,sofeelfreetowritesomecodethatyou'velearnedtoday.

Nowweneedtosavethefileandgiveitadescriptivename.Let'scallthefilepython_intro.pyandsaveittoyourdesktop.Wecannamethefileanythingwewant,buttheimportantparthereistomakesurethefileendsin.py.The.pyextensiontellsouroperatingsystemthatthisisaPythonexecutablefileandPythoncanrunit.

IntroductiontoPython

40

Page 41: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Youshouldnoticeoneofthecoolestthingaboutcodeeditors:colours!InthePythonconsole,everythingwasthesamecolour;nowyoushouldseethattheprintfunctionisadifferentcolourfromthestring.Thisiscalled"syntaxhighlighting",andit'sareallyusefulfeaturewhencoding.Thecolourofthingswillgiveyouhints,suchasunclosedstringsoratypoinakeywordname(likethedefinafunction,whichwe'llseebelow).Thisisoneofthereasonsweuseacodeeditor.:)

Withthefilesaved,it'stimetorunit!Usingtheskillsyou'velearnedinthecommandlinesection,usetheterminaltochangedirectoriestothedesktop.(Note:Replace<your_name>includingthe<and>withyourusername.)

OnaMac,thecommandwilllooksomethinglikethis:

command-line

$cd/Users/<your_name>/Desktop

OnLinux,itwillbelikethis(theword"Desktop"mightbetranslatedtoyourlocallanguage):

command-line

$cd/home/<your_name>/Desktop

AndonWindows,itwillbelikethis:

command-line

>cdC:\Users\<your_name>\Desktop

Ifyougetstuck,justaskforhelp.

NowusePythontoexecutethecodeinthefilelikethis:

command-line

$python3python_intro.py

Hello,Djangogirls!

Note:onWindows'python3'isnotrecognizedasacommand.Instead,use'python'toexecutethefile:

command-line

>pythonpython_intro.py

Alright!YoujustranyourfirstPythonprogramthatwassavedtoafile.Feelawesome?

Youcannowmoveontoanessentialtoolinprogramming:

If…elif…elseLotsofthingsincodeshouldbeexecutedonlywhengivenconditionsaremet.That'swhyPythonhassomethingcalledifstatements.

Replacethecodeinyourpython_intro.pyfilewiththis:

python_intro.py

if3>2:

IntroductiontoPython

41

Page 42: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Ifweweretosaveandrunthis,we'dseeanerrorlikethis:

command-line

$python3python_intro.py

File"python_intro.py",line2

^

SyntaxError:unexpectedEOFwhileparsing

Pythonexpectsustogivefurtherinstructionstoitwhichareexecutedifthecondition3>2turnsouttobetrue(orTrueforthatmatter).Let’strytomakePythonprint“Itworks!”.Changeyourcodeinyourpython_intro.pyfiletothis:

python_intro.py

if3>2:

print('Itworks!')

Noticehowwe'veindentedthenextlineofcodeby4spaces?WeneedtodothissoPythonknowswhatcodetoruniftheresultistrue.Youcandoonespace,butnearlyallPythonprogrammersdo4tomakethingslookneat.Asingletabwillalsocountas4spaces.

Saveitandgiveitanotherrun:

command-line

$python3python_intro.py

Itworks!

Note:RememberthatonWindows,'python3'isnotrecognizedasacommand.Fromnowon,replace'python3'with'python'toexecutethefile.

Whatifaconditionisn'tTrue?Inpreviousexamples,codewasexecutedonlywhentheconditionswereTrue.ButPythonalsohaselifandelsestatements:

python_intro.py

if5>2:

print('5isindeedgreaterthan2')

else:

print('5isnotgreaterthan2')

Whenthisisrunitwillprintout:

command-line

$python3python_intro.py

5isindeedgreaterthan2

If2wereagreaternumberthan5,thenthesecondcommandwouldbeexecuted.Easy,right?Let'sseehowelifworks:

python_intro.py

IntroductiontoPython

42

Page 43: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

name='Sonja'

ifname=='Ola':

print('HeyOla!')

elifname=='Sonja':

print('HeySonja!')

else:

print('Heyanonymous!')

andexecuted:

command-line

$python3python_intro.py

HeySonja!

Seewhathappenedthere?elifletsyouaddextraconditionsthatrunifthepreviousconditionsfail.

Youcanaddasmanyelifstatementsasyoulikeafteryourinitialifstatement.Forexample:

python_intro.py

volume=57

ifvolume<20:

print("It'skindaquiet.")

elif20<=volume<40:

print("It'sniceforbackgroundmusic")

elif40<=volume<60:

print("Perfect,Icanhearallthedetails")

elif60<=volume<80:

print("Niceforparties")

elif80<=volume<100:

print("Abitloud!")

else:

print("Myearsarehurting!:(")

Pythonrunsthrougheachtestinsequenceandprints:

command-line

$python3python_intro.py

Perfect,Icanhearallthedetails

CommentsCommentsarelinesbeginningwith#.Youcanwritewhateveryouwantafterthe#andPythonwillignoreit.Commentscanmakeyourcodeeasierforotherpeopletounderstand.

Let'sseehowthatlooks:

python_intro.py

#Changethevolumeifit'stooloudortooquiet

ifvolume<20orvolume>80:

volume=50

print("That'sbetter!")

Youdon'tneedtowriteacommentforeverylineofcode,buttheyareusefulforexplainingwhyyourcodeisdoingsomething,orprovidingasummarywhenit'sdoingsomethingcomplex.

Summary

IntroductiontoPython

43

Page 44: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Inthelastfewexercisesyoulearnedabout:

comparingthings–inPythonyoucancomparethingsbyusing>,>=,==,<=,<andtheand,oroperatorsBoolean–atypeofobjectthatcanonlyhaveoneoftwovalues:TrueorFalseSavingfiles–storingcodeinfilessoyoucanexecutelargerprograms.if…elif…else–statementsthatallowyoutoexecutecodeonlywhencertainconditionsaremet.comments-linesthatPythonwon'trunwhichletyoudocumentyourcode

Timeforthelastpartofthischapter!

Yourownfunctions!Forreadersathome:thispartiscoveredinthePythonBasics:Functionsvideo.

Rememberfunctionslikelen()thatyoucanexecuteinPython?Well,goodnews–youwilllearnhowtowriteyourownfunctionsnow!

AfunctionisasequenceofinstructionsthatPythonshouldexecute.EachfunctioninPythonstartswiththekeyworddef,isgivenaname,andcanhavesomeparameters.Let'sstartwithaneasyone.Replacethecodeinpython_intro.pywiththefollowing:

python_intro.py

defhi():

print('Hithere!')

print('Howareyou?')

hi()

Okay,ourfirstfunctionisready!

Youmaywonderwhywe'vewrittenthenameofthefunctionatthebottomofthefile.ThisisbecausePythonreadsthefileandexecutesitfromtoptobottom.Soinordertouseourfunction,wehavetore-writeitatthebottom.

Let'srunthisnowandseewhathappens:

command-line

$python3python_intro.py

Hithere!

Howareyou?

Thatwaseasy!Let'sbuildourfirstfunctionwithparameters.Wewillusethepreviousexample–afunctionthatsays'hi'tothepersonrunningit–withaname:

python_intro.py

defhi(name):

Asyoucansee,wenowgaveourfunctionaparameterthatwecalledname:

python_intro.py

IntroductiontoPython

44

Page 45: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

defhi(name):

ifname=='Ola':

print('HiOla!')

elifname=='Sonja':

print('HiSonja!')

else:

print('Hianonymous!')

hi()

Remember:Theprintfunctionisindentedfourspaceswithintheifstatement.Thisisbecausethefunctionrunswhentheconditionismet.Let'sseehowitworksnow:

command-line

$python3python_intro.py

Traceback(mostrecentcalllast):

File"python_intro.py",line10,in<module>

hi()

TypeError:hi()missing1requiredpositionalargument:'name'

Oops,anerror.Luckily,Pythongivesusaprettyusefulerrormessage.Ittellsusthatthefunctionhi()(theonewedefined)hasonerequiredargument(calledname)andthatweforgottopassitwhencallingthefunction.Let'sfixitatthebottomofthefile:

python_intro.py

hi("Ola")

Andrunitagain:

command-line

$python3python_intro.py

HiOla!

Andifwechangethename?

python_intro.py

hi("Sonja")

Andrunit:

command-line

$python3python_intro.py

HiSonja!

Now,whatdoyouthinkwillhappenifyouwriteanothernameinthere?(NotOlaorSonja.)Giveitatryandseeifyou'reright.Itshouldprintoutthis:

command-line

Hianonymous!

Thisisawesome,right?Thiswayyoudon'thavetorepeatyourselfeverytimeyouwanttochangethenameofthepersonthefunctionissupposedtogreet.Andthat'sexactlywhyweneedfunctions–youneverwanttorepeatyourcode!

IntroductiontoPython

45

Page 46: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Let'sdosomethingsmarter–therearemorenamesthantwo,andwritingaconditionforeachwouldbehard,right?

python_intro.py

defhi(name):

print('Hi'+name+'!')

hi("Rachel")

Let'scallthecodenow:

command-line

$python3python_intro.py

HiRachel!

Congratulations!Youjustlearnedhowtowritefunctions!:)

LoopsForreadersathome:thispartiscoveredinthePythonBasics:ForLoopvideo.

Thisisthelastpartalready.Thatwasquick,right?:)

Programmersdon'tliketorepeatthemselves.Programmingisallaboutautomatingthings,sowedon'twanttogreeteverypersonbytheirnamemanually,right?That'swhereloopscomeinhandy.

Stillrememberlists?Let'sdoalistofgirls:

python_intro.py

girls=['Rachel','Monica','Phoebe','Ola','You']

Wewanttogreetallofthembytheirname.Wehavethehifunctiontodothat,solet'suseitinaloop:

python_intro.py

fornameingirls:

Theforstatementbehavessimilarlytotheifstatement;codebelowbothoftheseneedtobeindentedfourspaces.

Hereisthefullcodethatwillbeinthefile:

python_intro.py

defhi(name):

print('Hi'+name+'!')

girls=['Rachel','Monica','Phoebe','Ola','You']

fornameingirls:

hi(name)

print('Nextgirl')

Andwhenwerunit:

command-line

IntroductiontoPython

46

Page 47: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

$python3python_intro.py

HiRachel!

Nextgirl

HiMonica!

Nextgirl

HiPhoebe!

Nextgirl

HiOla!

Nextgirl

HiYou!

Nextgirl

Asyoucansee,everythingyouputinsideaforstatementwithanindentwillberepeatedforeveryelementofthelistgirls.

Youcanalsouseforonnumbersusingtherangefunction:

python_intro.py

foriinrange(1,6):

print(i)

Whichwouldprint:

command-line

1

2

3

4

5

rangeisafunctionthatcreatesalistofnumbersfollowingoneaftertheother(thesenumbersareprovidedbyyouasparameters).

NotethatthesecondofthesetwonumbersisnotincludedinthelistthatisoutputbyPython(meaningrange(1,6)countsfrom1to5,butdoesnotincludethenumber6).Thatisbecause"range"ishalf-open,andbythatwemeanitincludesthefirstvalue,butnotthelast.

SummaryThat'sit.Youtotallyrock!Thiswasatrickychapter,soyoushouldfeelproudofyourself.We'redefinitelyproudofyouformakingitthisfar!

Youmightwanttobrieflydosomethingelse–stretch,walkaroundforabit,restyoureyes–beforegoingontothenextchapter.:)

IntroductiontoPython

47

Page 48: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

IntroductiontoPython

48

Page 49: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

WhatisDjango?Django(/ˈdʒæŋɡoʊ/jang-goh)isafreeandopensourcewebapplicationframework,writteninPython.Awebframeworkisasetofcomponentsthathelpsyoutodevelopwebsitesfasterandeasier.

Whenyou'rebuildingawebsite,youalwaysneedasimilarsetofcomponents:awaytohandleuserauthentication(signingup,signingin,signingout),amanagementpanelforyourwebsite,forms,awaytouploadfiles,etc.

Luckilyforyouotherpeoplelongagonoticedthatwebdevelopersfacesimilarproblemswhenbuildinganewsite,sotheyteamedupandcreatedframeworks(Djangoisoneofthem)thatgiveyouready-madecomponentsyoucanuse.

Frameworksexisttosaveyoufromhavingtoreinventthewheelandhelpalleviatesomeoftheoverheadwhenyou’rebuildinganewsite.

Whydoyouneedaframework?TounderstandwhatDjangoactuallyisfor,weneedtotakeacloserlookattheservers.Thefirstthingisthattheserverneedstoknowthatyouwantittoserveyouawebpage.

Imagineamailbox(port)whichismonitoredforincomingletters(requests).Thisisdonebyawebserver.Thewebserverreadstheletter,andsendsaresponsewithawebpage.Butwhenyouwanttosendsomething,youneedtohavesomecontent.AndDjangoissomethingthathelpsyoucreatethecontent.

Whathappenswhensomeonerequestsawebsitefromyourserver?Whenarequestcomestoawebserverit'spassedtoDjangowhichtriestofigureoutwhatactuallyisrequested.Ittakesawebpageaddressfirstandtriestofigureoutwhattodo.ThispartisdonebyDjango'surlresolver(notethatawebsiteaddressiscalledaURL-UniformResourceLocator-sothenameurlresolvermakessense).Itisnotverysmart-ittakesalistofpatternsandtriestomatchtheURL.DjangocheckspatternsfromtoptothebottomandifsomethingismatchedthenDjangopassestherequesttotheassociatedfunction(whichiscalledview).

Imagineamailcarrierwithaletter.Sheiswalkingdownthestreetandcheckseachhousenumberagainsttheoneontheletter.Ifitmatches,sheputstheletterthere.Thisishowtheurlresolverworks!

Intheviewfunctionalltheinterestingthingsaredone:wecanlookatadatabasetolookforsomeinformation.Maybetheuseraskedtochangesomethinginthedata?Likealettersaying"Pleasechangethedescriptionofmyjob."Theviewcancheckifyouareallowedtodothat,thenupdatethejobdescriptionforyouandsendbackamessage:"Done!".ThentheviewgeneratesaresponseandDjangocansendittotheuser'swebbrowser.

Ofcourse,thedescriptionaboveisalittlebitsimplified,butyoudon'tneedtoknowallthetechnicalthingsyet.Havingageneralideaisenough.

Soinsteadofdivingtoomuchintodetails,wewillsimplystartcreatingsomethingwithDjangoandwewilllearnalltheimportantpartsalongtheway!

WhatisDjango?

49

Page 50: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

DjangoinstallationIfyou'reusingaChromebook,skipthischapterandmakesureyoufollowtheChromebookSetupinstructions.

NoteIfyoualreadyworkedthroughtheInstallationstepsthenyou'vealreadydonethis-youcangostraighttothenextchapter!

PartofthissectionisbasedontutorialsbyGeekGirlsCarrots(https://github.com/ggcarrots/django-carrots).

Partofthissectionisbasedonthedjango-marcadortutoriallicensedundertheCreativeCommonsAttribution-ShareAlike4.0InternationalLicense.Thedjango-marcadortutorialiscopyrightedbyMarkusZapke-Gründemannetal.

VirtualenvironmentBeforeweinstallDjangowewillgetyoutoinstallanextremelyusefultooltohelpkeepyourcodingenvironmenttidyonyourcomputer.It'spossibletoskipthisstep,butit'shighlyrecommended.Startingwiththebestpossiblesetupwillsaveyoualotoftroubleinthefuture!

So,let'screateavirtualenvironment(alsocalledavirtualenv).VirtualenvwillisolateyourPython/Djangosetuponaper-projectbasis.Thismeansthatanychangesyoumaketoonewebsitewon'taffectanyothersyou'realsodeveloping.Neat,right?

Allyouneedtodoisfindadirectoryinwhichyouwanttocreatethevirtualenv;yourhomedirectory,forexample.OnWindowsitmightlooklikeC:\Users\Name\(whereNameisthenameofyourlogin).

NOTE:OnWindows,makesurethatthisdirectorydoesnotcontainaccentedorspecialcharacters;ifyourusernamecontainsaccentedcharacters,useadifferentdirectory,forexampleC:\djangogirls.

Forthistutorialwewillbeusinganewdirectorydjangogirlsfromyourhomedirectory:

command-line

$mkdirdjangogirls

$cddjangogirls

Wewillmakeavirtualenvcalledmyvenv.Thegeneralcommandwillbeintheformat:

command-line

$python3-mvenvmyvenv

WindowsTocreateanewvirtualenv,youneedtoopentheconsole(wetoldyouaboutthatafewchaptersago–remember?)andrunC:\Python35\python-mvenvmyvenv.Itwilllooklikethis:

command-line

C:\Users\Name\djangogirls>C:\Python35\python-mvenvmyvenv

whereC:\Python35\pythonisthedirectoryinwhichyoupreviouslyinstalledPythonandmyvenvisthenameofyourvirtualenv.Youcanuseanyothername,butsticktolowercaseandusenospaces,accentsorspecialcharacters.Itisalsogoodideatokeepthenameshort–you'llbereferencingitalot!

Djangoinstallation

50

Page 51: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

LinuxandOSX

CreatingavirtualenvonbothLinuxandOSXisassimpleasrunningpython3-mvenvmyvenv.Itwilllooklikethis:

command-line

$python3-mvenvmyvenv

myvenvisthenameofyourvirtualenv.Youcanuseanyothername,butsticktolowercaseandusenospaces.Itisalsogoodideatokeepthenameshortasyou'llbereferencingitalot!

NOTE:OnsomeversionsofDebian/Ubuntuyoumayreceivethefollowingerror:

command-line

Thevirtualenvironmentwasnotcreatedsuccessfullybecauseensurepipisnotavailable.OnDebian/Ubuntusys

tems,youneedtoinstallthepython3-venvpackageusingthefollowingcommand.

apt-getinstallpython3-venv

Youmayneedtousesudowiththatcommand.Afterinstallingthepython3-venvpackage,recreateyourvirtual

environment.

Inthiscase,followtheinstructionsaboveandinstallthepython3-venvpackage:

command-line

$sudoapt-getinstallpython3-venv

NOTE:OnsomeversionsofDebian/Ubuntuinitiatingthevirtualenvironmentlikethiscurrentlygivesthefollowingerror:

command-line

Error:Command'['/home/eddie/Slask/tmp/venv/bin/python3','-Im','ensurepip','--upgrade','--default-pip']'

returnednon-zeroexitstatus1

Togetaroundthis,usethevirtualenvcommandinstead.

command-line

$sudoapt-getinstallpython-virtualenv

$virtualenv--python=python3.5myvenv

NOTE:Ifyougetanerrorlike

command-line

E:Unabletolocatepackagepython3-venv

theninsteadrun:

command-line

sudoaptinstallpython3.5-venv

Workingwithvirtualenv

Djangoinstallation

51

Page 52: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Thecommandabovewillcreateadirectorycalledmyvenv(orwhatevernameyouchose)thatcontainsourvirtualenvironment(basicallyabunchofdirectoryandfiles).

Windows

Startyourvirtualenvironmentbyrunning:

command-line

C:\Users\Name\djangogirls>myvenv\Scripts\activate

NOTE:onWindows10youmightgetanerrorintheWindowsPowerShellsaysexecutionofscriptsisdisabledonthissystem.InthosecasesopenanotherWindowsPowerShellandRunasAdministratortrydoingthisbeforecontinue:

command-line

C:\WINDOWS\system32>Set-ExecutionPolicy-ExecutionPolicyRemoteSigned

ExecutionPolicyChange

Theexecutionpolicyhelpsprotectyoufromscriptsthatyoudonottrust.Changingtheexecutionpolicym

ightexposeyoutothesecurityrisksdescribedintheabout_Execution_Policieshelptopicathttp://go.micros

oft.com/fwlink/?LinkID=135170.Doyouwanttochangetheexecutionpolicy?[Y]Yes[A]YestoAll[N]No[L

]NotoAll[S]Suspend[?]Help(defaultis"N"):A

LinuxandOSXStartyourvirtualenvironmentbyrunning:

command-line

$sourcemyvenv/bin/activate

Remembertoreplacemyvenvwithyourchosenvirtualenvname!

NOTE:sometimessourcemightnotbeavailable.Inthosecasestrydoingthisinstead:

command-line

$.myvenv/bin/activate

Youwillknowthatyouhavevirtualenvstartedwhenyouseethatthepromptinyourconsoleisprefixedwith(myvenv).

Whenworkingwithinavirtualenvironment,pythonwillautomaticallyrefertothecorrectversionsoyoucanusepythoninsteadofpython3.

OK,wehaveallimportantdependenciesinplace.WecanfinallyinstallDjango!

InstallingDjangoNowthatyouhaveyourvirtualenvstarted,youcaninstallDjango.

Beforewedothat,weshouldmakesurewehavethelatestversionofpip,thesoftwarethatweusetoinstallDjango.Intheconsole,runpipinstall--upgradepip.

Thenrunpipinstalldjango~=1.9.0(notethatweuseatildefollowedbyanequalsign:~=)toinstallDjango.

command-line

Djangoinstallation

52

Page 53: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

(myvenv)~$pipinstalldjango~=1.9.0

Downloading/unpackingdjango==1.9

Installingcollectedpackages:django

Successfullyinstalleddjango

Cleaningup...

onWindows

IfyougetanerrorwhencallingpiponWindowsplatform,pleasecheckifyourprojectpathnamecontainsspaces,accentsorspecialcharacters(forexample,C:\Users\UserName\djangogirls).Ifitdoes,pleaseconsiderusinganotherplacewithoutspaces,accentsorspecialcharacters(suggestion:C:\djangogirls).Createanewvirtualenvinthenewdirectory,thendeletetheoldoneandtrytheabovecommandagain.(Movingthevirtualenvdirectorywon'tworksincevirtualenvusesabsolutepaths.)

onWindows8andWindows10

YourcommandlinemightfreezeafterwhenyoutrytoinstallDjango.Ifthishappens,insteadoftheabovecommanduse:

command-line

C:\Users\Name\djangogirls>python-mpipinstalldjango~=1.9.0

onLinux

IfyougetanerrorwhencallingpiponUbuntu12.04pleaserunpython-mpipinstall-U--force-reinstallpiptofixthepipinstallationinthevirtualenv.

That'sit!You'renow(finally)readytocreateaDjangoapplication!

Djangoinstallation

53

Page 54: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

YourfirstDjangoproject!PartofthischapterisbasedontutorialsbyGeekGirlsCarrots(https://github.com/ggcarrots/django-carrots).

Partsofthischapterarebasedonthedjango-marcadortutoriallicensedunderCreativeCommonsAttribution-ShareAlike4.0InternationalLicense.Thedjango-marcadortutorialiscopyrightedbyMarkusZapke-Gründemannetal.

We'regoingtocreateasimpleblog!

ThefirststepistostartanewDjangoproject.Basically,thismeansthatwe'llrunsomescriptsprovidedbyDjangothatwillcreatetheskeletonofaDjangoprojectforus.Thisisjustabunchofdirectoriesandfilesthatwewilluselater.

ThenamesofsomefilesanddirectoriesareveryimportantforDjango.Youshouldnotrenamethefilesthatweareabouttocreate.Movingthemtoadifferentplaceisalsonotagoodidea.Djangoneedstomaintainacertainstructuretobeabletofindimportantthings.

Remembertoruneverythinginthevirtualenv.Ifyoudon'tseeaprefix(myvenv)inyourconsoleyouneedtoactivateyourvirtualenv.WeexplainedhowtodothatintheDjangoinstallationchapterintheWorkingwithvirtualenvpart.Typingmyvenv\Scripts\activateonWindowsorsourcemyvenv/bin/activateonMacOS/Linuxwilldothisforyou.

InyourMacOSorLinuxconsoleyoushouldrunthefollowingcommand;don'tforgettoaddtheperiod(ordot).attheend:

command-line

(myvenv)~/djangogirls$django-adminstartprojectmysite.

OnWindows;don'tforgettoaddtheperiod(ordot).attheend:

command-line

(myvenv)C:\Users\Name\djangogirls>django-admin.pystartprojectmysite.

Theperiod.iscrucialbecauseittellsthescripttoinstallDjangoinyourcurrentdirectory(forwhichtheperiod.isashort-handreference)

NoteWhentypingthecommandsabove,rememberthatyouonlytypethepartwhichstartsdjango-adminordjango-admin.py.The(myvenv)~/djangogirls$and(myvenv)C:\Users\Name\djangogirls>partsshownherearejustexamplesofthepromptthatwillbeinvitingyourinputonyourcommandline.

django-admin.pyisascriptthatwillcreatethedirectoriesandfilesforyou.Youshouldnowhaveadirectorystructurewhichlookslikethis:

djangogirls

├───manage.py

└───mysite

settings.py

urls.py

wsgi.py

__init__.py

manage.pyisascriptthathelpswithmanagementofthesite.Withitwewillbeabletostartawebserveronourcomputerwithoutinstallinganythingelse,amongstotherthings.

Thesettings.pyfilecontainstheconfigurationofyourwebsite.

YourfirstDjangoproject!

54

Page 55: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Rememberwhenwetalkedaboutamailcarriercheckingwheretodeliveraletter?urls.pyfilecontainsalistofpatternsusedbyurlresolver.

Let'signoretheotherfilesfornowaswewon'tchangethem.Theonlythingtorememberisnottodeletethembyaccident!

ChangingsettingsLet'smakesomechangesinmysite/settings.py.Openthefileusingthecodeeditoryouinstalledearlier.

Itwouldbenicetohavethecorrecttimeonourwebsite.Gotothewikipediatimezoneslistandcopyyourrelevanttimezone(TZ).(eg.Europe/Berlin)

Insettings.py,findthelinethatcontainsTIME_ZONEandmodifyittochooseyourowntimezone:

mysite/settings.py

TIME_ZONE='Europe/Berlin'

Modifying"Europe/Berlin"asappropriate

We'llalsoneedtoaddapathforstaticfiles(we'llfindoutallaboutstaticfilesandCSSlaterinthetutorial).Godowntotheendofthefile,andjustunderneaththeSTATIC_URLentry,addanewonecalledSTATIC_ROOT:

mysite/settings.py

STATIC_URL='/static/'

STATIC_ROOT=os.path.join(BASE_DIR,'static')

:Ifyou'reusingaChromebook,addthislineatthebottomofyoursettings.pyfile:MESSAGE_STORAGE='django.contrib.messages.storage.session.SessionStorage'

SetupadatabaseThere'salotofdifferentdatabasesoftwarethatcanstoredataforyoursite.We'llusethedefaultone,sqlite3.

Thisisalreadysetupinthispartofyourmysite/settings.pyfile:

mysite/settings.py

DATABASES={

'default':{

'ENGINE':'django.db.backends.sqlite3',

'NAME':os.path.join(BASE_DIR,'db.sqlite3'),

}

}

Tocreateadatabaseforourblog,let'srunthefollowingintheconsole:pythonmanage.pymigrate(weneedtobeinthedjangogirlsdirectorythatcontainsthemanage.pyfile).Ifthatgoeswell,youshouldseesomethinglikethis:

command-line

YourfirstDjangoproject!

55

Page 56: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

(myvenv)~/djangogirls$pythonmanage.pymigrate

Operationstoperform:

Applyallmigrations:auth,admin,contenttypes,sessions

Runningmigrations:

Renderingmodelstates...DONE

Applyingcontenttypes.0001_initial...OK

Applyingauth.0001_initial...OK

Applyingadmin.0001_initial...OK

Applyingadmin.0002_logentry_remove_auto_add...OK

Applyingcontenttypes.0002_remove_content_type_name...OK

Applyingauth.0002_alter_permission_name_max_length...OK

Applyingauth.0003_alter_user_email_max_length...OK

Applyingauth.0004_alter_user_username_opts...OK

Applyingauth.0005_alter_user_last_login_null...OK

Applyingauth.0006_require_contenttypes_0002...OK

Applyingauth.0007_alter_validators_add_error_messages...OK

Applyingsessions.0001_initial...OK

Andwe'redone!Timetostartthewebserverandseeifourwebsiteisworking!

StartingthewebserverYouneedtobeinthedirectorythatcontainsthemanage.pyfile(thedjangogirlsdirectory).Intheconsole,wecanstartthewebserverbyrunningpythonmanage.pyrunserver:

command-line

(myvenv)~/djangogirls$pythonmanage.pyrunserver

IfyouareonaChromebook,usethiscommandinstead:

Cloud9

(myvenv)~/djangogirls$pythonmanage.pyrunserver0.0.0.0:8080

IfyouareonWindowsandthisfailswithUnicodeDecodeError,usethiscommandinstead:

command-line

(myvenv)~/djangogirls$pythonmanage.pyrunserver0:8000

Nowallyouneedtodoischeckthatyourwebsiteisrunning.Openyourbrowser(Firefox,Chrome,Safari,InternetExplorerorwhateveryouuse)andentertheaddress:

browser

http://127.0.0.1:8000/

Ifyou'reusingaChromebook,you'llalwaysvisityourtestserverbyaccessing:

browser

https://django-girls-<yourcloud9username>.c9users.io

Congratulations!You'vejustcreatedyourfirstwebsiteandrunitusingawebserver!Isn'tthatawesome?

YourfirstDjangoproject!

56

Page 57: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Whilethewebserverisrunning,youwon'tseeanewcommandlineprompttoenteradditonalcommands.Theterminalwillacceptnewtextbutwillnotexecutenewcommands.Thisisbecausethewebservercontinuouslyrunsinordertolistenforincomingrequests.

WereviewedhowwebserversworkintheHowtheInternetworkschapter.

Totypeadditionalcommandswhilethewebserverisrunning,openanewterminalwindowandactivateyourvirtualenv.Tostopthewebserver,switchbacktothewindowinwhichit'srunningandpressCTRL+C-ControlandCbuttonstogether(onWindows,youmighthavetopressCtrl+Break).

Readyforthenextstep?It'stimetocreatesomecontent!

YourfirstDjangoproject!

57

Page 58: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

DjangomodelsWhatwewanttocreatenowissomethingthatwillstoreallthepostsinourblog.Buttobeabletodothatweneedtotalkalittlebitaboutthingscalledobjects.

ObjectsThereisaconceptinprogrammingcalledObject-orientedprogramming.Theideaisthatinsteadofwritingeverythingasaboringsequenceofprogramminginstructionswecanmodelthingsanddefinehowtheyinteractwitheachother.

Sowhatisanobject?Itisacollectionofpropertiesandactions.Itsoundsweird,butwewillgiveyouanexample.

IfwewanttomodelacatwewillcreateanobjectCatthathassomepropertiessuchas:color,age,mood(likegood,bad,orsleepy;)),andowner(thatisaPersonobjectormaybe,incaseofastraycat,thispropertyisempty).

ThentheCathassomeactions:purr,scratch,orfeed(inwhichcase,wewillgivethecatsomeCatFood,whichcouldbeaseparateobjectwithproperties,liketaste).

Cat

--------

color

age

mood

owner

purr()

scratch()

feed(cat_food)

CatFood

--------

taste

Sobasicallytheideaistodescriberealthingsincodewithproperties(calledobjectproperties)andactions(calledmethods).

Howwillwemodelblogpoststhen?Wewanttobuildablog,right?

Weneedtoanswerthequestion:Whatisablogpost?Whatpropertiesshouldithave?

Well,forsureourblogpostneedssometextwithitscontentandatitle,right?Itwouldbealsonicetoknowwhowroteit-soweneedanauthor.Finally,wewanttoknowwhenthepostwascreatedandpublished.

Post

--------

title

text

author

created_date

published_date

Whatkindofthingscouldbedonewithablogpost?Itwouldbenicetohavesomemethodthatpublishesthepost,right?

Sowewillneedapublishmethod.

Sincewealreadyknowwhatwewanttoachieve,let'sstartmodelingitinDjango!

Djangomodel

Djangomodels

58

Page 59: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Knowingwhatanobjectis,wecancreateaDjangomodelforourblogpost.

AmodelinDjangoisaspecialkindofobject-itissavedinthedatabase.Adatabaseisacollectionofdata.Thisisaplaceinwhichyouwillstoreinformationaboutusers,yourblogposts,etc.WewillbeusingaSQLitedatabasetostoreourdata.ThisisthedefaultDjangodatabaseadapter--it'llbeenoughforusrightnow.

Youcanthinkofamodelinthedatabaseasaspreadsheetwithcolumns(fields)androws(data).

CreatinganapplicationTokeepeverythingtidy,wewillcreateaseparateapplicationinsideourproject.Itisverynicetohaveeverythingorganizedfromtheverybeginning.Tocreateanapplicationweneedtorunthefollowingcommandintheconsole(fromdjangogirlsdirectorywheremanage.pyfileis):

command-line

(myvenv)~/djangogirls$pythonmanage.pystartappblog

Youwillnoticethatanewblogdirectoryiscreatedanditcontainsanumberoffilesnow.Ourdirectoriesandfilesinourprojectshouldlooklikethis:

djangogirls

├──blog

│├──__init__.py

│├──admin.py

│├──apps.py

│├──migrations

││└──__init__.py

│├──models.py

│├──tests.py

│└──views.py

├──db.sqlite3

├──manage.py

└──mysite

├──__init__.py

├──settings.py

├──urls.py

└──wsgi.py

AftercreatinganapplicationwealsoneedtotellDjangothatitshoulduseit.Wedothatinthefilemysite/settings.py.WeneedtofindINSTALLED_APPSandaddalinecontaining'blog',justabove).Sothefinalproductshouldlooklikethis:

mysite/settings.py

INSTALLED_APPS=(

'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

'blog',

)

Creatingablogpostmodel

Intheblog/models.pyfilewedefineallobjectscalledModels-thisisaplaceinwhichwewilldefineourblogpost.

Let'sopenblog/models.py,removeeverythingfromitandwritecodelikethis:

blog/models.py

Djangomodels

59

Page 60: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

fromdjango.dbimportmodels

fromdjango.utilsimporttimezone

classPost(models.Model):

author=models.ForeignKey('auth.User')

title=models.CharField(max_length=200)

text=models.TextField()

created_date=models.DateTimeField(

default=timezone.now)

published_date=models.DateTimeField(

blank=True,null=True)

defpublish(self):

self.published_date=timezone.now()

self.save()

def__str__(self):

returnself.title

Double-checkthatyouusetwounderscorecharacters(_)oneachsideofstr.ThisconventionisusedfrequentlyinPythonandsometimeswealsocallthem"dunder"(shortfor"double-underscore").

Itlooksscary,right?Butnoworrieswewillexplainwhattheselinesmean!

Alllinesstartingwithfromorimportarelinesthataddsomebitsfromotherfiles.Soinsteadofcopyingandpastingthesamethingsineveryfile,wecanincludesomepartswithfrom...import....

classPost(models.Model):-thislinedefinesourmodel(itisanobject).

classisaspecialkeywordthatindicatesthatwearedefininganobject.Postisthenameofourmodel.Wecangiveitadifferentname(butwemustavoidspecialcharactersandwhitespaces).Alwaysstartaclassnamewithanuppercaseletter.models.ModelmeansthatthePostisaDjangoModel,soDjangoknowsthatitshouldbesavedinthedatabase.

Nowwedefinethepropertiesweweretalkingabout:title,text,created_date,published_dateandauthor.Todothatweneedtodefineatypeofeachfield(Isittext?Anumber?Adate?Arelationtoanotherobject,likeaUser?).

models.CharField-thisishowyoudefinetextwithalimitednumberofcharacters.models.TextField-thisisforlongtextwithoutalimit.Soundsidealforblogpostcontent,right?models.DateTimeField-thisisadateandtime.models.ForeignKey-thisisalinktoanothermodel.

Wewillnotexplaineverybitofcodeheresinceitwouldtaketoomuchtime.YoushouldtakealookatDjango'sdocumentationifyouwanttoknowmoreaboutModelfieldsandhowtodefinethingsotherthanthosedescribedabove(https://docs.djangoproject.com/en/1.9/ref/models/fields/#field-types).

Whataboutdefpublish(self):?Itisexactlythepublishmethodweweretalkingaboutbefore.defmeansthatthisisafunction/methodandpublishisthenameofthemethod.Youcanchangethenameofthemethod,ifyouwant.Thenamingruleisthatweuselowercaseandunderscoresinsteadofwhitespaces.Forexample,amethodthatcalculatesaveragepricecouldbecalledcalculate_average_price.

Methodsoftenreturnsomething.Thereisanexampleofthatinthe__str__method.Inthisscenario,whenwecall__str__()wewillgetatext(string)withaPosttitle.

Alsonoticethatbothdefpublish(self):,anddef__str__(self):areindentedinsideourclass.BecausePythonissensitivetowhitespace,weneedtoindentourmethodsinsidetheclass.Otherwise,themethodswon'tbelongtotheclass,andyoucangetsomeunexpectedbehavior.

Ifsomethingisstillnotclearaboutmodels,feelfreetoaskyourcoach!Weknowitiscomplicated,especiallywhenyoulearnwhatobjectsandfunctionsareatthesametime.Buthopefullyitlooksslightlylessmagicforyounow!

Djangomodels

60

Page 61: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Createtablesformodelsinyourdatabase

Thelaststephereistoaddournewmodeltoourdatabase.FirstwehavetomakeDjangoknowthatwehavesomechangesinourmodel(wehavejustcreatedit!).Gotoyourconsolewindowandtypepythonmanage.pymakemigrationsblog.Itwilllooklikethis:

command-line

(myvenv)~/djangogirls$pythonmanage.pymakemigrationsblog

Migrationsfor'blog':

0001_initial.py:

-CreatemodelPost

Djangopreparedforusamigrationfilethatwehavetoapplynowtoourdatabase.Typepythonmanage.pymigrateblogandtheoutputshouldbe:

command-line

(myvenv)~/djangogirls$pythonmanage.pymigrateblog

Operationstoperform:

Applyallmigrations:blog

Runningmigrations:

Renderingmodelstates...DONE

Applyingblog.0001_initial...OK

Hurray!OurPostmodelisnowinourdatabase!Itwouldbenicetoseeit,right?JumptothenextchaptertoseewhatyourPostlookslike!

Djangomodels

61

Page 62: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

DjangoadminToadd,editanddeletepostswe'vejustmodeled,wewilluseDjangoadmin.

Let'sopentheblog/admin.pyfileandreplaceitscontentwiththis:

blog/admin.py

fromdjango.contribimportadmin

from.modelsimportPost

admin.site.register(Post)

Asyoucansee,weimport(include)thePostmodeldefinedinthepreviouschapter.Tomakeourmodelvisibleontheadminpage,weneedtoregisterthemodelwithadmin.site.register(Post).

OK,timetolookatourPostmodel.Remembertorunpythonmanage.pyrunserverintheconsoletorunthewebserver.Gotothebrowserandtypetheaddresshttp://127.0.0.1:8000/admin/Youwillseealoginpagelikethis:

Tologin,youneedtocreateasuperuser-auserwhichhascontrolovereverythingonthesite.Gobacktothecommand-lineandtypepythonmanage.pycreatesuperuser,andpressenter.

Remember,towritenewcommandswhilethewebserverisrunning,openanewterminalwindowandactivateyourvirtualenv.WereviewedhowtowritenewcommandsintheYourfirstDjangoproject!chapter,intheStartingthewebserversection.

Whenprompted,typeyourusername(lowercase,nospaces),emailaddress,andpassword.Don'tworrythatyoucan'tseethepasswordyou'retypingin-that'showit'ssupposedtobe.Justtypeitinandpressentertocontinue.Theoutputshouldlooklikethis(whereusernameandemailshouldbeyourownones):

command-line

(myvenv)~/djangogirls$pythonmanage.pycreatesuperuser

Username:admin

Emailaddress:[email protected]

Password:

Password(again):

Superusercreatedsuccessfully.

Djangoadmin

62

Page 63: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Returntoyourbrowser.Loginwiththesuperuser'scredentialsyouchose;youshouldseetheDjangoadmindashboard.

GotoPostsandexperimentalittlebitwithit.Addfiveorsixblogposts.Don'tworryaboutthecontent-youcansimplycopy-pastesometextfromthistutorialtosavetime:).

Makesurethatatleasttwoorthreeposts(butnotall)havethepublishdateset.Itwillbehelpfullater.

IfyouwanttoknowmoreaboutDjangoadmin,youshouldcheckDjango'sdocumentation:https://docs.djangoproject.com/en/1.9/ref/contrib/admin/

Thisisprobablyagoodmomenttograbacoffee(ortea)orsomethingtoeattore-energiseyourself.YoucreatedyourfirstDjangomodel-youdeservealittletimeout!

Djangoadmin

63

Page 64: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Deploy!Thefollowingchaptercanbesometimesabithardtogetthrough.Persistandfinishit;deploymentisanimportantpartofthewebsitedevelopmentprocess.Thischapterisplacedinthemiddleofthetutorialsothatyourmentorcanhelpwiththeslightlytrickierprocessofgettingyourwebsiteonline.Thismeansyoucanstillfinishthetutorialonyourownifyourunoutoftime.

Untilnow,yourwebsitewasonlyavailableonyourcomputer.Nowyouwilllearnhowtodeployit!DeployingistheprocessofpublishingyourapplicationontheInternetsopeoplecanfinallygoandseeyourapp:).

Asyoulearned,awebsitehastobelocatedonaserver.Therearealotofserverprovidersavailableontheinternet.Wewilluseonethathasarelativelysimpledeploymentprocess:PythonAnywhere.PythonAnywhereisfreeforsmallapplicationsthatdon'thavetoomanyvisitorssoit'lldefinitelybeenoughforyounow.

Theotherexternalservicewe'llbeusingisGitHub,whichisacodehostingservice.Thereareothersoutthere,butalmostallprogrammershaveaGitHubaccountthesedays,andnowsowillyou!

Thesethreeplaceswillbeimportanttoyou.Yourlocalcomputerwillbetheplacewhereyoudodevelopmentandtesting.Whenyou'rehappywiththechanges,youwillplaceacopyofyourprogramonGitHub.YourwebsitewillbeonPythonAnywhereandyouwillupdateitbygettinganewcopyofyourcodefromGitHub.

GitGitisa"versioncontrolsystem"usedbyalotofprogrammers.Thissoftwarecantrackchangestofilesovertimesothatyoucanrecallspecificversionslater.Abitlikethe"trackchanges"featureinMicrosoftWord,butmuchmorepowerful.

InstallingGitIfyoualreadydidtheInstallationsteps,noneedtodothisagain-youcanskiptothenextsectionandstartcreatingyourGitrepository.

Windows

YoucandownloadGitfromgit-scm.com.Youcanhit"next"onallstepsexceptforone;inthefifthstepentitled"AdjustingyourPATHenvironment",choose"UseGitandoptionalUnixtoolsfromtheWindowsCommandPrompt"(thebottomoption).Otherthanthat,thedefaultsarefine.CheckoutWindows-style,commitUnix-stylelineendingsisgood.

MacOSDownloadGitfromgit-scm.comandjustfollowtheinstructions.

LinuxIfitisn'tinstalledalready,gitshouldbeavailableviayourpackagemanager,sotry:

DebianorUbuntucommand-line

$sudoapt-getinstallgit

Deploy!

64

Page 65: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Fedora(upto21)

command-line

$sudoyuminstallgit

Fedora(22+)

command-line

$sudodnfinstallgit

openSUSE

command-line

$sudozypperinstallgit

StartingourGitrepositoryGittrackschangestoaparticularsetoffilesinwhat'scalledacoderepository(or"repo"forshort).Let'sstartoneforourproject.Openupyourconsoleandrunthesecommands,inthedjangogirlsdirectory:

Checkyourcurrentworkingdirectorywithapwd(OSX/Linux)orcd(Windows)commandbeforeinitializingtherepository.Youshouldbeinthedjangogirlsfolder.

command-line

$gitinit

InitializedemptyGitrepositoryin~/djangogirls/.git/

$gitconfig--globaluser.name"YourName"

[email protected]

Initializingthegitrepositoryissomethingweonlyneedtodoonceperproject(andyouwon'thavetore-entertheusernameandemailagainever).

Gitwilltrackchangestoallthefilesandfoldersinthisdirectory,buttherearesomefileswewantittoignore.Wedothisbycreatingafilecalled.gitignoreinthebasedirectory.Openupyoureditorandcreateanewfilewiththefollowingcontents:

.gitignore

*.pyc

__pycache__

myvenv

db.sqlite3

/static

.DS_Store

Andsaveitas.gitignoreinthe"djangogirls"folder.

Deploy!

65

Page 66: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Thedotatthebeginningofthefilenameisimportant!Ifyou'rehavinganydifficultycreatingit(Macsdon'tlikeyoutocreatefilesthatbeginwithadotviatheFinder,forexample),thenusethe"SaveAs"featureinyoureditor,it'sbulletproof.

NoteOneofthefilesyouspecifiedinyour.gitignorefileisdb.sqlite3.Thatfileisyourlocaldatabase,wherealloryourpostsarestored.Wedon'twanttoaddthistoyourrepository,becauseyourwebsiteonPythonAnywhereisgoingtobeusingadifferentdatabase.ThatdatabasecouldbeSQLite,likeyourdevelopmentmachine,butusually,youwilluseonecalledMySQLwhichcandealwithalotmoresitevisitorsthanSQLite.Eitherway,byignoringyourSQLitedatabasefortheGitHubcopy,itmeansthatallofthepostsyoucreatedsofararegoingtostayandonlybeavailablelocally,butyou'regonnahavetoaddthemagainonproduction.Youshouldthinkofyourlocaldatabaseasagoodplaygroundwhereyoucantestdifferentthingsandnotbeafraidthatyou'regoingtodeleteyourrealpostsfromyourblog.

It'sagoodideatouseagitstatuscommandbeforegitaddorwheneveryoufindyourselfunsureofwhathaschanged.Thiswillhelpstopanysurprisesfromhappening,suchaswrongfilesbeingaddedorcommited.Thegitstatuscommandreturnsinformationaboutanyuntracked/modifed/stagedfiles,branchstatus,andmuchmore.Theoutputshouldbesimilarto:

command-line

$gitstatus

Onbranchmaster

Initialcommit

Untrackedfiles:

(use"gitadd<file>..."toincludeinwhatwillbecommitted)

.gitignore

blog/

manage.py

mysite/

nothingaddedtocommitbutuntrackedfilespresent(use"gitadd"totrack)

Andfinallywesaveourchanges.Gotoyourconsoleandrunthesecommands:

command-line

$gitadd--all.

$gitcommit-m"MyDjangoGirlsapp,firstcommit"

[...]

13fileschanged,200insertions(+)

createmode100644.gitignore

[...]

createmode100644mysite/wsgi.py

PushingourcodetoGitHubGotoGitHub.comandsignupforanew,freeuseraccount.(Ifyoualreadydidthatintheworkshopprep,thatisgreat!)

Then,createanewrepository,givingitthename"my-first-blog".Leavethe"initialisewithaREADME"tickboxun-checked,leavethe.gitignoreoptionblank(we'vedonethatmanually)andleavetheLicenseasNone.

Deploy!

66

Page 67: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Thenamemy-first-blogisimportant--youcouldchoosesomethingelse,butit'sgoingtooccurlotsoftimesintheinstructionsbelow,andyou'dhavetosubstituteiteachtime.It'sprobablyeasiertojuststickwiththenamemy-first-blog.

Onthenextscreen,you'llbeshownyourrepo'scloneURL.Choosethe"HTTPS"version,copyit,andwe'llpasteitintotheterminalshortly:

NowweneedtohookuptheGitrepositoryonyourcomputertotheoneuponGitHub.

Typethefollowingintoyourconsole(Replace<your-github-username>withtheusernameyouenteredwhenyoucreatedyourGitHubaccount,butwithouttheangle-brackets):

command-line

Deploy!

67

Page 68: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

$gitremoteaddoriginhttps://github.com/<your-github-username>/my-first-blog.git

$gitpush-uoriginmaster

EnteryourGitHubusernameandpasswordandyoushouldseesomethinglikethis:

command-line

Usernamefor'https://github.com':hjwp

Passwordfor'https://[email protected]':

Countingobjects:6,done.

Writingobjects:100%(6/6),200bytes|0bytes/s,done.

Total3(delta0),reused0(delta0)

Tohttps://github.com/hjwp/my-first-blog.git

*[newbranch]master->master

Branchmastersetuptotrackremotebranchmasterfromorigin.

YourcodeisnowonGitHub.Goandcheckitout!You'llfindit'sinfinecompany-Django,theDjangoGirlsTutorial,andmanyothergreatopensourcesoftwareprojectsalsohosttheircodeonGitHub:)

SettingupourblogonPythonAnywhereYoumighthavealreadycreatedaPythonAnywhereaccountearlierduringtheinstallsteps-ifso,noneedtodoitagain.

Nextit'stimetosignupforafree"Beginner"accountonPythonAnywhere.

www.pythonanywhere.com

Whenchoosingyourusernamehere,bearinmindthatyourblog'sURLwilltaketheformyourusername.pythonanywhere.com,sochooseeitheryourownnickname,oranameforwhatyourblogisallabout.

PullingourcodedownonPythonAnywhereWhenyou'vesignedupforPythonAnywhere,you'llbetakentoyourdashboardor"Consoles"page.Choosetheoptiontostarta"Bash"console--that'sthePythonAnywhereversionofaconsole,justliketheoneonyourcomputer.

PythonAnywhereisbasedonLinux,soifyou'reonWindows,theconsolewilllookalittledifferentfromtheoneonyourcomputer.

Let'spulldownourcodefromGitHubandontoPythonAnywherebycreatinga"clone"ofourrepo.TypethefollowingintotheconsoleonPythonAnywhere(don'tforgettouseyourGitHubusernameinplaceof<your-github-username>):

PythonAnywherecommand-line

$gitclonehttps://github.com/<your-github-username>/my-first-blog.git

ThiswillpulldownacopyofyourcodeontoPythonAnywhere.Checkitoutbytypingtreemy-first-blog:

PythonAnywherecommand-line

Deploy!

68

Page 69: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

$treemy-first-blog

my-first-blog/

├──blog

│├──__init__.py

│├──admin.py

│├──migrations

││├──0001_initial.py

││└──__init__.py

│├──models.py

│├──tests.py

│└──views.py

├──manage.py

└──mysite

├──__init__.py

├──settings.py

├──urls.py

└──wsgi.py

CreatingavirtualenvonPythonAnywhereJustlikeyoudidonyourowncomputer,youcancreateavirtualenvonPythonAnywhere.IntheBashconsole,type:

PythonAnywherecommand-line

$cdmy-first-blog

$virtualenv--python=python3.5myvenv

Runningvirtualenvwithinterpreter/usr/bin/python3.5

[...]

Installingsetuptools,pip...done.

$sourcemyvenv/bin/activate

(myvenv)$pipinstalldjango~=1.9.0

Collectingdjango

[...]

Successfullyinstalleddjango-1.9

Thepipinstallstepcantakeacoupleofminutes.Patience,patience!Butifittakesmorethan5minutes,somethingiswrong.Askyourcoach.

CreatingthedatabaseonPythonAnywhere

Here'sanotherthingthat'sdifferentbetweenyourowncomputerandtheserver:itusesadifferentdatabase.Sotheuseraccountsandpostscanbedifferentontheserverandonyourcomputer.

Wecaninitialisethedatabaseontheserverjustlikewedidtheoneonyourowncomputer,withmigrateandcreatesuperuser:

PythonAnywherecommand-line

(mvenv)$pythonmanage.pymigrate

Operationstoperform:

[...]

Applyingsessions.0001_initial...OK

(mvenv)$pythonmanage.pycreatesuperuser

Publishingourblogasawebapp

Deploy!

69

Page 70: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

NowourcodeisonPythonAnywhere,ourvirtualenvisready,andthedatabaseisinitialised.We'rereadytopublishitasawebapp!

ClickbacktothePythonAnywheredashboardbyclickingonitslogo,andgoclickontheWebtab.Finally,hitAddanewwebapp.

Afterconfirmingyourdomainname,choosemanualconfiguration(NBnotthe"Django"option)inthedialog.NextchoosePython3.5,andclickNexttofinishthewizard.

Makesureyouchoosethe"Manualconfiguration"option,notthe"Django"one.We'retoocoolforthedefaultPythonAnywhereDjangosetup;-)

SettingthevirtualenvYou'llbetakentothePythonAnywhereconfigscreenforyourwebapp,whichiswhereyou'llneedtogowheneveryouwanttomakechangestotheappontheserver.

Inthe"Virtualenv"section,clicktheredtextthatsays"Enterthepathtoavirtualenv",andenter:/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/.Clicktheblueboxwiththecheckmarktosavethepathbeforemovingon.

SubstituteyourownPythonAnywhereusernameasappropriate.Ifyoumakeamistake,PythonAnywherewillshowyoualittlewarning.

ConfiguringtheWSGIfile

Djangoworksusingthe"WSGIprotocol",astandardforservingwebsitesusingPython,whichPythonAnywheresupports.ThewayweconfigurePythonAnywheretorecogniseourDjangoblogisbyeditingaWSGIconfigurationfile.

Clickonthe"WSGIconfigurationfile"link(inthe"Code"sectionnearthetopofthepage--it'llbenamedsomethinglike/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py),andyou'llbetakentoaneditor.

Deleteallthecontentsandreplacethemwithsomethinglikethis:

<your-username>_pythonanywhere_com_wsgi.py

Deploy!

70

Page 71: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

importos

importsys

path='/home/<your-PythonAnywhere-username>/my-first-blog'#useyourownPythonAnywhereusernamehere

ifpathnotinsys.path:

sys.path.append(path)

os.environ['DJANGO_SETTINGS_MODULE']='mysite.settings'

fromdjango.core.wsgiimportget_wsgi_application

fromdjango.contrib.staticfiles.handlersimportStaticFilesHandler

application=StaticFilesHandler(get_wsgi_application())

Don'tforgettosubstituteinyourownPythonAnywhereusernamewhereitsays<your-PythonAnywhere-username>NoteInlinefour,wemakesurePythonanywhereknowshowtofindourapplication.Itisveryimportantthatthispathnameiscorrect,andespeciallythattherearenoextraspaceshere.Otherwiseyouwillseean"ImportError"intheerrorlog.

Thisfile'sjobistotellPythonAnywherewhereourwebapplivesandwhattheDjangosettingsfile'snameis.

TheStaticFilesHandlerisfordealingwithourCSS.Thisistakencareofautomaticallyforyouduringlocaldevelopmentbytherunservercommand.We'llfindoutabitmoreaboutstaticfileslaterinthetutorial,whenweedittheCSSforoursite.

HitSaveandthengobacktotheWebtab.

We'realldone!HitthebiggreenReloadbuttonandyou'llbeabletogoviewyourapplication.You'llfindalinktoitatthetopofthepage.

DebuggingtipsIfyouseeanerrorwhenyoutrytovisityoursite,thefirstplacetolookforsomedebugginginfoisinyourerrorlog.You'llfindalinktothisonthePythonAnywhereWebtab.Seeifthereareanyerrormessagesinthere;themostrecentonesareatthebottom.Commonproblemsinclude:

Forgettingoneofthestepswedidintheconsole:creatingthevirtualenv,activatingit,installingDjangointoit,migratingthedatabase.

MakingamistakeinthevirtualenvpathontheWebtab--therewillusuallybealittlerederrormessageonthere,ifthereisaproblem.

MakingamistakeintheWSGIconfigurationfile--didyougetthepathtoyourmy-first-blogfolderright?

DidyoupickthesameversionofPythonforyourvirtualenvasyoudidforyourwebapp?Bothshouldbe3.5.

TherearesomegeneraldebuggingtipsonthePythonAnywherewiki.

Andremember,yourcoachisheretohelp!

Youarelive!Thedefaultpageforyoursiteshouldsay"WelcometoDjango",justlikeitdoesonyourlocalcomputer.Tryadding/admin/totheendoftheURL,andyou'llbetakentotheadminsite.Loginwiththeusernameandpassword,andyou'llseeyoucanaddnewPostsontheserver.

Onceyouhaveafewpostscreated,youcangobacktoyourlocalsetup(notPythonAnywhere).Fromhereyoushouldworkonyourlocalsetuptomakechanges.ThisisacommonworkflowinWebdevelopment(makechangeslocally,pushthosechangestoGitHub,pullyourchangesdowntoyourliveWebserver).Thisallowsyoutoworkandexperimentwithout

Deploy!

71

Page 72: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

breakingyourliveWebsite.Prettycool,huh?

GiveyourselfaHUGEpatontheback!Serverdeploymentsareoneofthetrickiestpartsofwebdevelopmentanditoftentakespeopleseveraldaysbeforetheygetthemworking.Butyou'vegotyoursitelive,ontherealInternet,justlikethat!

Deploy!

72

Page 73: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

DjangoURLsWe'reabouttobuildourfirstwebpage:ahomepageforyourblog!Butfirst,let'slearnalittlebitaboutDjangourls.

WhatisaURL?AURLissimplyawebaddress.YoucanseeaURLeverytimeyouvisitawebsite-itisvisibleinyourbrowser'saddressbar(yes!127.0.0.1:8000isaURL!Andhttps://djangogirls.orgisalsoaURL):

EverypageontheInternetneedsitsownURL.ThiswayyourapplicationknowswhatitshouldshowtoauserwhoopensaURL.InDjangoweusesomethingcalledURLconf(URLconfiguration).URLconfisasetofpatternsthatDjangowilltrytomatchwiththereceivedURLtofindthecorrectview.

HowdoURLsworkinDjango?Let'sopenupthemysite/urls.pyfileinyourcodeeditorofchoiceandseewhatitlookslike:

mysite/urls.py

"""mysiteURLConfiguration

[...]

"""

fromdjango.conf.urlsimporturl

fromdjango.contribimportadmin

urlpatterns=[

url(r'^admin/',admin.site.urls),

]

Asyoucansee,Djangoalreadyputsomethinghereforus.

Linesbetweentriplequotes('''or""")arecalleddocstrings-youcanwritethematthetopofafile,classormethodtodescribewhatitdoes.Theywon'tberunbyPython.

TheadminURL,whichyouvisitedinpreviouschapterisalreadyhere:

mysite/urls.py

url(r'^admin/',admin.site.urls),

ItmeansthatforeveryURLthatstartswithadmin/Djangowillfindacorrespondingview.Inthiscasewe'reincludingalotofadminURLssoitisn'tallpackedintothissmallfile--it'smorereadableandcleaner.

Djangourls

73

Page 74: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

RegexDoyouwonderhowDjangomatchesURLstoviews?Well,thispartistricky.Djangousesregex,shortfor"regularexpressions".Regexhasalot(alot!)ofrulesthatformasearchpattern.Sinceregexesareanadvancedtopic,wewillnotgoindetailoverhowtheywork.

Ifyoustillwishtounderstandhowwecreatedthepatterns,hereisanexampleoftheprocess-wewillonlyneedalimitedsubsetoftherulestoexpressthepatternwearelookingfor,namely:

^forbeginningofthetext

$forendoftext

\dforadigit

+toindicatethatthepreviousitemshouldberepeatedatleastonce

()tocapturepartofthepattern

Anythingelseintheurldefinitionwillbetakenliterally.

Nowimagineyouhaveawebsitewiththeaddresslikethat:http://www.mysite.com/post/12345/,where12345isthenumberofyourpost.

Writingseparateviewsforallthepostnumberswouldbereallyannoying.Withregularexpressionwecancreateapatternthatwillmatchtheurlandextractthenumberforus: ̂ post/(\d+)/$.Let'sbreakitdownpiecebypiecetoseewhatwearedoinghere:

^post/istellingDjangototakeanythingthathaspost/atthebeginningoftheurl(rightafter ̂ )(\d+)meansthattherewillbeanumber(oneormoredigits)andthatwewantthenumbercapturedandextracted/tellsdjangothatanother/charactershouldfollow$thenindicatestheendoftheURLmeaningthatonlystringsendingwiththe/willmatchthispattern

YourfirstDjangourl!TimetocreateourfirstURL!Wewant'http://127.0.0.1:8000/'tobeahomepageofourbloganddisplayalistofposts.

Wealsowanttokeepthemysite/urls.pyfileclean,sowewillimporturlsfromourblogapplicationtothemainmysite/urls.pyfile.

Goahead,addalinethatwillimportblog.urlsintothemainurl('').Notethatweareusingtheincludefunctionheresoyouwillneedtoaddthattotheimportonthefirstlineofthefile.

Yourmysite/urls.pyfileshouldnowlooklikethis:

mysite/urls.py

fromdjango.conf.urlsimportinclude,url

fromdjango.contribimportadmin

urlpatterns=[

url(r'^admin/',admin.site.urls),

url(r'',include('blog.urls')),

]

Djangowillnowredirecteverythingthatcomesinto'http://127.0.0.1:8000/'toblog.urlsandlookforfurtherinstructionsthere.

WhenwritingregularexpressionsinPythonitisalwaysdonewithrinfrontofthestring.ThisisahelpfulhintforPythonthatthestringmaycontainspecialcharactersthatarenotmeantforPythonitself,butfortheregularexpressioninstead.

blog.urls

Djangourls

74

Page 75: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Createanewblog/urls.pyemptyfile.Allright!Addthesetwofirstlines:

blog/urls.py

fromdjango.conf.urlsimporturl

from.importviews

Herewe'reimportingDjango'sfunctionurlandallofourviewsfromblogapplication(wedon'thaveanyyet,butwewillgettothatinaminute!)

Afterthat,wecanaddourfirstURLpattern:

blog/urls.py

urlpatterns=[

url(r'^$',views.post_list,name='post_list'),

]

Asyoucansee,we'renowassigningaviewcalledpost_listto ̂ $URL.Thisregularexpressionwillmatch ̂ (abeginning)followedby$(anend)-soonlyanemptystringwillmatch.That'scorrect,becauseinDjangoURLresolvers,'http://127.0.0.1:8000/'isnotapartoftheURL.ThispatternwilltellDjangothatviews.post_lististherightplacetogoifsomeoneentersyourwebsiteatthe'http://127.0.0.1:8000/'address.

Thelastpartname='post_list'isthenameoftheURLthatwillbeusedtoidentifytheview.Thiscanbethesameasthenameoftheviewbutitcanalsobesomethingcompletelydifferent.WewillbeusingthenamedURLslaterintheprojectsoitisimportanttonameeachURLintheapp.WeshouldalsotrytokeepthenamesofURLsuniqueandeasytoremember.

Ifyoutrytovisithttp://127.0.0.1:8000/now,thenyou'llfindsomesortof'webpagenotavailable'message.Thisisbecausetheserver(remembertypingrunserver?)isnolongerrunning.Takealookatyourserverconsolewindowtofindoutwhy.

Yourconsoleisshowinganerrorbutdon'tworry—they'reactuallyprettyuseful:

It'stellingyouthatthereisnoattribute'post_list'.That'sthenameoftheviewthatDjangoistryingtofindanduse,butwehaven'tcreatedityet.Atthisstageyour/admin/willalsonotwork.Noworries,wewillgetthere.

IfyouwanttoknowmoreaboutDjangoURLconfs,lookattheofficialdocumentation:https://docs.djangoproject.com/en/1.9/topics/http/urls/

Djangourls

75

Page 76: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Djangoviews-timetocreate!Timetogetridofthebugwecreatedinthelastchapter:)

Aviewisaplacewhereweputthe"logic"ofourapplication.Itwillrequestinformationfromthemodelyoucreatedbeforeandpassittoatemplate.We'llcreateatemplateinthenextchapter.ViewsarejustPythonfunctionsthatarealittlebitmorecomplicatedthantheoneswewroteintheIntroductiontoPythonchapter.

Viewsareplacedintheviews.pyfile.Wewilladdourviewstotheblog/views.pyfile.

blog/views.pyOK,let'sopenupthisfileandseewhat'sinthere:

blog/views.py

fromdjango.shortcutsimportrender

#Createyourviewshere.

Nottoomuchstuffhereyet.

Rememberthatlinesstartingwith#arecommentsandthoselineswon'tberunbyPython.

Thesimplestviewcanlooklikethis.

blog/views.py

defpost_list(request):

returnrender(request,'blog/post_list.html',{})

Asyoucansee,wecreatedafunction(def)calledpost_listthattakesrequestandreturnafunctionrenderthatwillrender(puttogether)ourtemplateblog/post_list.html.

Savethefile,gotohttp://127.0.0.1:8000/andseewhatwehavegot.

Anothererror!Readwhat'sgoingonnow:

Thisshowsthattheserverisrunningagain,atleast,butitstilldoesn'tlookright,doesit?Don'tworry,it'sjustanerrorpage,nothingtobescaredof!Justliketheerrormessagesintheconsole,theseareactuallyprettyuseful.YoucanreadthattheTemplateDoesNotExist.Let'sfixthisbugandcreateatemplateinthenextchapter!

Djangoviews-timetocreate!

76

Page 77: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

LearnmoreaboutDjangoviewsbyreadingtheofficialdocumentation:https://docs.djangoproject.com/en/1.9/topics/http/views/

Djangoviews-timetocreate!

77

Page 78: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

IntroductiontoHTMLWhat'satemplate,youmayask?

Atemplateisafilethatwecanre-usetopresentdifferentinformationinaconsistentformat-forexample,youcoulduseatemplatetohelpyouwritealetter,becausealthougheachlettermightcontainadifferentmessageandbeaddressedtoadifferentperson,theywillsharethesameformat.

ADjangotemplate'sformatisdescribedinalanguagecalledHTML(that'stheHTMLwementionedinthefirstchapterHowtheInternetworks).

WhatisHTML?HTMLisasimplecodethatisinterpretedbyyourwebbrowser-suchasChrome,FirefoxorSafari-todisplayawebpagefortheuser.

HTMLstandsfor"HyperTextMarkupLanguage".HyperTextmeansit'satypeoftextthatsupportshyperlinksbetweenpages.Markupmeanswehavetakenadocumentandmarkeditupwithcodetotellsomething(inthiscase,abrowser)howtointerpretthepage.HTMLcodeisbuiltwithtags,eachonestartingwith<andendingwith>.Thesetagsrepresentmarkupelements.

Yourfirsttemplate!Creatingatemplatemeanscreatingatemplatefile.Everythingisafile,right?Youhaveprobablynoticedthisalready.

Templatesaresavedinblog/templates/blogdirectory.Sofirstcreateadirectorycalledtemplatesinsideyourblogdirectory.Thencreateanotherdirectorycalledbloginsideyourtemplatesdirectory:

blog

└───templates

└───blog

(Youmightwonderwhyweneedtwodirectoriesbothcalledblog-asyouwilldiscoverlater,thisissimplyausefulnamingconventionthatmakeslifeeasierwhenthingsstarttogetmorecomplicated.)

Andnowcreateapost_list.htmlfile(justleaveitblankfornow)insidetheblog/templates/blogdirectory.

Seehowyourwebsitelooksnow:http://127.0.0.1:8000/

IfyoustillhaveanerrorTemplateDoesNotExist,trytorestartyourserver.Gointocommandline,stoptheserverbypressingCtrl+C(ControlandCbuttonstogether)andstartitagainbyrunningapythonmanage.pyrunservercommand.

IntroductiontoHTML

78

Page 79: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Noerroranymore!Congratulations:)However,yourwebsiteisn'tactuallypublishinganythingexceptanemptypage,becauseyourtemplateisemptytoo.Weneedtofixthat.

Addthefollowingtoyourtemplatefile:

blog/templates/blog/post_list.html

<html>

<p>Hithere!</p>

<p>Itworks!</p>

</html>

Sohowdoesyourwebsitelooknow?Clicktofindout:http://127.0.0.1:8000/

Itworked!Niceworkthere:)

Themostbasictag,<html>,isalwaysthebeginningofanywebpageand</html>isalwaystheend.Asyoucansee,thewholecontentofthewebsitegoesbetweenthebeginningtag<html>andclosingtag</html><p>isatagforparagraphelements;</p>closeseachparagraph

Head&bodyEachHTMLpageisalsodividedintotwoelements:headandbody.

headisanelementthatcontainsinformationaboutthedocumentthatisnotdisplayedonthescreen.

bodyisanelementthatcontainseverythingelsethatisdisplayedaspartofthewebpage.

Weuse<head>totellthebrowserabouttheconfigurationofthepage,and<body>totellitwhat'sactuallyonthepage.

Forexample,youcanputawebpagetitleelementinsidethe<head>,likethis:

blog/templates/blog/post_list.html

IntroductiontoHTML

79

Page 80: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

<html>

<head>

<title>Ola'sblog</title>

</head>

<body>

<p>Hithere!</p>

<p>Itworks!</p>

</body>

</html>

Savethefileandrefreshyourpage.

Noticehowthebrowserhasunderstoodthat"Ola'sblog"isthetitleofyourpage?Ithasinterpreted<title>Ola'sblog</title>andplacedthetextinthetitlebarofyourbrowser(itwillalsobeusedforbookmarksandsoon).

Probablyyouhavealsonoticedthateachopeningtagismatchedbyaclosingtag,witha/,andthatelementsarenested(i.e.youcan'tcloseaparticulartaguntilalltheonesthatwereinsideithavebeenclosedtoo).

It'slikeputtingthingsintoboxes.Youhaveonebigbox,<html></html>;insideitthereis<body></body>,andthatcontainsstillsmallerboxes:<p></p>.

Youneedtofollowtheserulesofclosingtags,andofnestingelements-ifyoudon't,thebrowsermaynotbeabletointerpretthemproperlyandyourpagewilldisplayincorrectly.

CustomizeyourtemplateYoucannowhavealittlefunandtrytocustomizeyourtemplate!Hereareafewusefultagsforthat:

<h1>Aheading</h1>-foryourmostimportantheading<h2>Asub-heading</h2>foraheadingatthenextlevel<h3>Asub-sub-heading</h3>...andsoon,upto<h6><p>Aparagraphoftext</p>

<em>text</em>emphasizesyourtext<strong>text</strong>stronglyemphasizesyourtext<br/>goestoanotherline(youcan'tputanythinginsidebr)<ahref="https://djangogirls.org">link</a>createsalink<ul><li>firstitem</li><li>seconditem</li></ul>makesalist,justlikethisone!<div></div>definesasectionofthepage

Here'sanexampleofafulltemplate:

blog/templates/blog/post_list.html

IntroductiontoHTML

80

Page 81: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

<html>

<head>

<title>DjangoGirlsblog</title>

</head>

<body>

<div>

<h1><ahref="">DjangoGirlsBlog</a></h1>

</div>

<div>

<p>published:14.06.2014,12:14</p>

<h2><ahref="">Myfirstpost</a></h2>

<p>Aeneaneuleoquam.Pellentesqueornaresemlaciniaquamvenenatisvestibulum.Donecidelitnonmipo

rtagravidaategetmetus.Fuscedapibus,tellusaccursuscommodo,tortormauriscondimentumnibh,utfermentummass

ajustositametrisus.</p>

</div>

<div>

<p>published:14.06.2014,12:14</p>

<h2><ahref="">Mysecondpost</a></h2>

<p>Aeneaneuleoquam.Pellentesqueornaresemlaciniaquamvenenatisvestibulum.Donecidelitnonmipo

rtagravidaategetmetus.Fuscedapibus,tellusaccursuscommodo,tortormauriscondimentumnibh,utf.</p>

</div>

</body>

</html>

We'vecreatedthreedivsectionshere.

Thefirstdivelementcontainsthetitleofourblog-it'saheadingandalinkAnothertwodivelementscontainourblogpostswithapublisheddate,h2withaposttitlethatisclickableandtwops(paragraph)oftext,oneforthedateandoneforourblogpost.

Itgivesusthiseffect:

Yaaay!Butsofar,ourtemplateonlyeverdisplaysexactlythesameinformation-whereasearlierweweretalkingabouttemplatesasallowingustodisplaydifferentinformationinthesameformat.

IntroductiontoHTML

81

Page 82: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

WhatwereallywanttodoisdisplayrealpostsaddedinourDjangoadmin-andthat'swherewe'regoingnext.

Onemorething:deploy!It'dbegoodtoseeallthisoutandliveontheInternet,right?Let'sdoanotherPythonAnywheredeploy:

Commit,andpushyourcodeuptoGithub

Firstoff,let'sseewhatfileshavechangedsincewelastdeployed(runthesecommandslocally,notonPythonAnywhere):

command-line

$gitstatus

Makesureyou'reinthedjangogirlsdirectoryandlet'stellgittoincludeallthechangeswithinthisdirectory:

command-line

$gitadd--all.

--allmeansthatgitwillalsorecognizeifyou'vedeletedfiles(bydefault,itonlyrecognizesnew/modifiedfiles).Alsoremember(fromchapter3)that.meansthecurrentdirectory.

Beforeweuploadallthefiles,let'scheckwhatgitwillbeuploading(allthefilesthatgitwilluploadshouldnowappearingreen):

command-line

$gitstatus

We'realmostthere,nowit'stimetotellittosavethischangeinitshistory.We'regoingtogiveita"commitmessage"wherewedescribewhatwe'vechanged.Youcantypeanythingyou'dlikeatthisstage,butit'shelpfultotypesomethingdescriptivesothatyoucanrememberwhatyou'vedoneinthefuture.

command-line

$gitcommit-m"ChangedtheHTMLforthesite."

Makesureyouusedoublequotesaroundthecommitmessage.

Oncewe'vedonethat,weupload(push)ourchangesuptoGithub:

command-line

$gitpush

PullyournewcodedowntoPythonAnywhere,andreloadyourwebapp

OpenupthePythonAnywhereconsolespageandgotoyourBashconsole(orstartanewone).Then,run:

command-line

$cd~/my-first-blog

$gitpull

[...]

IntroductiontoHTML

82

Page 83: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Andwatchyourcodegetdownloaded.Ifyouwanttocheckthatit'sarrived,youcanhopovertotheFilestabandviewyourcodeonPythonAnywhere.

Finally,hoponovertotheWebtabandhitReloadonyourwebapp.

Yourupdateshouldbelive!Goaheadandrefreshyourwebsiteinthebrowser.Changesshouldbevisible:)

IntroductiontoHTML

83

Page 84: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

DjangoORMandQuerySetsInthischapteryou'lllearnhowDjangoconnectstothedatabaseandstoresdatainit.Let'sdivein!

WhatisaQuerySet?AQuerySetis,inessence,alistofobjectsofagivenModel.QuerySetallowsyoutoreadthedatafromthedatabase,filteritandorderit.

It'seasiesttolearnbyexample.Let'strythis,shallwe?

DjangoshellOpenupyourlocalconsole(notonPythonAnywhere)andtypethiscommand:

command-line

(myvenv)~/djangogirls$pythonmanage.pyshell

Theeffectshouldbelikethis:

command-line

(InteractiveConsole)

>>>

You'renowinDjango'sinteractiveconsole.It'sjustlikePythonpromptbutwithsomeadditionalDjangomagic:).YoucanuseallthePythoncommandsheretoo,ofcourse.

AllobjectsLet'strytodisplayallofourpostsfirst.Youcandothatwiththefollowingcommand:

command-line

>>>Post.objects.all()

Traceback(mostrecentcalllast):

File"<console>",line1,in<module>

NameError:name'Post'isnotdefined

Oops!Anerrorshowedup.IttellsusthatthereisnoPost.It'scorrect--weforgottoimportitfirst!

command-line

>>>fromblog.modelsimportPost

Thisissimple:weimportmodelPostfromblog.models.Let'strydisplayingallpostsagain:

command-line

>>>Post.objects.all()

[<Post:myposttitle>,<Post:anotherposttitle>]

DjangoORM(Querysets)

84

Page 85: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

It'salistofthepostswecreatedearlier!WecreatedthesepostsusingtheDjangoadmininterface.But,nowwewanttocreatenewpostsusingPython,sohowdowedothat?

Createobject

ThisishowyoucreateanewPostobjectindatabase:

command-line

>>>Post.objects.create(author=me,title='Sampletitle',text='Test')

Butwehaveonemissingingredienthere:me.WeneedtopassaninstanceofUsermodelasanauthor.Howtodothat?

Let'simportUsermodelfirst:

command-line

>>>fromdjango.contrib.auth.modelsimportUser

Whatusersdowehaveinourdatabase?Trythis:

command-line

>>>User.objects.all()

[<User:ola>]

It'sthesuperuserwecreatedearlier!Let'sgetaninstanceoftheusernow:

command-line

me=User.objects.get(username='ola')

Asyoucansee,wenowgetaUserwithausernamethatequalsto'ola'.Neat!Ofcourse,youhavetoadjustittoyourusername.

Nowwecanfinallycreateourpost:

command-line

>>>Post.objects.create(author=me,title='Sampletitle',text='Test')

Hurray!Wannacheckifitworked?

command-line

>>>Post.objects.all()

[<Post:myposttitle>,<Post:anotherposttitle>,<Post:Sampletitle>]

Thereitis,onemorepostinthelist!

Addmoreposts

Youcannowhavealittlefunandaddmorepoststoseehowitworks.Add2-3moreandgoaheadtothenextpart.

Filterobjects

DjangoORM(Querysets)

85

Page 86: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

AbigpartofQuerySetsisanabilitytofilterthem.Let'ssay,wewanttofindallpostsUserolaauthored.WewillusefilterinsteadofallinPost.objects.all().Inparentheseswewillstatewhatcondition(s)ablogpostneedstomeettoendupinourqueryset.Inoursituationitisauthorthatisequaltome.ThewaytowriteitinDjangois:author=me.Nowourpieceofcodelookslikethis:

command-line

>>>Post.objects.filter(author=me)

[<Post:Sampletitle>,<Post:Postnumber2>,<Post:My3rdpost!>,<Post:4thtitleofpost>]

Ormaybewewanttoseeallthepoststhatcontainaword'title'inthetitlefield?

command-line

>>>Post.objects.filter(title__contains='title')

[<Post:Sampletitle>,<Post:4thtitleofpost>]

Therearetwounderscorecharacters(_)betweentitleandcontains.Django'sORMusesthisruletoseparatefieldnames("title")andoperationsorfilters("contains").Ifyouonlyuseoneunderscore,you'llgetanerrorlike"FieldError:Cannotresolvekeywordtitle_contains".

Youcanalsogetalistofallpublishedposts.Wedoitbyfilteringallthepoststhathavepublished_datesetinthepast:

command-line

>>>fromdjango.utilsimporttimezone

>>>Post.objects.filter(published_date__lte=timezone.now())

[]

Unfortunately,thepostweaddedfromthePythonconsoleisnotpublishedyet.Wecanchangethat!Firstgetaninstanceofapostwewanttopublish:

command-line

>>>post=Post.objects.get(title="Sampletitle")

Andthenpublishitwithourpublishmethod!

command-line

>>>post.publish()

Nowtrytogetlistofpublishedpostsagain(presstheuparrowbutton3timesandhitenter):

command-line

>>>Post.objects.filter(published_date__lte=timezone.now())

[<Post:Sampletitle>]

Orderingobjects

QuerySetsalsoallowyoutoorderthelistofobjects.Let'strytoorderthembycreated_datefield:

command-line

>>>Post.objects.order_by('created_date')

[<Post:Sampletitle>,<Post:Postnumber2>,<Post:My3rdpost!>,<Post:4thtitleofpost>]

DjangoORM(Querysets)

86

Page 87: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Wecanalsoreversetheorderingbyadding-atthebeginning:

command-line

>>>Post.objects.order_by('-created_date')

[<Post:4thtitleofpost>,<Post:My3rdpost!>,<Post:Postnumber2>,<Post:Sampletitle>]

ChainingQuerySets

YoucanalsocombineQuerySetsbychainingthemtogether:

>>>Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')

Thisisreallypowerfulandletsyouwritequitecomplexqueries.

Cool!You'renowreadyforthenextpart!Toclosetheshell,typethis:

command-line

>>>exit()

$

DjangoORM(Querysets)

87

Page 88: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

DynamicdataintemplatesWehavedifferentpiecesinplace:thePostmodelisdefinedinmodels.py,wehavepost_listinviews.pyandthetemplateadded.ButhowwillweactuallymakeourpostsappearinourHTMLtemplate?Becausethatiswhatwewanttodo.Takesomecontent(modelssavedinthedatabase)anddisplayitnicelyinourtemplate,right?

Thisisexactlywhatviewsaresupposedtodo:connectmodelsandtemplates.Inourpost_listviewwewillneedtotakemodelswewanttodisplayandpassthemtothetemplate.Inaviewwedecidewhat(model)willbedisplayedinatemplate.

OK,sohowwillweachieveit?

Weneedtoopenourblog/views.py.Sofarpost_listviewlookslikethis:

blog/views.py

fromdjango.shortcutsimportrender

defpost_list(request):

returnrender(request,'blog/post_list.html',{})

Rememberwhenwetalkedaboutincludingcodewrittenindifferentfiles?Nowitisthemomentwhenwehavetoincludethemodelwehavewritteninmodels.py.Wewilladdthislinefrom.modelsimportPostlikethis:

blog/views.py

fromdjango.shortcutsimportrender

from.modelsimportPost

Thedotbeforemodelsmeanscurrentdirectoryorcurrentapplication.Bothviews.pyandmodels.pyareinthesamedirectory.Thismeanswecanuse.andthenameofthefile(without.py).Thenweimportthenameofthemodel(Post).

Butwhat'snext?TotakeactualblogpostsfromPostmodelweneedsomethingcalledQuerySet.

QuerySetYoushouldalreadybefamiliarwithhowQuerySetswork.WetalkedaboutitinDjangoORM(QuerySets)chapter.

Sonowwewantpublishedblogpostssortedbypublished_date,right?WealreadydidthatinQuerySetschapter!

blog/views.py

Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')

Nowweputthispieceofcodeinsidetheblog/views.pyfilebyaddingittothefunctiondefpost_list(request):

blog/views.py

fromdjango.shortcutsimportrender

fromdjango.utilsimporttimezone

from.modelsimportPost

defpost_list(request):

posts=Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')

returnrender(request,'blog/post_list.html',{})

Dynamicdataintemplates

88

Page 89: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

PleasenotethatwecreateavariableforourQuerySet:posts.TreatthisasthenameofourQuerySet.Fromnowonwecanrefertoitbythisname.

Also,thecodeusesthetimezone.now()function,soweneedtoaddanimportfortimezone.

ThelastmissingpartispassingthepostsQuerySettothetemplate.Don'tworrywewillcoverhowtodisplayitinanextchapter.

Intherenderfunctionwealreadyhaveparameterwithrequest(soeverythingwereceivefromtheuserviatheInternet)andatemplatefile'blog/post_list.html'.Thelastparameter,whichlookslikethis:{}isaplaceinwhichwecanaddsomethingsforthetemplatetouse.Weneedtogivethemnames(wewillstickto'posts'rightnow:)).Itshouldlooklikethis:{'posts':posts}.Pleasenotethatthepartbefore:isastring;youneedtowrapitwithquotes''.

Sofinallyourblog/views.pyfileshouldlooklikethis:

blog/views.py

fromdjango.shortcutsimportrender

fromdjango.utilsimporttimezone

from.modelsimportPost

defpost_list(request):

posts=Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')

returnrender(request,'blog/post_list.html',{'posts':posts})

That'sit!TimetogobacktoourtemplateanddisplaythisQuerySet!

WanttoreadalittlebitmoreaboutQuerySetsinDjango?Youshouldlookhere:https://docs.djangoproject.com/en/1.9/ref/models/querysets/

Dynamicdataintemplates

89

Page 90: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

DjangotemplatesTimetodisplaysomedata!Djangogivesussomehelpfulbuilt-intemplatetagsforthat.

Whataretemplatetags?Yousee,inHTML,youcan'treallywritePythoncode,becausebrowsersdon'tunderstandit.TheyonlyknowHTML.WeknowthatHTMLisratherstatic,whilePythonismuchmoredynamic.

DjangotemplatetagsallowustotransferPython-likethingsintoHTML,soyoucanbuilddynamicwebsitesfasterandeasier.Yikes!

DisplaypostlisttemplateInthepreviouschapterwegaveourtemplatealistofpostsinthepostsvariable.NowwewilldisplayitinHTML.

ToprintavariableinDjangotemplates,weusedoublecurlybracketswiththevariable'snameinside,likethis:

blog/templates/blog/post_list.html

{{posts}}

Trythisinyourblog/templates/blog/post_list.htmltemplate.Replaceeverythingfromthesecond<div>tothethird</div>with{{posts}}.Savethefile,andrefreshthepagetoseetheresults:

Asyoucansee,allwe'vegotisthis:

blog/templates/blog/post_list.html

[<Post:Mysecondpost>,<Post:Myfirstpost>]

ThismeansthatDjangounderstandsitasalistofobjects.RememberfromIntroductiontoPythonhowwecandisplaylists?Yes,withforloops!InaDjangotemplateyoudothemlikethis:

blog/templates/blog/post_list.html

{%forpostinposts%}

{{post}}

{%endfor%}

Trythisinyourtemplate.

Djangotemplates

90

Page 91: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Itworks!ButwewantthemtobedisplayedlikethestaticpostswecreatedearlierintheIntroductiontoHTMLchapter.YoucanmixHTMLandtemplatetags.Ourbodywilllooklikethis:

blog/templates/blog/post_list.html

<div>

<h1><ahref="/">DjangoGirlsBlog</a></h1>

</div>

{%forpostinposts%}

<div>

<p>published:{{post.published_date}}</p>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaksbr}}</p>

</div>

{%endfor%}

Everythingyouputbetween{%for%}and{%endfor%}willberepeatedforeachobjectinthelist.Refreshyourpage:

Haveyounoticedthatweusedaslightlydifferentnotationthistime{{post.title}}or{{post.text}}?WeareaccessingdataineachofthefieldsdefinedinourPostmodel.Alsothe|linebreaksbrispipingtheposts'textthroughafiltertoconvertline-breaksintoparagraphs.

Djangotemplates

91

Page 92: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

OnemorethingIt'dbegoodtoseeifyourwebsitewillstillbeworkingonthepublicInternet,right?Let'strydeployingtoPythonAnywhereagain.Here'sarecapofthesteps...

First,pushyourcodetoGithub

command-line

$gitstatus

[...]

$gitadd--all.

$gitstatus

[...]

$gitcommit-m"Modifiedtemplatestodisplaypostsfromdatabase."

[...]

$gitpush

Then,logbackintoPythonAnywhereandgotoyourBashconsole(orstartanewone),andrun:

command-line

$cdmy-first-blog

$gitpull

[...]

Finally,hoponovertotheWebtabandhitReloadonyourwebapp.Yourupdateshouldbelive!IftheblogpostsonyourPythonAnywheresitedon'tmatchthepostsappearingonthebloghostedonyourlocalserver-that'sOK.ThedatabasesonyourlocalcomputerandPythonAnywheredon'tsyncwiththerestofyourfiles.

Congrats!NowgoaheadandtryaddinganewpostinyourDjangoadmin(remembertoaddpublished_date!)MakesureyouareintheDjangoadminforyourpythonanywheresite,https://yourname.pythonanywhere.com/admin.Thenrefreshyourpagetoseeifthepostappearsthere.

Workslikeacharm?We'reproud!Stepawayfromyourcomputerforabit,youhaveearnedabreak.:)

Djangotemplates

92

Page 93: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

CSS-makeitpretty!Ourblogstilllooksprettyugly,right?Timetomakeitnice!WewilluseCSSforthat.

WhatisCSS?CascadingStyleSheets(CSS)isalanguageusedfordescribingthelookandformattingofawebsitewritteninmarkuplanguage(likeHTML).Treatitasmake-upforourwebpage;).

Butwedon'twanttostartfromscratchagain,right?Oncemore,we'llusesomethingthatprogrammersreleasedontheInternetforfree.Youknow,reinventingthewheelisnofun.

Let'suseBootstrap!BootstrapisoneofthemostpopularHTMLandCSSframeworksfordevelopingbeautifulwebsites:https://getbootstrap.com/

ItwaswrittenbyprogrammerswhoworkedforTwitter.Nowit'sdevelopedbyvolunteersfromallovertheworld!

InstallBootstrapToinstallBootstrap,youneedtoaddthistoyour<head>inyour.htmlfile:

blog/templates/blog/post_list.html

<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">

<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">

Thisdoesn'taddanyfilestoyourproject.Itjustpointstofilesthatexistontheinternet.Justgoahead,openyourwebsiteandrefreshthepage.Hereitis!

Lookingniceralready!

StaticfilesinDjango

CSS-makeitpretty

93

Page 94: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Finallywewilltakeacloserlookatthesethingswe'vebeencallingstaticfiles.StaticfilesareallyourCSSandimages.Theircontentdoesn'tdependontherequestcontextandwillbethesameforeveryuser.

WheretoputstaticfilesforDjango

Djangoalreadyknowswheretofindthestaticfilesforthebuilt-in"admin"app.Nowwejustneedtoaddsomestaticfilesforourownapp,blog.

Wedothatbycreatingafoldercalledstaticinsidetheblogapp:

djangogirls

├──blog

│├──migrations

│└──static

└──mysite

Djangowillautomaticallyfindanyfolderscalled"static"insideanyofyourapps'folders.Then,itwillbeabletousetheircontentsasstaticfiles.

YourfirstCSSfile!Let'screateaCSSfilenow,toaddyourownstyletoyourweb-page.Createanewdirectorycalledcssinsideyourstaticdirectory.Thencreateanewfilecalledblog.cssinsidethiscssdirectory.Ready?

djangogirls

└───blog

└───static

└───css

└───blog.css

TimetowritesomeCSS!Openuptheblog/static/css/blog.cssfileinyourcodeeditor.

Wewon'tbegoingtoodeepintocustomizingandlearningaboutCSShere.It'sprettyeasyandyoucanlearnitonyourownafterthisworkshop.Thereisarecommendationforafreecoursetolearnmoreattheendofthispage.

Butlet'sdoatleastalittle.Maybewecouldchangethecolorofourheader?Tounderstandcolors,computersusespecialcodes.Thesecodesstartwith#followedby6letters(A-F)andnumbers(0-9).Forexample,thecodeforblueis#0000FF.Youcanfindthecolorcodesformanycolorshere:http://www.colorpicker.com/.Youmayalsousepredefinedcolors,suchasredandgreen.

Inyourblog/static/css/blog.cssfileyoushouldaddthefollowingcode:

blog/static/css/blog.css

h1a{

color:#FCA205;

}

h1aisaCSSSelector.Thismeanswe'reapplyingourstylestoanyaelementinsideofanh1element.Sowhenwehavesomethinglike:<h1><ahref="">link</a></h1>theh1astylewillapply.Inthiscase,we'retellingittochangeitscolorto#FCA205,whichisorange.Ofcourse,youcanputyourowncolorhere!

InaCSSfilewedeterminestylesforelementsintheHTMLfile.Thefirstwayweidentifyelementsiswiththeelementname.YoumightremembertheseastagsfromtheHTMLsection.Thingslikea,h1,andbodyareallexamplesofelementnames.Wealsoidentifyelementsbytheattributeclassortheattributeid.Classandidarenamesyougivetheelementbyyourself.Classesdefinegroupsofelements,andidspointtospecificelements.Forexample,youcouldidentifythefollowingtagbyusingthetagnamea,theclassexternal_link,ortheidlink_to_wiki_page:

CSS-makeitpretty

94

Page 95: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

<ahref="https://en.wikipedia.org/wiki/Django"class="external_link"id="link_to_wiki_page">

ReadaboutCSSSelectorsinw3schools.

Then,weneedtoalsotellourHTMLtemplatethatweaddedsomeCSS.Opentheblog/templates/blog/post_list.htmlfileandaddthislineattheverybeginningofit:

blog/templates/blog/post_list.html

{%loadstaticfiles%}

We'rejustloadingstaticfileshere:).Betweenthe<head>and</head>,afterthelinkstotheBootstrapCSSfilesaddthisline:

blog/templates/blog/post_list.html

<linkrel="stylesheet"href="{%static'css/blog.css'%}">

Thebrowserreadsthefilesintheorderthey'regiven,soweneedtomakesurethisisintherightplace.OtherwisethecodeinourfilemayoverridecodeinBootstrapfiles.WejusttoldourtemplatewhereourCSSfileislocated.

Yourfileshouldnowlooklikethis:

blog/templates/blog/post_list.html

{%loadstaticfiles%}

<html>

<head>

<title>DjangoGirlsblog</title>

<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">

<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">

<linkrel="stylesheet"href="{%static'css/blog.css'%}">

</head>

<body>

<div>

<h1><ahref="/">DjangoGirlsBlog</a></h1>

</div>

{%forpostinposts%}

<div>

<p>published:{{post.published_date}}</p>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaksbr}}</p>

</div>

{%endfor%}

</body>

</html>

OK,savethefileandrefreshthesite!

CSS-makeitpretty

95

Page 96: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Nicework!Maybewewouldalsoliketogiveourwebsitealittleairandincreasethemarginontheleftside?Let'strythis!

blog/static/css/blog.css

body{

padding-left:15px;

}

AddthistoyourCSS,savethefileandseehowitworks!

Maybewecancustomizethefontinourheader?Pastethisintoyour<head>inblog/templates/blog/post_list.htmlfile:

blog/templates/blog/post_list.html

<linkhref="//fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext"rel="stylesheet"type="text/css">

Asbefore,checktheorderandplacebeforethelinktoblog/static/css/blog.css.ThislinewillimportafontcalledLobsterfromGoogleFonts(https://www.google.com/fonts).

Findtheh1adeclarationblock(thecodebetweenbraces{and})intheCSSfileblog/static/css/blog.css.Nowaddthelinefont-family:'Lobster';betweenthebraces,andrefreshthepage:

blog/static/css/blog.css

CSS-makeitpretty

96

Page 97: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

h1a{

color:#FCA205;

font-family:'Lobster';

}

Great!

Asmentionedabove,CSShasaconceptofclasses.TheseallowyoutonameapartoftheHTMLcodeandapplystylesonlytothispart,withoutaffectingotherparts.Thiscanbesuperhelpful!Maybeyouhavetwodivsthataredoingsomethingdifferent(likeyourheaderandyourpost).Aclasscanhelpyoumakethemlookdifferent.

GoaheadandnamesomepartsoftheHTMLcode.Addaclasscalledpage-headertoyourdivthatcontainsyourheader,likethis:

blog/templates/blog/post_list.html

<divclass="page-header">

<h1><ahref="/">DjangoGirlsBlog</a></h1>

</div>

Andnowaddaclassposttoyourdivcontainingablogpost.

blog/templates/blog/post_list.html

<divclass="post">

<p>published:{{post.published_date}}</p>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaksbr}}</p>

</div>

Wewillnowadddeclarationblockstodifferentselectors.Selectorsstartingwith.relatetoclasses.TherearemanygreattutorialsandexplanationsaboutCSSontheWebtohelpyouunderstandthefollowingcode.Fornow,justcopyandpasteitintoyourblog/static/css/blog.cssfile:

blog/static/css/blog.css

CSS-makeitpretty

97

Page 98: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

.page-header{

background-color:#ff9400;

margin-top:0;

padding:20px20px20px40px;

}

.page-headerh1,.page-headerh1a,.page-headerh1a:visited,.page-headerh1a:active{

color:#ffffff;

font-size:36pt;

text-decoration:none;

}

.content{

margin-left:40px;

}

h1,h2,h3,h4{

font-family:'Lobster',cursive;

}

.date{

color:#828282;

}

.save{

float:right;

}

.post-formtextarea,.post-forminput{

width:100%;

}

.top-menu,.top-menu:hover,.top-menu:visited{

color:#ffffff;

float:right;

font-size:26pt;

margin-right:20px;

}

.post{

margin-bottom:70px;

}

.posth1a,.posth1a:visited{

color:#000000;

}

ThensurroundtheHTMLcodewhichdisplaysthepostswithdeclarationsofclasses.Replacethis:

blog/templates/blog/post_list.html

{%forpostinposts%}

<divclass="post">

<p>published:{{post.published_date}}</p>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaksbr}}</p>

</div>

{%endfor%}

intheblog/templates/blog/post_list.htmlwiththis:

blog/templates/blog/post_list.html

CSS-makeitpretty

98

Page 99: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

<divclass="contentcontainer">

<divclass="row">

<divclass="col-md-8">

{%forpostinposts%}

<divclass="post">

<divclass="date">

<p>published:{{post.published_date}}</p>

</div>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaksbr}}</p>

</div>

{%endfor%}

</div>

</div>

</div>

Savethosefilesandrefreshyourwebsite.

Woohoo!Looksawesome,right?LookatthecodewejustpastedtofindtheplaceswhereweaddedclassesintheHTMLandusedthemintheCSS.Wherewouldyoumakethechangeifyouwantedthedatetobeturquoise?

Don'tbeafraidtotinkerwiththisCSSalittlebitandtrytochangesomethings.PlayingwiththeCSScanhelpyouunderstandwhatthedifferentthingsaredoing.Ifyoubreaksomething,don'tworry,youcanalwaysundoit!

WereallyrecommendtakingthisfreeonlineCodeacademyHTML&CSScourse.ItcanhelpyoulearnallaboutmakingyourwebsitesprettierwithCSS.

Readyforthenextchapter?!:)

CSS-makeitpretty

99

Page 100: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

TemplateextendingAnothernicethingDjangohasforyouistemplateextending.Whatdoesthismean?ItmeansthatyoucanusethesamepartsofyourHTMLfordifferentpagesofyourwebsite.

Templateshelpwhenyouwanttousethesameinformation/layoutinmorethanoneplace.Youdon'thavetorepeatyourselfineveryfile.Andifyouwanttochangesomething,youdon'thavetodoitineverytemplate,justonce!

CreatebasetemplateAbasetemplateisthemostbasictemplatethatyouextendoneverypageofyourwebsite.

Let'screateabase.htmlfileinblog/templates/blog/:

blog

└───templates

└───blog

base.html

post_list.html

Thenopenitupandcopyeverythingfrompost_list.htmltobase.htmlfile,likethis:

blog/templates/blog/base.html

{%loadstaticfiles%}

<html>

<head>

<title>DjangoGirlsblog</title>

<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">

<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">

<linkhref='//fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext'rel='stylesheet'type='text/css'

>

<linkrel="stylesheet"href="{%static'css/blog.css'%}">

</head>

<body>

<divclass="page-header">

<h1><ahref="/">DjangoGirlsBlog</a></h1>

</div>

<divclass="contentcontainer">

<divclass="row">

<divclass="col-md-8">

{%forpostinposts%}

<divclass="post">

<divclass="date">

{{post.published_date}}

</div>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaksbr}}</p>

</div>

{%endfor%}

</div>

</div>

</div>

</body>

</html>

Theninbase.html,replaceyourwhole<body>(everythingbetween<body>and</body>)withthis:

blog/templates/blog/base.html

Templateextending

100

Page 101: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

<body>

<divclass="page-header">

<h1><ahref="/">DjangoGirlsBlog</a></h1>

</div>

<divclass="contentcontainer">

<divclass="row">

<divclass="col-md-8">

{%blockcontent%}

{%endblock%}

</div>

</div>

</div>

</body>

Youmightnoticethisreplacedeverythingfrom{%forpostinposts%}to{%endfor%}with:

blog/templates/blog/base.html

{%blockcontent%}

{%endblock%}

Butwhy?Youjustcreatedablock!Youusedthetemplatetag{%block%}tomakeanareathatwillhaveHTMLinsertedinit.ThatHTMLwillcomefromanothertemplatesthatextendsthistemplate(base.html).Wewillshowyouhowtodothisinamoment.

Nowsavebase.html,andopenyourblog/templates/blog/post_list.htmlagain.You'regoingtoremoveeverythingabove{%forpostinposts%}andbelow{%endfor%}.Whenyou'redonethefilewilllooklikethis:

blog/templates/blog/post_list.html

{%forpostinposts%}

<divclass="post">

<divclass="date">

{{post.published_date}}

</div>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaksbr}}</p>

</div>

{%endfor%}

Wewanttousethisaspartofourtemplateforallthecontentblocks.Timetoaddblocktagstothisfile!

Youwantyourblocktagtomatchthetaginyourbase.htmlfile.Youalsowantittoincludeallthecodethatbelongsinyourcontentblocks.Todothat,puteverythingbetween{%blockcontent%}and{%endblockcontent%}.Likethis:

blog/templates/blog/post_list.html

{%blockcontent%}

{%forpostinposts%}

<divclass="post">

<divclass="date">

{{post.published_date}}

</div>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaksbr}}</p>

</div>

{%endfor%}

{%endblock%}

Onlyonethingleft.Weneedtoconnectthesetwotemplatestogether.Thisiswhatextendingtemplatesisallabout!We'lldothisbyaddinganextendstagtothebeginningofthefile.Likethis:

blog/templates/blog/post_list.html

Templateextending

101

Page 102: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

{%extends'blog/base.html'%}

{%blockcontent%}

{%forpostinposts%}

<divclass="post">

<divclass="date">

{{post.published_date}}

</div>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaksbr}}</p>

</div>

{%endfor%}

{%endblock%}

That'sit!Checkifyourwebsiteisstillworkingproperly:)

IfyouhaveanerrorTemplateDoesNotExistthatsaysthatthereisnoblog/base.htmlfileandyouhaverunserverrunningintheconsole,trytostopit(bypressingCtrl+C-ControlandCbuttonstogether)andrestartitbyrunningapythonmanage.pyrunservercommand.

Templateextending

102

Page 103: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

ExtendyourapplicationWe'vealreadycompletedallthedifferentstepsnecessaryforthecreationofourwebsite:weknowhowtowriteamodel,url,viewandtemplate.Wealsoknowhowtomakeourwebsitepretty.

Timetopractice!

Thefirstthingweneedinourblogis,obviously,apagetodisplayonepost,right?

WealreadyhaveaPostmodel,sowedon'tneedtoaddanythingtomodels.py.

Createatemplatelinktoapost'sdetailWewillstartwithaddingalinkinsideblog/templates/blog/post_list.htmlfile.Sofaritshouldlooklike:

blog/templates/blog/post_list.html

{%extends'blog/base.html'%}

{%blockcontent%}

{%forpostinposts%}

<divclass="post">

<divclass="date">

{{post.published_date}}

</div>

<h1><ahref="">{{post.title}}</a></h1>

<p>{{post.text|linebreaksbr}}</p>

</div>

{%endfor%}

{%endblockcontent%}

Wewanttohavealinkfromapost'stitleinthepostlisttothepost'sdetailpage.Let'schange<h1><ahref="">{{post.title}}</a></h1>sothatitlinkstothepost'sdetailpage:

blog/templates/blog/post_list.html

<h1><ahref="{%url'post_detail'pk=post.pk%}">{{post.title}}</a></h1>

Timetoexplainthemysterious{%url'post_detail'pk=post.pk%}.Asyoumightsuspect,the{%%}notationmeansthatweareusingDjangotemplatetags.ThistimewewilluseonethatwillcreateaURLforus!

blog.views.post_detailisapathtoapost_detailviewwewanttocreate.Pleasenote:blogisthenameofourapplication(thedirectoryblog),viewsisfromthenameoftheviews.pyfileandthelastbit-post_detail-isthenameoftheview.

Nowwhenwegoto:http://127.0.0.1:8000/wewillhaveanerror(asexpected,sincewedon'thaveaURLoraviewforpost_detail).Itwilllooklikethis:

Extendyourapplication

103

Page 104: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

CreateaURLtoapost'sdetailLet'screateaURLinurls.pyforourpost_detailview!

Wewantourfirstpost'sdetailtobedisplayedatthisURL:http://127.0.0.1:8000/post/1/

Let'smakeaURLintheblog/urls.pyfiletopointDjangotoaviewnamedpost_detail,thatwillshowanentireblogpost.Addthelineurl(r'^post/(?P<pk>\d+)/$',views.post_detail,name='post_detail'),totheblog/urls.pyfile.Thefileshouldlooklikethis:

blog/urls.py

fromdjango.conf.urlsimporturl

from.importviews

urlpatterns=[

url(r'^$',views.post_list,name='post_list'),

url(r'^post/(?P<pk>\d+)/$',views.post_detail,name='post_detail'),

]

Thispart ̂ post/(?P<pk>\d+)/$looksscary,butnoworries-wewillexplainitforyou:

itstartswith ̂ again--"thebeginning"post/onlymeansthatafterthebeginning,theURLshouldcontainthewordpostand/.Sofarsogood.(?P<pk>\d+)-thispartistrickier.ItmeansthatDjangowilltakeeverythingthatyouplacehereandtransferittoaviewasavariablecalledpk.\dalsotellsusthatitcanonlybeadigit,notaletter(soeverythingbetween0and9).+meansthatthereneedstobeoneormoredigitsthere.Sosomethinglikehttp://127.0.0.1:8000/post//isnotvalid,buthttp://127.0.0.1:8000/post/1234567890/isperfectlyok!/-thenweneed/again$-"theend"!

Thatmeansifyouenterhttp://127.0.0.1:8000/post/5/intoyourbrowser,Djangowillunderstandthatyouarelookingforaviewcalledpost_detailandtransfertheinformationthatpkequals5tothatview.

pkisshortcutforprimarykey.ThisnameisoftenusedinDjangoprojects.Butyoucannameyourvariableasyoulike(remember:lowercaseand_insteadofwhitespaces!).Forexampleinsteadof(?P<pk>\d+)wecouldhavevariablepost_id,sothisbitwouldlooklike:(?P<post_id>\d+).

Ok,we'veaddedanewURLpatterntoblog/urls.py!Let'srefreshthepage:http://127.0.0.1:8000/Boom!Theserverhasstoppedrunningagain.Havealookattheconsole-asexpected,there'syetanothererror!

Extendyourapplication

104

Page 105: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Doyourememberwhatthenextstepis?Ofcourse:addingaview!

Addapost'sdetailviewThistimeourviewisgivenanextraparameterpk.Ourviewneedstocatchit,right?Sowewilldefineourfunctionasdefpost_detail(request,pk):.Notethatweneedtouseexactlythesamenameastheonewespecifiedinurls(pk).Omittingthisvariableisincorrectandwillresultinanerror!

Now,wewanttogetoneandonlyoneblogpost.Todothiswecanusequerysetslikethis:

blog/views.py

Post.objects.get(pk=pk)

Butthiscodehasaproblem.IfthereisnoPostwithgivenprimarykey(pk)wewillhaveasuperuglyerror!

Wedon'twantthat!But,ofcourse,Djangocomeswithsomethingthatwillhandlethatforus:get_object_or_404.IncasethereisnoPostwiththegivenpkitwilldisplaymuchnicerpage(calledPageNotFound404page).

Extendyourapplication

105

Page 106: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

ThegoodnewsisthatyoucanactuallycreateyourownPagenotfoundpageandmakeitasprettyasyouwant.Butit'snotsuperimportantrightnow,sowewillskipit.

Ok,timetoaddaviewtoourviews.pyfile!

Weshouldopenblog/views.pyandaddthefollowingcode:

blog/views.py

fromdjango.shortcutsimportrender,get_object_or_404

Nearotherfromlines.Andattheendofthefilewewilladdourview:

blog/views.py

defpost_detail(request,pk):

post=get_object_or_404(Post,pk=pk)

returnrender(request,'blog/post_detail.html',{'post':post})

Yes.Itistimetorefreshthepage:http://127.0.0.1:8000/

Extendyourapplication

106

Page 107: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Itworked!Butwhathappenswhenyouclickalinkinblogposttitle?

Ohno!Anothererror!Butwealreadyknowhowtodealwithit,right?Weneedtoaddatemplate!

CreateatemplateforpostdetailWewillcreateafileinblog/templates/blogcalledpost_detail.html.

Itwilllooklikethis:

blog/templates/blog/post_detail.html

Extendyourapplication

107

Page 108: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

{%extends'blog/base.html'%}

{%blockcontent%}

<divclass="post">

{%ifpost.published_date%}

<divclass="date">

{{post.published_date}}

</div>

{%endif%}

<h1>{{post.title}}</h1>

<p>{{post.text|linebreaksbr}}</p>

</div>

{%endblock%}

Onceagainweareextendingbase.html.Inthecontentblockwewanttodisplayapost'spublished_date(ifitexists),titleandtext.Butweshoulddiscusssomeimportantthings,right?

{%if...%}...{%endif%}isatemplatetagwecanusewhenwewanttochecksomething(rememberif...else..fromIntroductiontoPythonchapter?).Inthisscenariowewanttocheckifapost'spublished_dateisnotempty.

Ok,wecanrefreshourpageandseeifTemplateDoesNotExistisgonenow.

Yay!Itworks!

Onemorething:deploytime!It'dbegoodtoseeifyourwebsitewillstillbeworkingonPythonAnywhere,right?Let'strydeployingagain.

command-line

Extendyourapplication

108

Page 109: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

$gitstatus

$gitadd--all.

$gitstatus

$gitcommit-m"AddedviewandtemplatefordetailedblogpostaswellasCSSforthesite."

$gitpush

Then,inaPythonAnywhereBashconsole:

command-line

$cdmy-first-blog

$gitpull

[...]

Finally,hoponovertotheWebtabandhitReload.

Andthatshouldbeit!Congrats:)

Extendyourapplication

109

Page 110: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

DjangoFormsThefinalthingwewanttodoonourwebsiteiscreateanicewaytoaddandeditblogposts.Django'sadminiscool,butitisratherhardtocustomizeandmakepretty.Withformswewillhaveabsolutepoweroverourinterface-wecandoalmostanythingwecanimagine!

ThenicethingaboutDjangoformsisthatwecaneitherdefineonefromscratchorcreateaModelFormwhichwillsavetheresultoftheformtothemodel.

Thisisexactlywhatwewanttodo:wewillcreateaformforourPostmodel.

LikeeveryimportantpartofDjango,formshavetheirownfile:forms.py.

Weneedtocreateafilewiththisnameintheblogdirectory.

blog

└──forms.py

Ok,let'sopenitandtypethefollowingcode:

blog/forms.py

fromdjangoimportforms

from.modelsimportPost

classPostForm(forms.ModelForm):

classMeta:

model=Post

fields=('title','text',)

WeneedtoimportDjangoformsfirst(fromdjangoimportforms)and,obviously,ourPostmodel(from.modelsimportPost).

PostForm,asyouprobablysuspect,isthenameofourform.WeneedtotellDjango,thatthisformisaModelForm(soDjangowilldosomemagicforus)-forms.ModelFormisresponsibleforthat.

Next,wehaveclassMeta,wherewetellDjangowhichmodelshouldbeusedtocreatethisform(model=Post).

Finally,wecansaywhichfield(s)shouldendupinourform.Inthisscenariowewantonlytitleandtexttobeexposed-authorshouldbethepersonwhoiscurrentlyloggedin(you!)andcreated_dateshouldbeautomaticallysetwhenwecreateapost(i.einthecode),right?

Andthat'sit!Allweneedtodonowisusetheforminaviewanddisplayitinatemplate.

Soonceagainwewillcreate:alinktothepage,aURL,aviewandatemplate.

LinktoapagewiththeformIt'stimetoopenblog/templates/blog/base.html.Wewilladdalinkindivnamedpage-header:

blog/templates/blog/base.html

<ahref="{%url'post_new'%}"class="top-menu"><spanclass="glyphiconglyphicon-plus"></span></a>

Notethatwewanttocallournewviewpost_new.Theclass"glyphiconglyphicon-plus"isprovidedbythebootstrapthemeweareusing,andwilldisplayaplussignforus.

DjangoForms

110

Page 111: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Afteraddingtheline,yourhtmlfileshouldnowlooklikethis:

blog/templates/blog/base.html

{%loadstaticfiles%}

<html>

<head>

<title>DjangoGirlsblog</title>

<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">

<linkrel="stylesheet"href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">

<linkhref='//fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext'rel='stylesheet'type='text/css'

>

<linkrel="stylesheet"href="{%static'css/blog.css'%}">

</head>

<body>

<divclass="page-header">

<ahref="{%url'post_new'%}"class="top-menu"><spanclass="glyphiconglyphicon-plus"></span></a>

<h1><ahref="/">DjangoGirlsBlog</a></h1>

</div>

<divclass="contentcontainer">

<divclass="row">

<divclass="col-md-8">

{%blockcontent%}

{%endblock%}

</div>

</div>

</div>

</body>

</html>

Aftersavingandrefreshingthepagehttp://127.0.0.1:8000youwillobviouslyseeafamiliarNoReverseMatcherror,right?

URLWeopenblog/urls.pyandaddaline:

blog/urls.py

url(r'^post/new/$',views.post_new,name='post_new'),

Andthefinalcodewilllooklikethis:

blog/urls.py

fromdjango.conf.urlsimporturl

from.importviews

urlpatterns=[

url(r'^$',views.post_list,name='post_list'),

url(r'^post/(?P<pk>\d+)/$',views.post_detail,name='post_detail'),

url(r'^post/new/$',views.post_new,name='post_new'),

]

Afterrefreshingthesite,weseeanAttributeError,sincewedon'thavepost_newviewimplemented.Let'sadditrightnow.

post_newviewTimetoopentheblog/views.pyfileandaddthefollowinglineswiththerestofthefromrows:

blog/views.py

DjangoForms

111

Page 112: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

from.formsimportPostForm

andourview:

blog/views.py

defpost_new(request):

form=PostForm()

returnrender(request,'blog/post_edit.html',{'form':form})

TocreateanewPostform,weneedtocallPostForm()andpassittothetemplate.Wewillgobacktothisview,butfornow,let'screatequicklyatemplatefortheform.

TemplateWeneedtocreateafilepost_edit.htmlintheblog/templates/blogdirectory.Tomakeaformworkweneedseveralthings:

wehavetodisplaytheform.Wecandothatforexamplewithasimple{%raw%}{{form.as_p}}{%endraw%}.thelineaboveneedstobewrappedwithanHTMLformtag:<formmethod="POST">...</form>weneedaSavebutton.WedothatwithanHTMLbutton:<buttontype="submit">Save</button>andfinallyjustaftertheopening<form...>tagweneedtoadd{%raw%}{%csrf_token%}{%endraw%}.Thisisveryimportant,sinceitmakesyourformssecure!Djangowillcomplainifyouforgetaboutthisbitifyoutrytosavetheform:

Ok,solet'sseehowtheHTMLinpost_edit.htmlshouldlook:

blog/templates/blog/post_edit.html

{%extends'blog/base.html'%}

{%blockcontent%}

<h1>Newpost</h1>

<formmethod="POST"class="post-form">{%csrf_token%}

{{form.as_p}}

<buttontype="submit"class="savebtnbtn-default">Save</button>

</form>

{%endblock%}

Timetorefresh!Yay!Yourformisdisplayed!

DjangoForms

112

Page 113: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

But,waitaminute!Whenyoutypesomethingintitleandtextfieldsandtrytosaveit-whatwillhappen?

Nothing!Weareonceagainonthesamepageandourtextisgone...andnonewpostisadded.Sowhatwentwrong?

Theansweris:nothing.Weneedtodoalittlebitmoreworkinourview.

SavingtheformOpenblog/views.pyonceagain.Currentlyallwehaveinthepost_newviewis:

blog/views.py

defpost_new(request):

form=PostForm()

returnrender(request,'blog/post_edit.html',{'form':form})

Whenwesubmittheform,wearebroughtbacktothesameview,butthistimewehavesomemoredatainrequest,morespecificallyinrequest.POST(thenaminghasnothingtodowithablog"post",it'stodowiththefactthatwe're"posting"data).RememberthatintheHTMLfileour<form>definitionhadthevariablemethod="POST"?Allthefieldsfromtheformarenowinrequest.POST.YoushouldnotrenamePOSTtoanythingelse(theonlyothervalidvalueformethodisGET,butwehavenotimetoexplainwhatthedifferenceis).

Soinourviewwehavetwoseparatesituationstohandle.First:whenweaccessthepageforthefirsttimeandwewantablankform.Second:whenwegobacktotheviewwithallform'sdatawejusttyped.Soweneedtoaddacondition(wewilluseifforthat).

blog/views.py

DjangoForms

113

Page 114: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

ifrequest.method=="POST":

[...]

else:

form=PostForm()

It'stimetofillinthedots[...].IfmethodisPOSTthenwewanttoconstructthePostFormwithdatafromtheform,right?Wewilldothatwith:

blog/views.py

form=PostForm(request.POST)

Easy!Nextthingistocheckiftheformiscorrect(allrequiredfieldsaresetandnoincorrectvalueswillbesaved).Wedothatwithform.is_valid().

Wecheckiftheformisvalidandifso,wecansaveit!

blog/views.py

ifform.is_valid():

post=form.save(commit=False)

post.author=request.user

post.published_date=timezone.now()

post.save()

Basically,wehavetwothingshere:wesavetheformwithform.saveandweaddanauthor(sincetherewasnoauthorfieldinthePostFormandthisfieldisrequired!).commit=Falsemeansthatwedon'twanttosavePostmodelyet-wewanttoaddauthorfirst.Mostofthetimeyouwilluseform.save(),withoutcommit=False,butinthiscase,weneedtodothat.post.save()willpreservechanges(addingauthor)andanewblogpostiscreated!

Finally,itwouldbeawesomeifwecanimmediatelygotopost_detailpagefornewlycreatedblogpost,right?Todothatweneedonemoreimport:

blog/views.py

fromdjango.shortcutsimportredirect

Additattheverybeginningofyourfile.Andnowwecansay:gotopost_detailpageforanewlycreatedpost.

blog/views.py

returnredirect('post_detail',pk=post.pk)

post_detailisthenameoftheviewwewanttogoto.Rememberthatthisviewrequiresapkvariable?Topassittotheviewsweusepk=post.pk,wherepostisthenewlycreatedblogpost!

Ok,wetalkedalot,butweprobablywanttoseewhatthewholeviewlookslikenow,right?

blog/views.py

DjangoForms

114

Page 115: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

defpost_new(request):

ifrequest.method=="POST":

form=PostForm(request.POST)

ifform.is_valid():

post=form.save(commit=False)

post.author=request.user

post.published_date=timezone.now()

post.save()

returnredirect('post_detail',pk=post.pk)

else:

form=PostForm()

returnrender(request,'blog/post_edit.html',{'form':form})

Let'sseeifitworks.Gotothepagehttp://127.0.0.1:8000/post/new/,addatitleandtext,saveit...andvoilà!Thenewblogpostisaddedandweareredirectedtopost_detailpage!

Youmighthavenoticedthatwearesettingpublishdatebeforesavingthepost.Lateron,wewillintroduceapublishbuttoninDjangoGirlsTutorial:Extensions.

Thatisawesome!

AswehaverecentlyusedtheDjangoadmininterfacethesystemcurrentlythinksweareloggedin.Thereareafewsituationsthatcouldleadtousbeingloggedout(closingthebrowser,restartingtheDBetc.).Ifyoufindthatyouaregettingerrorscreatingapostreferringtoalackofaloggedinuser,headtotheadminpagehttp://127.0.0.1:8000/adminandloginagain.Thiswillfixtheissuetemporarily.ThereisapermanentfixawaitingyouintheHomework:addsecuritytoyourwebsite!chapterafterthemaintutorial.

FormvalidationNow,wewillshowyouhowcoolDjangoformsare.Ablogpostneedstohavetitleandtextfields.InourPostmodelwedidnotsay(asopposedtopublished_date)thatthesefieldsarenotrequired,soDjango,bydefault,expectsthemtobeset.

Trytosavetheformwithouttitleandtext.Guess,whatwillhappen!

DjangoForms

115

Page 116: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Djangoistakingcareofvalidatingthatallthefieldsinourformarecorrect.Isn'titawesome?

EditformNowweknowhowtoaddanewform.Butwhatifwewanttoeditanexistingone?Itisverysimilartowhatwejustdid.Let'screatesomeimportantthingsquickly(ifyoudon'tunderstandsomething,youshouldaskyourcoachorlookatthepreviouschapters,sincewecoveredallthesestepsalready).

Openblog/templates/blog/post_detail.htmlandaddthisline:

blog/templates/blog/post_detail.html

<aclass="btnbtn-default"href="{%url'post_edit'pk=post.pk%}"><spanclass="glyphiconglyphicon-pencil"></span></a

>

sothatthetemplatewilllooklike:

blog/templates/blog/post_detail.html

DjangoForms

116

Page 117: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

{%extends'blog/base.html'%}

{%blockcontent%}

<divclass="post">

{%ifpost.published_date%}

<divclass="date">

{{post.published_date}}

</div>

{%endif%}

<aclass="btnbtn-default"href="{%url'post_edit'pk=post.pk%}"><spanclass="glyphiconglyphicon-pencil"></

span></a>

<h1>{{post.title}}</h1>

<p>{{post.text|linebreaksbr}}</p>

</div>

{%endblock%}

Inblog/urls.pyweaddthisline:

blog/urls.py

url(r'^post/(?P<pk>\d+)/edit/$',views.post_edit,name='post_edit'),

Wewillreusethetemplateblog/templates/blog/post_edit.html,sothelastmissingthingisaview.

Let'sopenablog/views.pyandaddattheveryendofthefile:

blog/views.py

defpost_edit(request,pk):

post=get_object_or_404(Post,pk=pk)

ifrequest.method=="POST":

form=PostForm(request.POST,instance=post)

ifform.is_valid():

post=form.save(commit=False)

post.author=request.user

post.published_date=timezone.now()

post.save()

returnredirect('post_detail',pk=post.pk)

else:

form=PostForm(instance=post)

returnrender(request,'blog/post_edit.html',{'form':form})

Thislooksalmostexactlythesameasourpost_newview,right?Butnotentirely.Firstthing:wepassanextrapkparameterfromurls.Next:wegetthePostmodelwewanttoeditwithget_object_or_404(Post,pk=pk)andthen,whenwecreateaformwepassthispostasaninstancebothwhenwesavetheform:

blog/views.py

form=PostForm(request.POST,instance=post)

andwhenwejustopenedaformwiththisposttoedit:

blog/views.py

form=PostForm(instance=post)

Ok,let'stestifitworks!Let'sgotopost_detailpage.Thereshouldbeaneditbuttoninthetop-rightcorner:

DjangoForms

117

Page 118: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

Whenyouclickityouwillseetheformwithourblogpost:

Feelfreetochangethetitleorthetextandsavechanges!

Congratulations!Yourapplicationisgettingmoreandmorecomplete!

IfyouneedmoreinformationaboutDjangoformsyoushouldreadthedocumentation:https://docs.djangoproject.com/en/1.9/topics/forms/

DjangoForms

118

Page 119: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

SecurityBeingabletocreatenewpostsjustbyclickingalinkisawesome!But,rightnow,anyonethatvisitsyoursitewillbeabletopostanewblogpostandthat'sprobablynotsomethingyouwant.Let'smakeitsothebuttonshowsupforyoubutnotforanyoneelse.

Inblog/templates/blog/base.html,findourpage-headerdivandtheanchortagyouputinthereearlier.Itshouldlooklikethis:

blog/templates/blog/base.html

<ahref="{%url'post_new'%}"class="top-menu"><spanclass="glyphiconglyphicon-plus"></span></a>

We'regoingtoaddanother{%if%}tagtothiswhichwillmakethelinkonlyshowupforusersthatareloggedintotheadmin.Rightnow,that'sjustyou!Changethe<a>tagtolooklikethis:

blog/templates/blog/base.html

{%ifuser.is_authenticated%}

<ahref="{%url'post_new'%}"class="top-menu"><spanclass="glyphiconglyphicon-plus"></span></a>

{%endif%}

This{%if%}willcausethelinktoonlybesenttothebrowseriftheuserrequestingthepageisloggedin.Thisdoesn'tprotectthecreationofnewpostscompletely,butit'sagoodfirststep.We'llcovermoresecurityintheextensionlessons.

Remembertheediticonwejustaddedtoourdetailpage?Wealsowanttoaddthesamechangethere,sootherpeoplewon'tbeabletoeditexistingposts.

Openblog/templates/blog/post_detail.htmlandfind:

blog/templates/blog/post_detail.html

<aclass="btnbtn-default"href="{%url'post_edit'pk=post.pk%}"><spanclass="glyphiconglyphicon-pencil"></span></a

>

Changeitto:

blog/templates/blog/post_detail.html

{%ifuser.is_authenticated%}

<aclass="btnbtn-default"href="{%url'post_edit'pk=post.pk%}"><spanclass="glyphiconglyphicon-pencil"></sp

an></a>

{%endif%}

Sinceyou'relikelyloggedin,ifyourefreshthepage,youwon'tseeanythingdifferent.Loadthepageinanewbrowseroranincognitowindow,though,andyou'llseethatthelinkdoesn'tshowup,andtheicondoesn'tdisplayeither!

Onemorething:deploytime!Let'sseeifallthisworksonPythonAnywhere.Timeforanotherdeploy!

First,commityournewcode,andpushituptoGithub

command-line

DjangoForms

119

Page 120: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

$gitstatus

$gitadd--all.

$gitstatus

$gitcommit-m"Addedviewstocreate/editblogpostinsidethesite."

$gitpush

Then,inaPythonAnywhereBashconsole:

command-line

$cdmy-first-blog

$gitpull

[...]

Finally,hoponovertotheWebtabandhitReload.

Andthatshouldbeit!Congrats:)

DjangoForms

120

Page 121: Table of Contents - bedford-computing.co.ukbedford-computing.co.uk/learning/wp-content/... · Verify the installation was successful by opening the Terminal application and running

What'snext?Congratulateyourself!You'retotallyawesome.We'reproud!<3

Whattodonow?

Takeabreakandrelax.Youhavejustdonesomethingreallyhuge.

Afterthatmakesureto:

FollowDjangoGirlsonFacebookorTwittertostayuptodate

Canyourecommendanyfurtherresources?Yes!First,goaheadandtryourotherbook,calledDjangoGirlsTutorial:Extensions.

Lateron,youcantrytheresourceslistedbelow.They'reallveryrecommended!

Django'sofficialtutorialNewCodertutorialsCodeAcademyPythoncourseCodeAcademyHTML&CSScourseDjangoCarrotstutorialLearnPythonTheHardWaybookGettingStartedWithDjangovideolessonsTwoScoopsofDjango:BestPracticesforDjango1.8bookHelloWebApp:LearnHowtoBuildaWebApp

What'snext?

121