Přejít k navigační liště

Zdroják » Různé » Django: Rozšiřování možností Djanga

Django: Rozšiřování možností Djanga

Články Různé

Holá instalace Djanga má mnoho různých funkcí. Určitě však časem zjistíme, že nám nějaká maličkost chybí. Proto se v tomto díle podíváme na několik ukázek možného rozšíření.

Přidání vlastního filtru do šablony

Určitě si vzpomínáte na šestý díl seriálu, kde jsme se učili prezentovat data pomocí generických pohledů. V příkladu jsme si vypsali mimo jiné e-mailovou adresu provozovny. Tyto adresy nejsou nijak chráněné, takže je může zaznamenat i ten nejhloupější spambot, což představuje problém. Proto si napíšeme jednoduchý filtr, pomocí kterého e-mailovou adresu transformujeme do zakódovaného řetězce v JavaScriptu.

Filtr je vlastně obyčejná funkce, které předáme nějaký vstup a ona vrátí odpovídající výstup. Každá aplikace, která je uvedená v konstantě INSTALLED_APPS v souboru settings.py, může mít svou sadu filtrů a značek. Stačí v adresáři aplikace (v našem případě video_store) vytvořit podadresář templatetags a umístit do něj dva soubory. První je potřeba pojmenovat __init__.py a bude stačit, když bude prázdný. Označuje totiž, že daný adresář obsahuje modul napsaný v Pythonu. Druhý soubor můžeme pojmenovat libovolně, já si zvolil název misc.py, protože do tohoto souboru potom možná časem přidám další různorodé funkce (anglicky miscellaneous). Obsah souboru vypadá takto:

# coding: utf-8
from base64 import b64encode
from django import template
from django.utils.safestring import mark_safe
from django.template.defaultfilters import stringfilter

register = template.Library()

@register.filter
@stringfilter
def email(value):
    return mark_safe('<script type="text/javascript">display_email("%s");</script><noscript>(e-mail je chráněn JavaScriptem)</noscript>' % b64encode(value))

Na sedmém řádku se nachází přiřazení, které určuje, že se jedná o knihovnu filtrů a značek. Proměnná se musí jmenovat register a musí obsahovat objekt template.Library — takto to stanovuje konvence. Na devátém a desátém řádku můžeme vidět dva dekorátory. První z nich (@register.filter) registruje nový filtr. Kdybychom chtěli přidat novou značku, napíšeme místo toho @register.tag. Tento dekorátor má nepovinný parametr name, jež určuje název nového filtru či značky. My jsme ho vynechali, takže se název filtru odvodí z názvu funkce. Druhý dekorátor dbá na to, aby funkce dostala jako vstup řetězec. V případě, kdy by filtr byl připojen např. k číslu, by při zpracování šablony došlo k vyhození výjimky AttributeError. Tento dekorátor také převádí objekty na řetězce voláním metod __str__ nebo __unicode__.

Samotný filtr vezme hodnotu a vrátí HTML kód s JavaScriptem. Funkce mark_safe označí řetězec za bezpečný. Nedojde tak k automatickému escapování HTML značek a entit, takže se kupříkladu místo kódu &lt;noscript&gt; vypíše očekávaná hodnota <noscript>. Tuto vlastnost vypínejte s rozmyslem, hlavně při vypisování uživatelem zadaných dat. Pokud byste chtěli ošetřit uživatelem zadaná data sami, můžete k tomuto účelu použít funkci escape z modulu django.utils.html. V našem případě zaručíme bezpečnost vstupu tím, že ho zakódujeme pomocí kódování base64, které obsahuje pouze písmena abecedy, číslice a znaky plus, lomítko a rovnítko (viz RFC 3548). Takto zakódovaný e-mail spambot rozezná těžko.

Dále nesmíme zapomenout upravit šablonu s výpisem poboček (templates/stores.html):

{% extends "base.html" %}
{% load misc %}

{% block content %}
<h1>{% block title %}Provozovny{% endblock %}</h1>

{% for object in object_list %}
  <h2>{{ object.store }}</h2>

  <ul class="store">
  <li>{{ object.address }}</li>
  <li>{{ object.city }}</li>
  <li>{{ object.postal_code }}</li>
  {% if object.email %}
    <li>{{ object.email|email }}</li>
  {% endif %}
  </ul>

  {% if object.description %}
    <p>{{ object.description }}</p>
  {% endif %}
{% endfor %}
{% endblock %}

V tomto souboru přibyla na druhém řádku značka pro načtení našeho modulu s filtrem misc.py. Na patnáctém řádku se e-mail nevypisuje přímo, ale přes filtr email což zatím nebude fungovat, protože nemáme definovanou javascriptovou funkci display_email. Přesto se ale můžeme podívat na to, co uvidí uživatelé s vypnutým JavaScriptem.

Django 12

Založíme si tedy někde v adresáři static javascriptový soubor, který poté načteme přes značku &lt;script&gt; v šabloně templates/base.html. Tento soubor bude obsahovat již zmiňovanou funkci pro výpis e-mailu:

function display_email(str) {
    email = b64decode(str);

    document.write('<a href="mailto:' + encodeURI(email) + '">' + email + '</a>');
}

Na druhém řádku se volá funkce b64decode pro převedení zakódovaného řetězce do původní podoby. Ta v JavaScriptu není standardně implementována, takže jsem ji si musel napsat sám. Protože je však celkem rozsáhlá a pro další vysvětlování není potřeba, případní zájemci se na ni mohou podívat v přiloženém ukázkovém příkladu (soubor static/js/scripts.js). Co se týče čtvrtého řádku této funkce, ten zobrazí uživateli klikatelný e-mail.

Django 12

Přidání proměnné do kontextu

Opět navážeme na poznámku ze šestého dílu seriálu, kde jsme se zmínili o kontextových procesorech. Díky nim můžeme v šablonách používat společné proměnné (což je např. {{ MEDIA_URL }} nebo {{ user }}), stačí vždy při volání metody render_to_response uvést parametr context_instance=RequestContext(request). Konstanta TEMPLATE_CONTEXT_PROCESSORS určuje, které kontextové procesory se v projektu použijí. V dokumentaci Djanga je popsáno několik základních procesorů, my si napíšeme vlastní.

Zadavatel našeho projektu dostal šílený nápad, že by se v hlavičce webu měla zobrazovat náhodně některá z předem připravených marketingových hlášek. Protože se tato funkce týká všech pohledů, při implementaci přímo v pohledech, by došlo k zbytečnému duplikování kódu. K tomuto účelu je lepší vybranou hlášku předat šabloně jako globální kontext. Náhodné vypisování by se to sice dalo vyřešit jednoduchým kódem v JavaScriptu, ale myslím, že skriptování v prohlížeči už dnes bylo dost.

Soubor s funkcí, která přidává další kontext, si můžeme založit kdekoliv. Například přímo v adresáři projektu. Pojmenujeme ho jako context_processors.py:

# coding: utf-8

from random import choice

def nonsense(request):
    quotes = [
        'Jsme nejlepší!',
        'Naše tituly do vašeho přehrávače.',
        'Dobrý den je, když si pustíte film.',
        'Je přece správné platit za půjčování.',
        'Tohle u konkurence nenajdete.',
    ]

    return {'NONSENSE': choice(quotes)}

Funkce pro přidání kontextu požaduje jako parametr objekt Request a vrací slovník s deklaracemi proměnných. Bývá zvykem proměnné z kontextového procesoru zapisovat verzálkami, aby se odlišily od těch z pohledů. V naší funkci náhodně vybíráme jeden z blábolů, ke kterému poté budeme mít možnost přistupovat pomocí proměnné {{ NONSENSE }}.

Tento kontextový procesor je potřeba přidat do nastavení. Otevřeme si tedy soubor settings.py a dopíšeme do něj následující řádky:

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'hrajeme_si.context_processors.nonsense',
)

První čtyři procesory jsou výchozí, ten poslední je náš. Teď už stačí jenom upravit v hlavní šabloně templates/base.html horní část webu:

<div id="header">
Videopůjčovny s. r. o.
{% if NONSENSE %}
  <div id="nonsense">{{ NONSENSE }}</div>
{% endif %}
</div>

Django 12

Související odkazy

Příště se podíváme na tvorbu vícejazyčných webů.

Komentáře

Odebírat
Upozornit na
guest
0 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
Zobrazit všechny komentáře

Přístupnost není jen o splnění norem: nový pohled na inkluzivní design

Přístupnost a inkluze možná nepatří mezi nejžhavější témata digitálního světa – dokud o nich nezačne mluvit Vitaly Friedman. Na WebExpo 2024 předvedl, že inkluzivní design není jen o splněných checkboxech, ale hlavně o lidech. S energií sobě vlastní obrátil zažité přístupy naruby a ukázal, že skutečně přístupný web je nejen možný, ale i nezbytný.

Efektivnější vývoj UI nebo API: Co si odnést z WebExpo 2025?

Různé
Komentáře: 0
Jak snadno implementovat moderní uživatelské rozhraní? Které funkce brzdí rychlost vašeho webu? A kdy raději sami přibrzdit, abychom využitím AI nepřekročili etické principy? Debatu aktuálních dev témat rozdmýchá sedmnáctý ročník technologické konference WebExpo, která proběhne v Praze od 28. do 30. května. Který talk či workshop si rozhodně nenechat ujít? Toto je náš redakční výběr z vývojářských hroznů.

Zapřáhněte AI jako nikdy předtím. Květnová konference WebExpo přivítá hvězdy technologického světa

Od 28. do 30. května 2025 promění pražský Palác Lucerna na tři dny technologická konference WebExpo. Na programu je více než 80 přednášek a workshopů od expertů z celého světa. WebExpo tradičně propojuje vývojáře, designéry, marketéry i byznysové lídry a nabízí praktické dovednosti, strategické myšlení a přináší nejnovější trendy nejen v oblasti AI.