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

Stav SIMD v Rustu v roce 2025

Různé
Komentáře: 1
SIMD - neboli Single Instruction, Multiple Data - znamená, že procesor může jednou instrukcí zpracovat více datových prvků najednou. Typicky to znamená, že místo sčítání dvou čísel přičtete dvě sady čísel paralelně. To může přinést výrazné zrychlení například při zpracování obrazu, audia nebo numerických výpočtů. Pokud již SIMD znáte, tato tabulka je vše, co budete potřebovat. A pokud s SIMD teprve začínáte, tabulku pochopíte do konce tohoto článku

GPUI Component: moderní Rust GUI komponenty pro cross-platform desktop aplikace

Různé
Komentáře: 0
GPUI Component je open-source Rust knihovna rozšiřující framework GPUI o více než 60 moderních, nativních a multiplatformních UI komponent. Staví na deklarativním přístupu, stateless renderování a jednoduchém API inspirovaném Reactem či Yew. Díky optimalizovanému výkonu, podpoře témat a flexibilním layoutům umožňuje rychlý vývoj desktopových aplikací, jako je například trading nástroj Longbridge Pro. Knihovna je licencována pod Apache 2.0 a dostupná na GitHubu.