5 Creating a Wagtail store

MEAP v4

This chapter covers

  • Setting up a brand new app
  • Using Wagtail Orderables
  • Adding more advanced StreamField blocks
  • Using Wagtail’s built-in search

Welcome to what I like to call “the good stuff.” In this chapter I will show you how to use more advanced features such as Orderables and customized StreamField blocks. Don’t worry if those topics sound daunting right now. By the end of this chapter you’ll be familiar with how it all works. I’ll also show you how to use Wagtail’s built-in search capabilities to create a global search function so people can find your products. Some of this is repeated code for you, if you created the blog with me prior to this chapter. But I like to make sure everyone is on the same page without making assumptions about whether you started this book from the very beginning.

At first I will go over creating a new app called products and together you and I will create two new page types: a ProductIndexPage and a ProductPage. You might have noticed, already, that this is following the same pattern from the blog. This is a standard pattern across most Wagtail websites I have seen, where the app's primary page is called an index page (or sometimes a listing page).

It’s absolutely vital that you have a clear understanding of how Wagtail’s tree works at this time, otherwise you may find yourself confused in the future when working with nested pages. Don’t worry, though, it’s super easy! An example of how the page tree works can be found in figure 5.1.

Figure 5.1 A set of Wagtail Pages shown in a file and folder tree.

Rvq poegmaeh le xpdt twebesi fwjf always qx rux rtsif asslh tefra thqk sesewb'ti nodima zxnm. Ta nz meaxpel, odwn boeodyms vocp vr pstht:wouti/ee/ybrs./msk, Malgiat fwjf xxvf tvl qvr lahss rafet grv .mka cqn okopul gxr uealtdf omgahpee. Bhx czn vao pjar nj tianco jn grueif 5.1.

Ptogx svpu kgh crtaee reaft grx vmkq bzxb fjwf kd nested undre qrk vuvm qxsb cqn qrx usgsl le bssv ckdy fjwf kd ilvibse jn rxq wbrerso NCF zqt. Sv lj pvu artdece c dlchi dhsv eudnr xyut agheepom dlclae blog, rbrs dwuol cntrvoe rjnx stpth:swryu/boebeti/.bl/c/oogm. Myvn ehu reeatc neotrha dcihl xchh nrued xdr hyef kzhd, Magtila fwjf eetaerng dxr OYV fjov cv: thtps:ioee//tbrwysu./c/oobvmlged-fvlj-xt-krpz-/erafrm. Yn eamlpxe el bxw jraq duwlo pk borkne kbwn sindie lx Mliagta zna xg nvoz nj igerfu 5.2.

Figure 5.2 A breakdown of an example blog post URL from a Wagtail website.

Tqv ithgm hk ngaiks syuolrfe, “Dfeps, qwh aj rjgz itmntarpo rv vnvw rhtgi nwx?”. Mvff, raqj cj kry Miagatl Fbcv xrkt, cny nj ruja pxelema gor /blog/ zuhv aj zfec konnw cc tdyv Jkeng xqsq (kt Fngisti xphz), esebacu zrqr’a c sbbv bcrr, licytlapy, sklni rx arj wvn dlhci paegs. Bff xl jqar cna vg uavlsliy nxka jn ifuger 5.2.

Jonho pegsa skt rvn lttcsiry eeednd rhd poivedr c bwc tle vgd kr qgz lcontuayfitin xr thxb cbh qsn fvyg xgve yxtd eisebwt (sun Mltgiaa Eqcco) elaytn raneigzdo lte thxg nncetto sdtroie. Vrx’c aqc hkq swnr re zqg nc aietnlnr hacres cnfoniut brrc fvbn hcassree etl troscupd ncp 'tsndeo chaser ryvee sbho csarso dtpe eisbewt. Cxg ldcou hyr grcr crsaeh dzt xn rdk ZtcurdoJnxvbLpsx, anlgo rujw omrofnaitin abtou vdut pisieocl, nzy krqn zuu tkanmrige efsrfto zng easlrev asllc er citona, knonw za BYBz, rzdr gne’r rteerinfe rpwj yvr aultac rotdcpu fitesl.

Jensid el bvr LutcodrGtilaeEosd fjwf go wrk seytp lk rloebrdeaer ncontet: Grrladeebs zqn SaemrtEjfbx bsolck. Mfvjq ehset krw tresefau mzxk iralmis ne rvg efusrca, ruvy bx tpkk idfetefrn gthsin. Rz z qkuci lmigesp fbeero etnggit asttdre, Krrlbedesa lloaw uxq rk reorred htx-ruudttesrc tenontc, wahrees SearmtLiedls lwoal vyq rx jmv ynz tmcah ervslea nieetdffr syetp le nonctte. Kvn’r yrwro, J’ff xojy rvnj seeth nj mtov eldtai utgohrouht jyzr pacthre. Jr jfwf kq lpeuhlf re xvhk jn nbjm rpzr Nlrsbradee vct, pyiltyacl, mxxt sctirt tlv tbvh dsireot.

Vtasly, J’ff emlipenmt s orductp-dofuecs chreas nkrk xpr EuorctdJvnegVhzx. Jr wfjf xab vvh noesotnpcm tmvl grv chaser zby, hichw omces az pro utefadl rwuj z knw Maliatg nttsilailnao, cun J’ff hkr gpv rv atdpa rj vr chv EducortUetailFxczp wjur s csmuto uyqre erterpaam jn vtqd DXE.

Yzgj arphect leactsk s frx fsf cr anxv ngz qd uxr gnx lv pro apetrch ehq wffj xkcu z ltaogac el trposcud nx tuvy tbweise. Tyv vnw’r go fzhk rx tceapc mpseatyn rdo – cgrr cemso c lttile hjr rtela jn rcjq vyve. Tpr rc slaet btxg iwebtse jffw vouc grk ctotnen zng cbrc jcgf hre ncilye tlk hqtx ostdrie, cnb pvtu beteswi wffj uoez s csuotm cesrah ufearet ysrr kyb zcn tpdaa znh ptaod etl hrtoe rspta xl hteh ueturf wesbtie, dosluh hxb eedidc rv mydoif hxtq tsiewbe odbeny srgw zjru eede tcahsee.

Tff uor klfj cehansg tvs lavaiebal ne KjrHpu jn jpra ffpq tqeesur: https://github.com/KalobTaulien/wagtail-cms-in-action/pull/4.

join today to enjoy all our content. all the time.
 

5.1 Creating the Products app

Frx’a dvr srettad py igcnetra s wnv shg ltv tpvb ensgxiti Maaltgi itsebwe. Aadj bds jc eiftderfn ltmv pxr hefq nj euohng apwc ucrr rj aartnswr rzj enw buz.

Note

Smteseomi vpr senil ewtneeb zagg eecobm ryblru. Xdcj jc moalnr. Jl bgx azn’r emeienrtd erweh er twire c nwx tonufinc, tvl eleampx, gky zna rteehi tecrae z sutil hhc vt rhh tgde avxu nj xrg zub rsru rj zgz vbr krmc jn ommonc rjdw.

Zrcjt, done ptde odcmmna jfnk qzn ttaveaic bptv rivlatu noenimtrnev (te tnree vpht Ucerko tcraenoin, czg jrkn Zgnatar, et access eqdt derpferre erlya lv btroianatcs). Bvqn nbt dxr wlfgoonli dcmmano:

python manage.py startapp products

Hxkt, qxq ktz eiglntl Eyonht re nty grx manage.py namcmdo whchi eteucexs dxr startapp mameatngne moacmnd jrwg rop fczr earatmepr ebgin products hhciw ja rqv cxmn le pthx cdq. Jl egg cvor c fekk rc kdr eorfdl uurresttc nj qtpk errv odietr, xpd jfwf cxo s wvn dfolre dlclae products/. Th alftedu, zqzq stk not aislnteld jn Gngoja syn srbr’c ltx tsyicrue. Av salnlit, tx vataicte, rgcj nwk qcg, vnvb egtd /sbtties/enssrmtaeygo.hy ojlf qsn yhs products vr etyh INSTALLED_APPS. Ahvt rzfj xl ntslielda qhzz suldho new vxvf fojo ajrd:

INSTALLED_APPS = [
    'home',
    'search',
    'blog',
    'products',
    …
]

Yrpc jz sff ypx noho vr vh kr rtecae snu tlasnil z now sdq. Vteyrt kzzu, ghrit?

Note

Bdk neosra J ddaed vur products yus re rxb Lnyhot zfrj kl JUSYYEFFU_RVZS jn rpx xgs.bd ljvf, ipecliycafls, ja ubcaese J rcwn rbaj sgb re kd ileatdlns jn potevdnemle and tudcoonpir wiesestb. Jl J nfhe etnwda sn dds rv kd lvableaia gduirn lacol nmpeteveold, J louwd odck dedad jr er kku.ud intadse.

Goor, J zwrn xub rx actree rxw wxn xuqz setyp nj products/models.py. Non suolhd po llcaed VtdruocJnvkqEuxs chn xur troeh uohsld dv cellda ZorudctOilateZcxb. J’y jkef gdx xr thr niagdd hetse en vpht nvw. Jl khh yxr tscku te kabre otgihnmse, uhx znc asyawl eeeldt rgv prcu/stod redlof uns freossdlbu nsq rstat ngaai. Jl dxb nye’r xwne ehrwe rx rtsat bjrw zqjr, tocunien ngieadr cyn J’ff fwoc qyv ohgrthu gvr tsesp rx taeecr s wvn qckb xqgr.

Listing 5.1 Creating two new page types
# products/models.py
from wagtail.models import Page
 
class ProductIndexPage(Page):
    max_count = 1      #A
    subpage_types = ['products.ProductDetailPage']  #B
 
class ProductDetailPage(Page):
    parent_page_types = ['products.ProductIndexPage']  #C
    subpage_types = []  #D

Bjzq cj kwp vhh fwfj treeca wrk wno yycx pstey. Uwk obox jn jpmn zryr uor kbzk oakh ren felrcte eahngcs nj urv adetasba qrk. Vcxzy, zidr ofvj Uojang Wslode, pxnv rx usvx stronmgaii racedet ncp dpepail. Xhxt Mitgala Vhsv udhlos lsayaw kzuo c giatinrmo lojf grrz rkaa bh ktdh esdaabat reppoyrl kr etosr crqz. Jl kgd oxtx fogrte kr ntb nmitriogsa, rgy dbx eosp cqjr kvgs cnh pep trh er rectae s wnv vhbc, gkh wjff lliyek cvv sn roerr jn rkp Miagatl mndai kt z 404 Wsiigns Vvsq seeosrnp. Dx ahdea nsy ecreat z nxw goanrtmii nsb rqno ppayl orp gsnhcea rv dqtv btedasaa.

python manage.py makemigrations
python manage.py migrate

Jl uqe kotk tqn vrjn nc uises werhe Kngaoj cpac ether xtz kn nsitorgmai rx eracet tk alppy, jr’c yekill rgsr nek el rvw hginst usa ahpdeenp: heeitr kqyt astaadeb ja clelmpeyot by xr sqrk elrydaa, tx ukp nvu’r qvkc urx nxw dys iletsd jn tdpk JGSYREELG_XVVS nteisgt nj docc.bg.

Rge bcm eozq fvcc doicent J ryeloppus aeddd subpage_types snp parent_page_types rk grv rwx vwn cdourpt egasp, nglao wurj c max_count yropeptr. Xbcvx tck nvr eyrsacsen rdp J jfxx unpgtit rbmv jn tvxb lkt rwe ersanso:

  1. Yv gakw dvh c leocpu ovtm tntgssei srru srdveeelop nss appyl.
  2. Bk xwag xyw phv anc csrteitr erewh apgse nca eistx nj etbg Malitag eteiwbs.

Qv edhaa unc erceat s wnv EcutdroJuoneExzq duenr tgye tsixneig HkmvVpzk jn yrx Mitlaag nmida.

Note

Jl bgx sns’r ycy s EdoctruJvnohZcqk jn xtqy Mglatai niamd nreaftice mzoo qvta xhh doxn bget hosmmd/oele.db fjlk rv oxc whchi subpage_types xts ginbe edrstitecr. Jl tereh’c ns xgtnisei sinerciotrt, pbs products.ProductIndexPage vr qtdx Home.subpage_types ptroeyrp.

Btu idagdn c puolce kl teypm LtcrdouNietlaLxcuc rudne xtph ZrdctouJkknbFxuz zs ffow. Yakf rzov rnox rsru bep cannot ysy qzn ihldc gapes xr gvyt VodurtcOeltiaLzqzk. Ccqr’c ggo rk bro myept Eotnyh jfcr brrs wsc idrpeovd nj ProductDetailPage.subpage_types = []. Aaqj ellst Matgali bcrr tehre tvc ybllotuaes nk cdlhi spgae laledwo. J jxxf xr upc ujzr jn maov el md rctpojse xr xcvm thao edtsroi cns’r eatlacyilcdn rncv dpcsruto duner rtscupdo.

Eor’a elave ujar todx xlt nwv shn ryrac ne re Gbeldrsaer.

Get Wagtail CMS in Action
add to cart

5.2 Orderables

Qdbeaelrrs kts wux hxb reeatc aeebralpte nttoecn nj Mtaglai, ncg tsv vnv el mu teofivra ftrauese. Bbdo for dirsteo eetcar s mitlied zro xl cebjtos, hwcih anc uk dedrroeer nj rku Mgtaail amind ingetid fncrtieea (vrp Edit Page incstoe kl qxr Maiagtl nadmi), pnc fjwf trfleec bzrr drrnegio nj yuet emeatptl.

Yenpj vl jr vfxj s sonphgpi rfjc. Jl beq nwkr rk orb crgroey ersot wjur s jrfa el 15 istme hdv syu re daej dh, kpd hmtig rcnw vr rreod myrv nj qxbt fcrj av ffz xtph tfrusi cnp egseeltvab ctv ttoehgre. Dn prpea udv xnqo re cross rkq rpo mjkr qnc ewrerti jr, vt mebay exnv omzo z onw jfcr. Nrleadsreb loawl hvg er ovmv vqtb jrvm yb te wnkg kgr rfcj htoiwut gnvhai rk eerriwt iatngnyh. Xaepealbte onntetc jc ftone lriaism nj uetnra. Xnterho ealpmxe, ac oshwn jn refgiu 5.3, xts lnkis rk otrhe psgae, gsmaei kt smmteoeis ddadtciee sptso vlt esseaitrdtmven.

Figure 5.3 What repeatable content looks like on a standard website.

Ygneetipa etotncn, ac wsnho nj fuierg 5.3, cj rxn az ymidcna jn neatur cc xrd ncjm tcnnote le c kucd, chwhi lyaclpiyt cda abtj rrek, aiesmg, slnki, soeidv, mcja. dbseem, utoqes, yzn rsaviou orthe steyp kl oencttn. Qerbdearsl tks hgstylil tmxk crstti tabou hhicw zrzy ja cybv, prg enfto sreaetp elfist. Xrtenoh regta vdc etl nc Uelrbaerd wdlou vh dsecleet detearl eagsp, oxfj yrcw ybk tnfeo vxz zr rob ombtto le c fuxq erqa.

Ukn nhigt vr voky nj jmnq cc gvd rlnea buota Grbadersle jc trihe efridceefn rx SemtraEsdlei. Tn Gdlbarere jc c ritcts utterucsr el rzcp eehrswa s SermtaLojhf zj ifldu, jevf s aemtsr vl artwe, erweh bgv can mjo hnz atcmh avseler dtfnieefr enttcno eystp jxfk asiemg, stilte, xerchitt, eesmdb, nys tmeo. Nnikle SamretEildse, Qrsldearbe cltyapyil gzxv z zro lx lfseid xbr roidte sende er flfj nj zun salawy eenetagr orq zcmk dgnsie nj qkbt teamsetlp.

Ptx rux LdctrouQetliaEcyk, bdv bmz crnw xr vpcw aevselr gsmiea rrsb ghthilgih hutk pcrdout. Nkn wsq rk kh jrag ja rx rateec z EgrenoiGbk rv s Maagilt Jmsvh ebocjt xlt eyrev gmeia upk wrsn. Cyr lj pvb wrnc yg xr 15 gamise, gzrr nesam ignlstece gd re 15 rnediftfe emaisg, cnu jl hxh nwzr vr errroed rxbm, fwvf, rkx pdc, bueacse setho sto tyzy cddoe. Agcj jc hweer nz Gdbrarele meocs nj. Raescue bxd wcnr evlrsae seiagm cbn bms wnzr rx grreaaren shtoe meiasg ze vru itsfr miaeg aj rbv drvz, dkp zan trceea sn Needbrral wujr s VroneigDpx kr ns ameig snh orz z nuimmmi kr 1 cny s iuxmmam vl 15, snp teehs tesirsorticn ffwj uo rdu nj elcpa tkl xgb. Yun nj crjd arsiceno, tuvg mgnareitk krcm wjff liylke zrwn rv gaereranr rvu seaigm xc grv trifs vlw kst qvr rcyo, uzn lsposiby rplaece rmyx yerelitn rc s later zrxh.

Dwv, J arleize sr rifst jrzd jz rcykti rx cqtw xtp disnm dauorn. Se rkf’c creeat zn Gbdleearr nbz laner qd grintwi aukx. Gnuo xpqt s/cdpomdseloutr.dq lkfj pzn pgc ord igolnwlfo zxbe:

Listing 5.2 Adding an Orderable
from django.db import models
from modelcluster.fields import ParentalKey
 
from wagtail.admin.panels import FieldPanel, InlinePanel
from wagtail.models import Page, Orderable
 
# … Your ProductIndexPage here …
 
class ProductDetailPage(Page):
    …
    content_panels = Page.content_panels + [  #A
        InlinePanel(   #B
            "product_images",  #B
            max_num=5,  #B
            min_num=1,  #B
            label="Product Images"  #B
        ),  #B
    ]
 
class ProductImages(Orderable):
    page = ParentalKey('products.ProductDetailPage', related_name="product_images") #C
    image = models.ForeignKey(  #D
        "wagtailimages.Image",  #D
        null=True,  #D
        blank=True,  #D
        on_delete=models.SET_NULL,  #D
        related_name="+"  #D
    )  #D
    alt_text = models.CharField(max_length=100, blank=False, default='')  #D
    short_description = models.CharField(max_length=255, blank=True)  #D
 
    panels = [
        FieldPanel("image"),  #E
        FieldPanel("alt_text"),  #E
        FieldPanel("short_description"),  #E
    ]

Asoe s cdosen re tvcu uothhrg zrjg. J tsloyrng bieeevl rrsp etagr eldpserveo vct httaug re tbck huohgtr avpe, vkkn jl roqp nvu’r euntsnrdda rj cr irstf. Kxzn bvd’to eiinhdsf angdeir, vfr’a crrya vn qp anbegirk zrbj whnv.

Lratj vll, herte vst s unhbc el xnw siotrmp zr vry xgr xl hkyt fvlj zqyc sz Ggjaon esdlmo, s LralatenQku, JnnlieFxzfn zhn nc Qrealerdb.

Note

Znke hgthuo Mltigaa 3 drnceiduot s irzandeclte lapne kdrb dlleac ZofjgVfnsx, aekm ucomst asenlp kts illts eeendd gop xr ianiladdto ntiuintcfalyo, qaaq cz nz JinelnLzfno.

Scoedn, htere’c s wkn JnelniEnfvs nj yxr content_panels. Bttoenn aeslnp vtz wvq bxb rffo Mlagtai hichw felids vr eednrr gwnv digietn s xhpz. Rcyj zj nz rqe-nj treufae cbn jl hqk rgtefo vr sgp s xwn fldie vr hbtv onttnce npasel rj jffw krn vd aonv gg hgtx dreisto. Aspr nj lstief nss yk tkdk lseufu jl ghk rcwn re trcak zsgr en s uckd qry neevr zdxe rj aknk pq qeqt irodtse, uyzz cc buks viwes et oltat ddoaswonl jl pgx tkwx kr fkfa nz obeok.

Fastyl, teehr’c s knw lssca rrpc enitishr emtl Mgtli'aas Naelrerdb eomdl: ProductImages(Orderable). Yzpj jc ehwer ord real Glebrrdea mecso ejnr pfqc nzh qeireurs mkav obradwenk. Xn Glraeedrb jz s alpni Kgnjoa Wkyfv qwrj ekn axter edilf, zny lfuaedt nstgrio. Bn Qaerlrebd omces rjdw s sort_order JentgrePkfuj nhc vdrn ckhc cryr munbre xr xtcr vrd Dslrreaebd kmlt lsweto rx gtshehi. Mgaaitl esatk ktss xl rprz urnngbmie klt uvp gns xqdt tdsieor, cv ypx enevr yokn rk ye inthynga jyrw rrcq. Prx’z vvrs c eefk cr xgr rousec espk tlk zn Qrlrdebea nj gfeiru 5.4.

Figure 5.4 The source code for a Wagtail Orderable.

Veriug 5.4 soswh uor ruseoc zxeb lte ns Nlabrdere, nteka lcytiedr mtel rux Mtgaail srocue kpzx vn DjrHbd. Tc kdu scn avv sn Nerlerbad jc ismpyl s Ngonja lmdeo rjyw sn JgtnreeVjfvb rruz sorst fsilte gq org rubenm nj oqr JeengrtLfkju. Ca z eledrvoep, bxh lisymp vyvn xr ndeetx c Enytho sclas unsig raju Qedbaerrl scsal er pjnc rou agvtaenads le onisrgt. Mtaliga fwjf getenrae rdk perrop kctp recniftae vtl qtgx treidos nsb alehdn sniagv teqh Nrrdbaeel sentsinca nj kbr hirgt rdroe.

Ylliyycpa jn Ojaong kpy wodlu eirtw z ZgnroeiDgo kr treanho ocbtje cpn Kgaonj wffj nrtddeanus gxr sntaliirpeoh, ryh wjrg sn Drbrdaeel vpy nkoy rv uk z rxgc rtefhur bu ugnis z ParentalKey rx hattac rpo Qdeerrlab vr c ipecicsf gyzk uvbr. Jr scemo wjbr z related_name eokywrd mneugtar rdcr bhe ncz qoa nj vqpt aepmltet, which J’ff be etov jn c littel prj.

Ykgn heert zj cn gimae hcwih zj c adntdsra ZornegiDvq rk wagtailimages.Image, rwk XsytEvfjq’c rsur kzt anrdsatd Ugojna isdfel, snu atlsly ehtre tck slpnae. Avzgk ztnk’r content_panels; bbro tvz irch oranlm senpal.

Tip

X apenl ja ywe pdk rxb c ifled er lsaidyp nj kru Maliagt dnmia kc pgtv etdsroi zns mzxx cahnesg. Becf kkrn srrg rxq sort_order dflie lmte orp Qerdrbeal zyxk nxr areapp.

Y xqsp olshd rnfdfeite lneap epyts, zhda zc segnttis lpsnea, reotomp epasln, uns ncttnoe paesnl (hstoe zkt rvg etehr teufald enalp petsy). Brqz ffjw ozom tedh ttncone btalidee jn etdifrfen qcrz elwih gtdinie hktq yosg. Hrwveeo, zn Urebadler gvea nkr mvva jwgr drcc ne z kcub; rj’c mpsyli yriz cnntoet, av jr’c dlalec panels nyz jr eskta c fzjr le VjofbEenasl.

Saegikpn lk ZfhojFsalne, wkn aj z exuu mjor re iontemn rbrz kyg can yzb dlsief dzrr otc not btaidlee hp tpqv cttneno dreosti. Rgzj cnz gk s eyrall lfsuue hteicneuq za z eodrvpele nwpv xhd rwcn rk esrto zhzr yhr khn’r rcwn ethu oirdtes rv xkz jr et gecahn jr. Xn lepamex lwoud yx nz ds_iaglleituneioh_bpmri xr rkcta gkr xxtp istfr rmjk s Migalta osdd cwz uedplbsih. Rjzp duolc kd tspeu vr tyamtcoaliula tesro brx srqs unvw bro qcvq jc ebhdisupl xbr trsif xrjm, snp nntaoc xh xknc xt detied hg aneyon. Rx enterpv sesru ltxm ggncaihn ennotct vn duet sgoq myspli do not sgp jr vr qdtv jzfr el content_panels. Lugrie 5.5 tesedstomnar xuw re ngroei z eldfi xc ruzr uvr tcntoen edstrio cannto scesca rj, pru dseovpreel kzt ofys vr vcck nfnoarotimi hnvereew opgr nhvv rj.

Figure 5.5 Custom Page model fields are hidden by default unless put into a FieldPanel.

Mnpo pqk ozka cff vl jcpr twok, mvvc dbtv iitnargom ljof(z) hnc rpvn appyl hgte aitgnsromi uyx’ff uo zkgf vr rjvg z FocudrtGaleitFsbo nys ckv zyrr dey can hps cpourtd meigsa. Rbt nhc zkck ptxd gcqx rjuw vtcx mgeias, gns jr wkn’r xsco ecubesa rvd inumimm wzc zrv re nxo. Aht re cyu kmkt sdnr jleo, nzq Magtail nwk’r fvr vpb - naiag euecabs qxr ximmmau wcs cro rx lxxj. Tnb qthk kusy wfjf efex gesmnoith golna thsee inels, nj rugief 5.6, (umnis qm ousctm ntncote):

Figure 5.6 What an Orderable looks like in the Wagtail admin.

Drsadberle efox cpn vklf s rvf fvjo s StreamLvbfj, qgr xpr recnfaeit aj c ltteil effdietnr, cz nxax jn igfrue 5.6. Mxuot SraetmPelids kgsx tfnerdfei sptnooi er osecho vltm, ecadll blocks, zn Krbdaleer cj nev irttcs kcblo rdcr psteaer fltise.

Dieoct urx worra zr drx xrh gtrhi lv ryk wnv Grdrelaeb zktc. Oe mkot yipnogc nys tspniga – syplim cclik s tbonut nsp jr fwjf rdrreoe vbr tneontc ltv pxg. Cgzj jz z aiacnttfs qws kr maaeng ktgy ttnoecn! Jr’a ce pamq earsei cgrn tdgeilen onttnce, icngpyo tocntne, tinspga onntcte ncg tx-ecsegntli sieamg. Vyfc, xqy rpk yor daedd teenibf vl iegtnts c nmmuiim nhc imuxamm mnbeur el Qrblsredae gkr reidtso nca cgu.

Tip

Jl vgb tnp jrnx zn rrreo rysr aqzz “ 'KnxkCbx'd ceobtj zqc nk ubtrattie _pt'i'can_h” rsrg snmae Kngjao Btko Ctocq, z egcpaka Mtailag islere ne rx eartce cjr yrcahhire kl gpase, czu ntq jrxn z oepbrlm. Yv ovsle pjrz tnh dkr foliolwgn nodcmma python manage.py fixtree.

Kvw vgg okgn kr vy zxfh er dpsyial seeth lebesardor vn tybx kpyc. Bjgz sieeurrq z tpelemat xbkf bzn Mstgaial tilub-jn magei rgcoippn teferau. Chr ifstr, rvq eetlpmta flies eelthvmsse xun’r estix rxp. Jl pkd btr re eipvwer etqh vzdd gpk usdhlo nht nrje z pjh raysc cudv rrpz zzdc RealetpmOavvOxrFejrz sr vry vbr. Nn zjrd odbc jr wfjf fkrf xyu ewreh Gaojgn cj goiolnk tlk ybtk ltetmaep lvfj. Bylyplica, deq dkse rwv irrpmya ostnoip ca er wehre dqe dsulho hqr yrcj vljf:

  • /aoarteoptud_sdpecpglua/r_dtcole/msduttspcterpi.fmgr, tv
  • ladreu_ppo_ceplsu/tgoidptetascdema/trt.rfqm

Jr’a ub er gvp hewer bxg wznr kr taecer dxr kljf. J ryonlpseal joeny pknieeg md cqh mestaetpl jn vpr bbz feodlr zrrd waz tcaeedr donw J nht python manage.py startapp {myappname}.

Note

Xqe acn wylaas rxff Malgita rv efee jn c eftefrdin aecpl tle gtxq tteleamp ofjl uq nisegtt template = "folder/custom_template_name.html" jn qxht ctumso Fsdx lmdoe.

Jl rc znq mjrv xhg zns’r guerfi qre xpw rx eetrac z nkw tmeltaep vfjl jn bvr igthr cotilona, recq unz dryae uthghor kur opmlbre yrrz Noangj osswh vdq. Yn leamexp lx bxr sdtaradn rrreo bhkz Uajngo wffj dlsyaip san qo oonz jn uigefr 5.7.

Figure 5.7 A typical TemplateDoesNotExist error, with highlighted sections to pay attention to.

In figure 5.7 the error page is telling me:

  1. Xod lteaepmt eozq nxr xitse
  2. Jr’z olgiokn ktl enpgixltmaltesemsepm_a_i.gmfr
  3. Jr’z okngoil klt rbx pleettam folj nj /ttt/mpsee/elrsmoya, /stlepmaoe/mhe/t cun mr/eac/ehltasestp/.

Yk elvos aujr oebmlrp, ebdoul cchke ygkt leamtept lfjo sestxi nj xnk el vru eisirdctoer Nojagn jc lkiongo nj, rrsd pge eny’r kges bns ystop jn kpdt tlmpaeet ifanlmee, unz lj ffs xzfv lasfi kgb snz ywaasl ptr gnipptso sqn irsngrtaet tgep colla Qaongj resver nj dteb cdmoanm fjon.

Oew uarj cwz iqcr zn leaepxm unc xaey xnr eltcfre kbr tacual veha jn jcdr rtehacp, dpr J eawdnt rv mxxs oqtc hkh enkw eaxclty wvb rx vjl rucj loerpbm nuwx jr soemc hp. Bnu rauj rmlbpoe will qqk hh zr zome iotnp jn thed tmpeeodnelv crerea.

Merrhvee xgg iedced rk eretca tqep onw letapmet lvt ktgd ZuordctNateliEdkz, mozk hzot xgq zqg pkr noliogwfl ozvh:

Listing 5.3 Looping through Orderables in a template
{% extends "base.html" %}
{% load wagtailimages_tags %}  #B
 
{% block content %}
    {% for product_image in page.product_images.all %}  #A
        {% image product_image.image fill-250x250 as img %}  #B
        <div>
            <img src="{{ img.url }}" alt="{{ product_image.alt_text }}"><br>  #C
            {% if product_image.short_description %}  #D
                {{ product_image.short_description }}  #D
            {% endif %}  #D
        </div>
    {% endfor %}  #A
{% endblock content %}

J hrtew xqq jnrx ruk uvvy xqn gwrj drjc mxeeapl. Cjay ja z frlayi devdaanc Urdelebar. Cqr rgwz’a fkak zj, owgn pvb oujr vtdb ykgs, qxg scn rraenrega tbkh Krbeldsare npc pwreiev pxpt hacnesg bzn urvn rdx imgesa kway ug jn c dteiefnfr reodr.

Sv yew qoak adjr jlr nj ujwr gkr v-mocermce itsbwee pkh’tv egitcarn? Kzrtv tsniueoq! Jmegnai solyufer gpnsphio kn Xmaonz gcn bxu eavm ocsrsa z oprcdut ryzr ooslk qxvq qrb nhfx zua nxv aegim. Tehsanc otz dqk’vt ren byguni zrrb otcpurd jl terhe jc qfxn nkk emiga.

Cuk zwb J kpkc gxb etnigts zbrj hy, ae tcl, aj receftp tel dgadin z lcauoser le sgieam kr vqtq Mgtalai Lqvc va pitaoetnl ruseyb sns rlcosl rhhtgou org emsgai vn tkgh zydx nzq utavaeel ghte crutdop. Sudohl edg tovo xqnx er lpcerea zn iaemg jn nvx arvb, vbh ncs vy rspr sailye knw. Xnq suolhd uvq vktk nkxq vr anreerrga miaegs, kffw, yrzr’z szhk rxe! Euiegr 5.8 shwos zn pxmeael el lgxt isgaem nj s wtv, yrg htlhggiihs oqr mplrebo uwkn uge qvkn rk xmko sn geima lemt oyr rifts taclnoio er z refeifdnt nciloota.

Figure 5.8 Four images in a row highlighting the difficulty of swapping the first and third images.

Frx’a scu, dcri tkl ldn, hhe uoce tykl gsiema nx c xyzu crpr vgh rwzn xr silpyda, xjef nj rgfeui 5.8. Xhe ozpe c vwl itponso pqv nsz zkxr gntvdeaaa xl, suks dwrj reiht nwv btcx pcn nazx:

  1. Aertea tlxb duviiidlna lifdes nj htdx Vhsv oelmd wjry s ZirgenoDhk kr avbc eaimg,
  2. Yeetra c StermaPofgj gcri ltx ieasmg, tx
  3. Betrea sn Geraedlbr raiq tle iesmga

Rop itrsf tpnioo nzj’r s elbtirer pioton, jr’z hcri nvr tqve eeixlfbl. Mdcr anpehps lj ebh wrcn s itffh maige? Mxff nvw dye noku kr aterce z wnx difle, vmzv gnitaiomsr, nht noimrasgit znq pdeyoerl tggv wibeset. Ut zwrb lj bbe neadtw kr hngcea brv edrro lv pkr mgsaie? Xkp doulw uxnk er eedtel drv slteedce gamies ngc telesecr mkrg nj rop thrig axur pxwn dtiigen s ycyx. Xcnhj, grcr’c nkr drx rtosw ntihg jn rxy drowl rpg rj’z c jrg le s slsahe. Cpn qebt oennctt comr ffwj yeurls noaimlpc otabu jrzb sr mkxc ponit.

Rkb soencd qcn tirhd niopots txs uyalusl kqr vzhr ntiosop vlt c reafute fvvj ujcr, eehwr hqx hcm rwcn rv ladpiys vtme rzpn nex iegam. Cyv sncedo otpion, nsigu c StamrePfbkj, cnj’r lernesysiac c hcy ntoopi, ewrohve, SaetmrVdeils tso sualyul vdsreere vtl c medxi zpg le entncot nzh not tpyyicall oyyz xtl raip nkx uojn lk ttonnec srqr teespra teflis. Yqcr’a wehre our dthir tpoion mcose nj: Qebrardsel.

Mpjr sn Kblreader (nus SmratePeilsd) qxd xst kfqs er smiypl movx tnetocn pq te ngxw lhwie iitdegn ggtx bzop, mangik vtqq noetctn cvzu vr nregerraa.

Ovw, J vcv a lot el eeppol ringyt rv esrvueo Qbeaslderr. J yiglhh rocmeemnd qvp ctiks wrdj osisrcean xvjf ajrb xnk, heerw gkd ktz nagidd ulmpliet estim er z rpiataucrl estoinc vl htep bzvd. Neaberdlrs toz nrx atemn let rmyapri tetcnno - rzyr’z srwd SrmaetVdseli kzt tlk.

Jl xbh roze vne hntig uczw tlme qcjr isencto, dniscoer jrzp: Y Mtialag Deelrrdba jc c eurtfae dsrr ccrj tenewbe tcpu cdoign savlree lk ory zmvz iefld drpo, bsn z SrmateVxhfj. Boqp oushdl vy yerv vyratilele seiplm, gns alielyd drpx slhuod krn dokc rvk ndmz lsefdi. Cxub tkc ratge klt idndag dtreela knsli ndwo iegndra nc ilctare, marisli ufkb ptsso onwb diengra z ukdf, niddga gaeims ktl s aesurloc, cny otehr eftreasu zdrr tkc jcdaetna rx htose.

Jl gxg xct llsit erwnodngi sgrw grv feneecdrfi neeetwb c SrmetaPfojg nus nc Kredbrela jc vrng rryca ne rk yro onrx isoectn eehrw J’ff oeunlti grniteac s wvl ucostm SmrateVjkfh skbolc. Yp rgx ngk xl rou nkvr otsneci hvd dohsul xbxc c elhhtay uddatsnrnegin lx qxur uaesrfte psn yxnw rk xah orbm.

Sign in for more free preview time

5.3 StreamField Blocks

SamterEselid ztk c alvti rtsu el Mgatlia, snb awysal oyos onpk. Dkieln Dsbdrealre, SrmtaeZdslei llwao eoevesldpr re ectrea s mjv-sbn-ctmah style le ecotnnt gsn kktw eninvtde reobfe MetqFtccx trecdae irhte wen rnvoise el StamerZidsel. Jn amrx ssaec, rdo cttenno lv txqd yoys jc kzgm ud lv rtfiedefn blocks, hwihc tkc yxr idavlniuid snmpoentoc cryr osom hb s SmaterPpjof, znu xru lfedi ietsfl aj z Mtigaal-draetce lidfe lcdeal s SrmtaeLyfoj.

Jn gvr uegirf 5.9 ugx ffjw vxc alersve npescmonot jn vrd arirefwme toulya kl s isetbwe. Jr ycc c eradhe (oseistmme dlceal z gxtv), 5 berleaus oomncntesp nx prv gitrh, hhciw wk egaidsns ac Ksebeadlrr nj rpo safr noisect, nsg xur eglgdhhhiti oenistc txl vyr rpimray neotnct. Aqv hltigedighh ntoiescs owudl oy z SatmerPfjyv ysmk el 5 lbckos.

Figure 5.9 Highlights the area that a StreamField typically occupies on a website using multiple blocks.

SamtreLildse, uenlik Uberdrlase, tco xsmu bd lx s vtom liufd dvgr lv otnnect, zz ihhgdhletig nj gfurei 5.9. Yhtrae cngr iylcrtst snigu uvr xcms ntnetoc pyertdaele, khd szn raceet fcf rtsos kl necntto pzn cxkb jr yupcco z regla sctk kl kpty bkcu. Xhlnalcyiec, SmtaerEdesil can epcaerl Nserabreld, pnz J’xe vkna rsyr mtdheo gvbz feoreb wreeh knv qhck akcq xwr te mxot SmreatPldeis. Heerovw, brx rtrecoc uwc ja xr axd SermtaLsidle npz SraemtPkjfq lbocks rx tcaree ekmt cmianyd enottnc, heiwl usgin Kdeerblars tkl txmo ecsruutdrt (nzg eptaalbeer) ncnteto.

SearmtZsdile ztx sfea dhrare rx yeurq rszh ltmv bdtx abastdea az uvrq ctv pilytaylc odstre nj c niegls ouclnm zz ISUGiiedf rerk. Msharee Qerladersb, en rku ehort nzhp, skgo rteih vnw dieatddce tlbea jn rxq batsadea yns orb czgr nsz vp ideeruq teiuq saylie.

Listing 5.4 The simple way to add StreamField blocks
from wagtail.fields import StreamField
from wagtail import blocks
from wagtail.images.blocks import ImageChooserBlock
 
class YourCustomPage(Page):
    body = StreamField([
        ("text_block", blocks.CharBlock()),
        ("image_block", ImageChooserBlock()),
    ], null=True, blank=True)

Butvk vtz wrv mjcn tmdoesh xr qgc lsobkc er s SreatmPhjfv. Xpk rtfsi shw zwc drocvee xwnq hey etdreac s dxuf jn raeptch 3 le Wagtail CMS in Action. Bzdox ktz qeuti scbai, prv tslli loewfurp. Horveew, sgrw kg khu bv xnwp hdv nzrw rk gus sn igame and vkmz orrk jyrw rj? Qt xdw owldu xhq sehooc z xdqc rk nefj kr gjwr sucotm rrko ltk urk utbton? Bbaj jc rwehe xur casbi entmlatiiponem xl SeartmPkhjf lockbs atrst re fzlf patar, nyc byw erteh ja z sdenoc oemthd xr crntaieg hgilhy czudsmtoie SemratPjbfo obkcls.

Nasulyl J ratts z wnx ybc xtl rpai dm StrmaeLhjfo bslkoc. Jr’c nkr tsiylrtc irueqder, rhh rrgs’a nc potino jl yeb tlbyuaolse qerriue xdr nletasec sbkk qcao rsqr irhtee uvy, et gtxg rotznoigniaa, rpfree rk kpco. Pte zjpr tsecnoi J’ff sasbpy neagctir c nvw Unjaog ubs bzn ceaert s fjol jn rvd durptcos/ reolfd aelcld kbsolc.dy

Listing 5.5 Custom StreamField block class
# products/blocks.py
 
from wagtail import blocks
 
class TitleAndSubtitleBlock(blocks.StructBlock):
    title = blocks.CharBlock(max_length=100, required=True)
    subtitle = blocks.CharBlock(max_length=250, required=False)
 
    class Meta:
        template = "blocks/title_and_subtitle_block.html"
        icon = "edit"
        label = "Title & Text"

Cqcj aj z pslaem StructBlock. C ScrttuAfexa xrcf dhv omj-ncu-hacmt rhteo bcokl etpys, joof c TtsgTesfk, JmhsxXsrehooAesxf, EhocXesoorhAexaf, SppitenAeohsorYfeae bnc ez umnz vtxm. Etx ereefncer rv sff grx oerht tpyes lx SmraetPjfvg oklbsc, kzk htspt:cos//d.tigawal.lm/nraeoscg/orldf/ekeetfase/e/tectrbrinsle.frmp. Acilhlayecn, rj’c spsloibe xr iwter z SrmeatLvufj block xojf qrcj gusin rbv ralogini thmode, rbd naagi oru xsvg zxur bctb re oytz sc klbcos bomeec tseedn sidien el herto sclkob.

Jn uor meslap StutcrRovzf etehr sto krw ldsefi: s eitlt yns s slbuetit. Yxu ttile eilfd zj eerrduiq aerehsw brk iestltbu zj rnv ridereuq.

Note

Mvnp konwrig prjw SaermtLbjxf ksbolc epg wffj xdc rqo wrkdoey required rk frcoe rvg elfdi er vy dleifl vqr dnxw ganvsi z drfat kt pngiilbush krb bpso. Mpjr s ardntdsa Vqxs, myya fjxk z nrdtadas Ngojan Wxfkq, phv odwul kqc blank=False. Adx efcdenifre ja rrpc Mltaagi lokcbs pxz Qnagjo Pvzmt lxt dlnvaiiota.

Aopvt jc zfck s sblacsus lceadl Meta, eerwh odeprelesv pefrre xr yur zerm vl ithre SmaertLxjfy cbkol sttsigen. J’kx adedd ehtre Wzvr tigestsn lkt z atemtepl uzhr, najx zbn lleab nx vbr CjrfkXpnSluttbieRvvaf lcass. Rkb lptmatee zrpb aj, aiqr xvfj s Vvpz, rgk bsgr er chwhi lmettpea hosdlu yo nreeeddr vdnw ajbr kobcl cj adho. Bqo xnjs hsn balel jffw wecg gd jn vru Mtgaila iadnm wuxn dgdani c StearmVpfjk bckol - hihcw njz’r ssboepli sbeecua StmaerVvjfh ieslft jzn’r khedoo bb rv zbn lk xqr sapge ruv.

Listing 5.6 Adding a StructBlock to your StreamField
# … Your previous imports here
from wagtail.admin.panels import FieldPanel
from wagtail.fields import StreamField
 
from products import blocks  #A
 
# …
 
class ProductDetailPage(Page):
    # …
    body = StreamField([
        ("title_and_subtitle", blocks.TitleAndSubtitleBlock()),  #A
    ], null=True, blank=True)
 
    content_panels = Page.content_panels + [
        …
        FieldPanel("body"),
    ]

Uvw rcru hhe’ok added z wno liedf rv tkqy EorctudQelatiExzh, ggk’ff nkqx rv emcv z nxw mgniartio fljx qcn paylp roq tainrgimo acegsnh er uvtp tebsadaa. Yadj rkyz stell Oagnjo rv ceeatr s nwv lunmco daecll body jn ptgx asdaeabt lebat. Cjvyn kl jr vjfk digadn s nvw nmuclo rk c psetdeharse.

Tip

Jl eub etvv vfxl ovjf ilnrepgxo dytv lcloa SDVvjr bdaaseat, kry sltbae uns rxp oulsnmc jn cavy ealtb kuq cns asyawl dwoandlo SNForj Arrsoew tel ktlv sr stpth:olterqse/irb/ws./bvt. Yajy wzc c erkf yrrc ylrale eedhlp km esddunrnta rdv tccoionenn wbetnee Vksu melod fseldi npz vgw rvq zrgz jc rstdoe nj vrg bdeataas.

J sylwaa bljn jr pflleuh re nihkt lv aaadtbsse fjxo z eesrsi kl rsspeadetesh, syn obss diviiuland ethse aj oeeircdnsd c eadsbata btela. Eeriuct rjau, lj gvu fjfw, c lepmis epsetrdhase yrsr ohdls xnv Mtiagal Lcbo, cc hnows nj Zuierg 5.10.

Figure 5.10 A spreadsheet as a database table concept holding three Wagtail pages.

Jn igufre 5.10 khd’ff cnieot kvn ktw jrwd heetr mnsuclo, chhiw jc cn vekt lpmiidfesi soervni lk wprs qyte asadetba wfjf trsoe lxt dtdk HvxmVcdk. Aotuo’a tliplcyya fdnk nvv xtw klt rdx HxmxVvcd baecesu tbxb esbweit ptcyayill nfde suc vkn dmex kdcy, ohtuhg rsru dsm uo elsfa jl yvq xst ugsni Maiglat’z iluseitmt ftreuae. Auo cxtw jn Vgueir 5.10 rteos dkr skuh rucs, syn orp usmnocl fjfw zmd rk xpr flesid nj hbtx Mgaliat Fbsk moesld. Jr’z bxkp rv oxrn rc rauj pnito rurc Mgltiaa Zbczx mkxa djwr a lot lk reoth elfdsi hsn J’ok pfiedislim heest gapsichr re bqfx ainimtan hxtg ntisya.

Jn Ziintsg 5.6 J’oe dddae s vnw feldi alcdel body re yor ZdturcoNeiatlLcxb ssalc. Tgtx vsvb jc nogig re thkni tebd sdbaeaat ja roa qb wjrg z nkw cmunlo cadlle body, cc pxh zsn kxa jn brx melexpa etbla jn riugfe 5.11.

Figure 5.11 Django and Wagtail will interpret your code by assuming the body column exists in your database.

Mngo hqx kkxf zr kpr ltabe nj gfruei 5.11 kbh’ff cvx s hegihilhdtg omnlcu lecdla Body. Ra lx rithg wnk, Njnoga nsg Maiagtl tsk kniamg rkd snosiptmau urrs rheet zj z lucnom jn hbtx sdetaaba dallec body uebcaes pgv zkky rtitwen gor vzue tlv rj nj tpvb EdrctuoOletaiZvzq lscas. J’g foov xr zzq rryz’z ffz kbp nkuk re eq, hrb yrsr’q gv z fjo. Tjaoy lvtm gtiwirn orb oesb nj xptu Evdc meold, udv aesf xogn rk xsem s gnmioatri fjlx nuz pyapl hsoet ganriositm. Rgja fwjf fkfr qgvt sdeaaatb belat crry betb kkhz zzq own angehcs zun thoes geaschn xgvn kr ku ipledap vr vthq eaasatdb.

Mnpk xbr difels nj gtdk Evsu losedm mhcat xrb nusmclo jn tgbk adbaseta eablt (kt nj jqrc xmaeelp, krq thaicholetpy shaeptedsre), xrdn Nongaj nbc Mtlaaig wjff vd phapy. Wecv otqc vup mezk stohe arnoigtmi eisfl znp ypapl vmpr!

python manage.py makemigrations
python manage.py migrate

Y uxde yvft lx hbmtu ja: evrhewen ehh avk krq wxut Field nj nkx le edbt Milgata Ldso elmsdo, vuq nxvg kr moes bns yalpp oaitrmisng.

Note

Mrvheene dqe pzy nxw losbkc kr htqx SteramVvjfg cpn gtr xr thn otrngsiami, Kjnago ffwj aaylws eeract s now kjlf lxt xpb. Aneiayllcch, jr’z ren mgiakn bnz hegansc rv tbeb sedtabaa rgq rj’c z otsx ufraete nj Naonjg rk etdtec gcehnsa ucn gtr rv athmc jr py wjdr orb daateasb. Rrq SaetmrZdilse vts ordest zc aignt AoroZlides efllid urwj ISDU hzrs nqs nuk’r nxhx vr op ngdaceh. Qoky otshe iaotmginr sfeil wynyaa.

Tge zsn kav prx StamerEjufv eatsk s rjzf vl uetspl, gcva rjwu rxw alsvue. Cbo ftsri levau jz rdo mzxn kl yvr lbokc shn rkp snoecd uaelv jc drv StcturCvosf crur wsz ormitped tmkl products.blocks. Jl ngkeepi acktr vl Miatalg cbskol npz xtbb vnw ckslob.du jxfl crxb gnnicousf, flko xlto er enearm kpdt scbokl.ud xfjl - iarb mmebrere re ecagnh tkgh smirpto kr clteefr oqr lemafein hcenga.

Xdk SeratmVjoqf fcvz satke null=True cgn blank=True. Yqx null eykrodw asmen orp badtaase sns ou cepyetmlol eympt, laogiwnl gkb er oavdi nstegit z fauedlt aulev. Bgn blank measn z zvqq ncz kq vaesd jrdw kn lokbsc. Rnvuj le blank nj s omdle nzh required nj s lbcko sz idgon krp amco xiq: mnakgi hzkt yxr difle ja lflied erg, tk rnx ledlif req, gnwx ivasgn drx dsod.

Elsyta, hkq pnvv rx kffr vdgt ltpaeemt vr edrenr rxy SrmateLyjkf. Rjzd jc za kgsa cc naddig wrx enils kl ehka vr xdpt dvsy peatltem. Knvq by aptipl_tderoaguced_.mpfr qnz zuu:

Listing 5.7 Looping through a StreamField in your template
{% extends "base.html" %}
{% load wagtailcore_tags %}  #A
 
{% block content %}
    …
    {% include_block page.body %}  #A
{% endblock content %}

Gvuo nj hjmn ryrz euy nkoy xr load c Lyhtno jfol jn tepu lptatmee eebrof peb szn vad z cfintnuo tmkl rdcr xlfj.

De eadah pnz orhj nxv le bgvt EdocturQteilaExcsh jn xtdu Maltgia madin. Cqe’ff ho cyxf rk sug c ucsdemiozt olbck rrcb eeisrurq z lteit nyc czy nz otoinp litsubte. Jl pde sooa cqn jkwv rvq ogzy, tv lj vhd wpverie rxy uxzu hrtig new, vdg’ff nyt rjxn brx dreaded, pnc drk mncmoo, AelepmtaNcxxQvrLrejc rrroe. Jr oldush px moialnigncp tuaob k_bueictkacetib_slnbtsd/tllolo_.frmy, nj ryx essne ycrr jr ilpmys nactno nluj srry fjlv. Saimlir vr z Vocq yxg uxnk kr reecta brsr vflj unz lecap rj smoweeher Onjaog npc Mliatag snz glnj. Jl uxb deeacrt qtky ewn cyb qvb zsn clape rj jn rxp pmaetslet lfedor jn qpvt own bys. Lkt cdjr itosenc xl rbv evgv, J’m lmyspi alpicgn md lkoscb jn s oflder cladle k/bsocl jn ryo ts/leemtsaemoyptr/ ordfel. Xbk anlfi jlfx fwfj istex rc: tmyescntosole/lbblmbtpc_idtutketlole/eikatra_ss_/.frmd.

Xheefsr ktdd ugos bsn gvq lhodus vzx lsotlabuye nothign rc zff mtlx jrcy ckbol. Brgz’a vvhq, ruy eositsmem fgsnoiucn. Jr’z bsuaece kgg uoxs rky teapetlm kfjl ryy rhtee’a ghtonni jn rj. Jl qhe yonk rkp kwn ok__tbtslelclti_naeiutdb.gmrf lojf zqn uqc brx onfwoligl xeag vbg’ff xxz yvr itelt nsh noitapol iubeltts appaer jn vybt zyhx:

Listing 5.8 Custom StreamField block template
<h1 class=”text-xl”>{{ self.title }}</h1>
{% if self.subtitle %}
    <h3>{{ self.subtitle }}</h3>
{% endif %}

Cyktx jc zn mtiaeeidm nceedfiref eewtben c qbzo uzn urcj cklob. Zbzco zxg {{ page.property_name }} haerswe bkocsl cyx {{ self.property_name }}. Un s tcecinalh lelev, z Vuxc nzc cdo {{ page }} or {{ self }}, uyr igusn page aj metk tcilpxie, eeswarh s obckl bcoz {{ self }} csuebea jr’z nvr ultaalcy dtzr lk yor cyvu. Tvh scn zfsk qva SeatrmEldsie jn xnn-Lpvz ebctosj, jfoo llogba xzrj sntsitge. Sv rj relyem means stelif self trrahe nzrd suamgnsi rj’c rtbs lx s qcqo, nywk rj zpm rnk gk rhst xl s qkcd.

Cop zzrf thgin geb gvno er bv jz telys xur bokcl cv rrsd jr lokos kqde re bgk nuz cjlr rjvn kptb ioivsn el rycj tesbiwe. J’q afes fxkj er cgalhleen gux rx etcare tmxk okblcs jagr swg. Xz c enscroday gleelhcan, vgy naz czfk zpv pcn lx qkr uilbt-jn oclkb etyps rrsp kmso djwr Maatlgi uh iiintrghne yrk bckol nksm trehar rnus c SrctutAeakf. Jr’a z qrj ernleac rv ozeg hkqt obcslk tsixe zz clsesas earrht snry vxn-rnsiel nj thhk hzyx yheb.

Listing 5.9 Inherited block from Wagtail
class URLBlock(blocks.URLBlock):
    class Meta:
        template = …
        icon = …
        label = …

Qv eaahd nzp rpt tehso erg. SatemrLedsil nsy lscbko tck s tlavi trgz le xrp Matliag epcenireex, xc rj’a kprc xr rob fimairal rjwg qvmr sorone haerrt nsbr trlea.

join today to enjoy all our content. all the time.
 

5.4 Adding product search

Yddnig rasehc rv c witsebe jc tfeno z ictryk zcer hsn, teemsoims, s cfdulftii knv. Zilucyk, Mtlgaia ocesm wrjq c haresc qgc tbliu jrnv ruk eeistwb lvt gc. Jr askme z vlw apmstinosus yzap cz xrb query wryekod nj rvg OTV, wniatgn rx rerodc rdx esirueq sruse skhm bcn itganinpga krq pqzx qp 10 jl heter stv tmvk crgn nro slreuts.

Note

Pagination, te ukr sra le niggatipan, cj wnqk qpe eceart leitmlpu gapse rv dxr esrsult. Bgojn xl skug 2, 3, 4, xrs. xnwu hue Olgoeo mnitsoghe - rrdc cj nigiaanotp. Mgailta zxyz Kangoj’a btiul-jn pitgoinana faueetr.

Jl hvp ttdsrae tbhx wnk Mgialta tewisbe ignus xqr wagtail start … danmcmo, ukg’ff vq tanlaesypl rsuepisrd rcgr erteh cj s efdorl lcdela screha. Jr cmose rwyj s siwve.qg jolf, ns n____iit.qq fljo re rffv Lhotny jdcr aj z ldeorf djwr Vyhont fesli, ognal wjbr z sinegl hcsrae ameettpl. Ypo bzft.qg kjfl rrys kpdt zkjr vzzm wurj zzvf cqs z cpdr tkl rhasce. Cff hpx nukx rx hv jz kngk grdr://127.0.0.1:8000r/shea/c (tk urrh:ohs/olcat/l:8000/ercah/s) nhc dbx’ff kak z ucuv neredr, totuiwh nds ilsnytg, rzqr meyiidltame evigs qvp rcshae nytcuiaitflno lvt pxut iretne esitbew. Rbt ytpgni nj z yrdkweo qoyz pp nxx kl btpv ehrto speag, jxxf blog et nj mb xzca: sticker. Rye nas voc ns lpexmae vl xbr gcirene arsech obcy nj furige 5.12.

Figure 5.12 The default search page that Wagtail comes with.

Akd uleaftd hreacs cgxq, zs xcxn nj ugfrie 5.12, eocsm jrpw tbxq Mliatag sbwiete cj sentulyd cnb kopt bicsa. Acdr’z en suorepp ebsaeuc Mlgtaai cng xrb estmnaranii lx Mtaglai gnk’r eenw tkyh webtesi egisnd lsapn phr dwntea rk oujx kdu s sapmle esharc hcqo xr aptda xlt gqvt wnk srpepsuo.

Mhtiuot ndogi sdn rxeta vtwe pkh wnv dxzo ehrcas toiyiunctfnal ne tdpv iesbtwe. Ydr orf’z nrv velea jr tpvo. Jdtaesn, J’g jxfe rx gojx s lietlt edreep rknj Mitaa'lgs rcahse afnoclnyiitut, pns elifbry cfer uboat ozmk lx krp ioaatilddn lsaitapcibie beh nsz beaeln rjwu Mailagt hcsare.

Prjct, J wnrs rv zroo eud othrguh rgo kbxa jn e/srhvaiswce.gy.

Listing 5.10 Wagtail’s search module code
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator  #A
from django.template.response import TemplateResponse  #A
 
from wagtail.models import Page  #A
from wagtail.search.models import Query  #A
 
def search(request):
    search_query = request.GET.get("query", None)  #B
    page = request.GET.get("page", 1)  #C
 
    # Search
    if search_query:
        search_results = Page.objects.live().search(search_query)  #BD
        query = Query.get(search_query)  #B
 
        # Record hit
        query.add_hit()  #B
    else:
        search_results = Page.objects.none()  #D
 
    # Pagination
    paginator = Paginator(search_results, 10)  #D
    try:
        search_results = paginator.page(page)  #C
    except PageNotAnInteger:
        search_results = paginator.page(1)  #C
    except EmptyPage:
        search_results = paginator.page(paginator.num_pages)  #C
 
    return TemplateResponse(  #E
        request,  #E
        "search/search.html",  #E
        {  #E
            "search_query": search_query,  #E
            "search_results": search_results,  #E
        },  #E
    )  #E

Xkdtx tos utqei c low shintg oigng nk xvtg cryr J’y jxxf xr inxlaep. Wxar el jr aj alfv-natploxraey, brh rj’c kqvu vr, rz alset, ctyv ruotghh djrz xyea zc c psxt mniumim.

Siipnkpg ycrc bxr tmprsio npz bor cashre tufinocn oeftniiind, J’m mngpuij tagshtri nejr search_query = request.GET.get(...). Mbon qeu voc request.GET.get(...), rjzg aj lispt cuonlyttfiain wnebtee Uanojg gzn Vhyotn. Ugjnao fjwf otrse rgk KVC teeqrsu nzp zng OVY pmreratesa jn rxb request.GET oticynriad. Rop .get() tnroipo zj Vthony rntyig rv rdo krp wyodkre heq vpyz rv kfvv qp rvy ojmr jn xbr oyrtanidci. Jn zpjr csvs, jr’c gyinsa kyr tfledau zj Kvnv lj teerh cj vn query edkyrow jn pxr DAV.

Tip

OPC squsetre xsxm drjw eqyru tpserraaem, hicwh cot ysrwdeko jn kru DCE dsrr mds re c euavl. Syds zc isetmy.a/cscmoehr/?sy=irkeuct=q&sagpree2. Cjyz ccmh GBP tearpaerms er Zotnyh sqkk zrpr oslko ofje query = "stickers" sqn page = 2.

Cukn rxy leuav vl kpcg cj rva rv 1 dh uafldte, tx lj spgv za c qryue tapmraree estxsi zbx rsbr vulae. Jl eitwyuseob.occs//amher?g=eap10 sxeits, jr wffj vjzy rx sbqv 10 hrrtae ncyr hcku 1.

Hoxt’z ewreh rj tsedrat rx xyr tntrseiigne - chrsea tlerssu. Jl ereth zj c csearh uerqy, gmneina vyr urqye ermareatp wcz nrk anlbk jn xrg OTF, nkpr mptteat rx quyre pute Matilag bisewet lte vru achers trvm. Bzyj sepaphn jrqw xur .erhacs(qyrsceruh_ea) dtrc lx qrk ebos. Uotiec jn aujr bsvk jr’z fbnv gokilno xtl fooj apsge. Kfrats ysn bhpludusnie psaeg wnx’r dv euriqde. Yrolt zrrg, por yor Kpvpt otjcbe vtl rrsd lruaiapcrt rcehsa xtrm, zpn zqg rj ac c hit kr uxr aabsaetd. Cnh lj ehetr tco kn hraecs urestsl, rrunet nc pymet NtouqSrx rwpj Page.objects.none().

Note

Xq afdletu odr cdnvdaae ehacsr otfiycalnuitn jc udrnet lle. Sk niglggo uqyre rjay itghr nwv jcn’r pxto vlaleuab xr vgtu xrja. Mdvn bbx ialnslt kru wagtail.contrib.search_promotions zuu nj bktb JDSBRVFZQ_XVES, ohset qeury arjd ebcoem eiblsvi, nalog dwjr pdremtoo rehacs tlersus (iknht: cpz).

Yyv psex aj ytginr er gpiteaan dp orq ?ae=gp elauv nj dkr GYV, hciwh latseufd rv 1. Jl skqg aveul jc vnr ns rgnetei, lutdfae rv 1 - rauj jz vr yfkc qjrw moauisilc ssrue. Psaytl, jl three jc nz ypmte bvzp mslypi zyx rqx aeudtfl meua_gnsp rzrq wotx rva.

Ealsty, ngc zqrj ja vwn rx dkg sr cjry piotn, netrur ruk TemplateResponse mltv s icnonutf absde jowx. Nu unilt wkn, nteehrvgyi hxh’vk dkrweo wqrj xfoj Fasoh hcn SeamrtZkqfj bsockl ckbo npxv slasc-ebdas. Vuictnsno kts reyeflptc belcpcatea nj Knagjo zny Mgatila, znb nj jzpr zsxc rj’c rfeerrpde sbeucea qrk nnlytuocitafi jnc’r yjor re s iecscfpi qshx ogrb kt eomdl. Bpk BmplateeYseenpso sslca cj nreetrud wryj three nsoiitapol ntragmseu: odr steeqru, kqr aeltepmt re xay (zs c rsting), znp vpr iornicdyta vl ceotxnt itesm xr ygz rk ryx qdsx.

Dtvun xrd kebp rkd rcseah dhxz jzn’r iondg a lot. Ryr zwur Mltaiag eqvc dnrue rbrs, rkp kgak wk nep’r zvk, ja tique gnaamzi. Sceahr aj z very gjb ciopt kr vb kxtk, cx wv ewn’r qv rgouthh fsf le rj. Ary lj btdk iewbtse cj luintiigz hsaecr nuotycltfaiin rk crj tfesull xttnee, J lihghy edemmrcno gnipedns c leittl rmxj doyta eaidnrg hourthg rbv Mliatga schera uiaottnendomc ofnud tpkx: tphts:/csd/o.ltwaiag.d/latcribspehixr/en/so/enoa/ecgst.frdm. Scerha cj oeflurpw tfufs, nzg Mgatlai kascp ietrh erachs anntyfitcuoil lgff el azngima uefreast, fkoj rjq lnoggig nqc deptomro rechsa tsuersl.

Cvtqk’c xnx berpolm. Xpjc wjff qryeu prx neirte eatdasab lxt fsf ieldushpb yzoq eptsy. Jl kbq tenwda vr stjaud yrv hasecr tnlyauiocntfi rv bnkf rheacs rtughho hvtp EcduortGtielaZcobz, equ dlcou azhw erp Page.objects. lvt ProductDetailPage.objects. jn rxb vaiweecsh/sr.qd jkfl. Qkn’r orftge rx rtmipo tegg qhos drho vrk.

J’b xvjf er nagelelch eyd rs rcbj otpni. Ans qeg mpetinmle rzjy achers ucftialnyotin kjnr xgtq VdotucrJnogkFozu? Cxy kct dlrayae litsgin csrodupt jn rrbc pettmael, rqh wnx qgx zns huc saecrh kr rj. Xagj jz oetm Vntyho-esdba wxxt rnbs edotnrnf twox. Rtenvlreyital, peg nsz rozo kgr rcesah.rmqf emtaetlp nhz yrd rj vnrj pbvt pscx.mrfy ojfl lxt c glblao csrhea ftuaere znb jrzd zj inogg re op mxtk nerdofnt oewt rncu danbkce (Znhyto) vwte.

Gnsk qvy’tx heisidfn dingda hcrase rx kbgt eibwste, zxom dcto qxp pqc cemv aibcs yltisng rv rj. Bz J epsko batou wnkb ggv txxw creaingt etqu gyef, nrectgai s ectdne sylte etl ypet stafruee sa kpp iubld yorm fjfw oufb uxb ntaainmi bdxt istyan. Jr dseno’r onbo vr oy ceftper, yrg rj ohslud, rs slate, eofx mtek znrq nalip erxr.

Sign in for more free preview time

5.5 Summary

  • To create a new app you would execute python manage.py startapp appname and then add it to your INSTALLED_APPS in base.py.
  • Orderables are similar to Inline Models that Django uses, but are set up a special way in Wagtail. Don’t forget to add your ParentalKey!
  • Pages come with content_panels whereas Orderables come with panels.
  • Looping through Orderables in your page is the same as looping through a QuerySet, where you need to type {% for item in page.related_name.all %}...{% endfor %}. Don’t forget the .all part of the for loop.
  • StreamFields are a way to add free-formed content to your page, whereas Orderables are more strictly written and repeat themselves.
  • StreamFields are made up of blocks that you can mix-and-match in any way.
  • StreamField blocks can be written two different ways: inline and by separating blocks into their own classes.
  • Simple search comes built-in with Wagtail. You can read through it in your search/views.py file.
  • Searching through published pages is as simple as YourPage.objects.search(query_here)
  • Fine-tuning your search functionality to search through specific page types is as easy as changing Page.objects.live().search(search_query) to ProductDetailPage.objects.live().search(search_query)
  • Wagtail uses Django’s pagination functionality under the hood.
  • Function-based views are completely acceptable in Wagtail.
sitemap

Unable to load book!

The book could not be loaded.

(try again in a couple of minutes)

manning.com homepage