Templates maken met Jinja2 in de flacon geavanceerd

In het eerste deel van deze drieledige instructiereeks hebben we gezien hoe we de sjabloonstructuur in een Flask-gebaseerde applicatie met Jinja2 konden indelen. We hebben ook gezien hoe blokken kunnen worden gebruikt om gebruik te maken van de overerving in sjablonen. In dit deel bespreken we hoe u een aangepast filter, een aangepaste contextprocessor en een macro schrijft.

Ermee beginnen

Ik zal voortbouwen op de catalogusapplicatie die we in het eerste deel van deze serie hebben gemaakt. Eerst zal ik een aangepaste Jinja2 contextprocessor toevoegen om een ​​beschrijvende naam voor elk product te tonen. Vervolgens maak ik een aangepast Jinja2-filter om hetzelfde werk te doen als de aangepaste contextprocessor. Vervolgens zal ik laten zien hoe je een aangepaste Jinja2-macro kunt maken voor reguliere formuliervelden.

Een aangepaste Jinja2-contextprocessor maken

Soms willen we misschien een waarde rechtstreeks in de sjablonen berekenen of verwerken. Jinja2 houdt vast aan het feit dat de verwerking van logica moet worden afgehandeld in weergaven en niet in sjablonen, en het houdt de sjablonen dus schoon. Een contextprocessor wordt in dit geval een handig hulpmiddel. We kunnen onze waarden doorgeven aan een methode; dit wordt dan verwerkt in een Python-methode en onze resulterende waarde wordt geretourneerd. Daarom voegen we in feite gewoon een functie toe aan de sjablooncontext (met dank aan Python voor het toestaan ​​dat we functies net als elk ander object doorgeven).

Laten we zeggen dat we een beschrijvende naam voor elk product in de indeling willen toevoegen Categorie / Productnaam. Hiervoor moet een methode worden toegevoegd, die moet zijn versierd met @ app.context_processor.

@ app.context_processor def some_processor (): def volledige naam (product): retourneer '0 / 1'. format (product ['categorie'], product ['name']) retour 'volledige naam': volledige naam

Technisch gezien is een context slechts een Python-woordenboek dat kan worden aangepast om waarden toe te voegen en te verwijderen. Elke methode met de opgegeven decorateur moet een woordenboek retourneren dat de huidige toepassingscontext zou bijwerken.

Als u deze contextprocessor wilt gebruiken, voegt u gewoon de volgende Jinja2-tag toe aan de sjabloon.

volledige naam (product)

Als we dit daaraan toevoegen flask_app / templates / product.html van onze applicatie, zou het eruit zien als:

% breidt 'home.html'% % block container% uit 

volledige naam (product)

productnaam'] product categorie']

$ product ['price']

% endblock%

De resulterende productpagina zou er nu als volgt uitzien:

Een aangepast Jinja2-filter maken

Na het bovenstaande voorbeeld te hebben bekeken, zouden ervaren ontwikkelaars kunnen denken dat het stom was om hiervoor een contextprocessor te gebruiken. Men kan eenvoudig een filter schrijven om hetzelfde resultaat te krijgen; dit maakt de dingen veel schoner. Een filter kan worden geschreven om de beschrijvende naam van het product weer te geven, zoals hieronder wordt getoond.

@ app.template_filter ('volledige_naam') def full_name_filter (product): retourneer '0 / 1'. format (product ['categorie'], product ['naam'])

Dit filter kan net als een normaal filter worden gebruikt, d.w.z. door een toe te voegen | (pijp) symbool en vervolgens de filternaam.

product | volledige_naam

Het bovenstaande filter zou hetzelfde resultaat opleveren als de contextprocessor een tijdje geleden liet zien.

Om dingen naar een hoger niveau te tillen, maken we een filter dat de valuta opmaakt op basis van de lokale taal van de huidige browser. Hiervoor moeten we eerst een Python-pakket met de naam installeren CCY.

$ pip ccy installeren

Nu moeten we een methode toevoegen voor het valutafilter.

import ccy uit kolf importverzoek @ app.template_filter ('format_currency') def format_currency_filter (amount): currency_code = ccy.countryccy (request.accept_languages.best [-2:]) retourneer '0 1'. format ( wisselkoers)

Om dit filter te gebruiken, moeten we het volgende in onze sjabloon toevoegen:

product ['price'] | format_currency

Nu zou de productpagina er als volgt uitzien:

Een aangepaste Jinja2-macro voor formulieren maken

Met macro's kunnen we herbruikbare stukken HTML-blokken schrijven. Ze zijn analoog aan functies in reguliere programmeertalen. We kunnen argumenten doorgeven aan macro's zoals we doen met functies in Python en ze vervolgens gebruiken om het HTML-blok te verwerken. Macro's kunnen elk willekeurig aantal keren worden aangeroepen en de uitvoer zal variëren volgens de logica erin. Het werken met macro's in Jinja2 is een veel voorkomend onderwerp en heeft veel gebruiksgevallen. Hier zullen we alleen zien hoe een macro kan worden gemaakt en vervolgens worden gebruikt na het importeren.

Een van de meest overtollige stukjes code in HTML is het definiëren van invoervelden in formulieren. De meeste velden hebben dezelfde code, met enkele aanpassingen aan de stijl enzovoort. Het volgende is een macro die invoervelden maakt wanneer deze wordt aangeroepen. De beste methode is om de macro in een afzonderlijk bestand te maken voor bijvoorbeeld betere herbruikbaarheid, _helpers.html:

% macro render_field (naam ,, type = "text") -%  % - endmacro%

Nu moet deze macro worden geïmporteerd in het bestand dat moet worden gebruikt:

% from '_helpers.jinja' import render_field%

Vervolgens kan het eenvoudigweg worden opgeroepen met behulp van het volgende:

render_field ('gebruikersnaam', 'icon-user') render_field ('wachtwoord', 'pictogram-toets', type = "wachtwoord") 

Het is altijd een goede gewoonte om macro's in een ander bestand te definiëren om de code schoon te houden en de leesbaarheid van de code te vergroten. Als een privémacro die niet toegankelijk is uit het huidige bestand nodig is, geeft u de macro een naam met een onderstrepingsteken voorafgaand aan de naam.

Conclusie

In deze zelfstudie hebben we gezien hoe een aangepast filter, een aangepaste contextprocessor en een aangepaste macro voor formulieren kunnen worden geschreven. In het volgende deel van deze serie zullen we zien hoe we geavanceerde datum- en tijdopmaak op sjabloonniveau in Jinja2 kunnen implementeren met behulp van moment.js.