= Násobky a delitele s dekorátorom = == Mechanizmus dekorátorov == V [[ProgramovanieInternetovychAplikacii/NasobkyADelitele | projekte násobky a delitele]] sme porušili zásadu neduplikovania kódu. Vo {{{views.py}}} sa opakovala kontrola parametra cislo. Potrebujeme nejako vytiahnuť spoločný kód von z views. Toto je možné vyriešiť niekoľkými spôsobmi, jeden elegantný je tu. Využijeme to, že funkcia v pythone je objekt ako každý iný. Pozrite sa na tento kód: {{{#!python def skontroluj_cislo(f): # * __dekorovane_f je funkcia s dvomi premennymi # ocakava, ze v nadradenom prostredi je nastavena premenna f def __dekorovane_f(request,cislo): # cislo je retazec # musime ho previest na int # treba kontrolovat vstup uzivatela! try: cislo_int=int(cislo) except ValueError: return chyba("%s sa nepodarilo previest na cislo" % cislo) if cislo_int<0: return chyba("cislo %d je zaporne" % cislo_int) return f(request,cislo_int) return __dekorovane_f }}} {{{skontroluj_cislo}}} je funkcia druhého rádu -- ako parameter dostáva funkciu dvoch premenných a vracia funkciu dvoch premenných. Vrátená funkcia robí to isté ako pôvodná, ale predtým skontroluje druhý parameter, a ak je chybný, vráti chybu. Teraz môžeme zmeniť funkciu {{{nasobky}}} takto: {{{#!python # * Toto je povodna funkcia nasobky, z ktorej sme vyhodili # kontrolu cisla # * Ako parameter ocakava uz cislo, nie retazec def nasobky(request,cislo_int): zoz_nasobkov=[] for i in range(11): zoz_nasobkov.append(Dvojica(i,i*cislo_int)) c=Context({'cislo':cislo_int,'vysledky':zoz_nasobkov}) t=loader.get_template("nasobky.html") return HttpResponse(t.render(c)) # * Blizime sa k pointe: # * Nasledujuci riadok obohati funkciu nasobky # o kontrolu parametra cislo. nasobky=skontroluj_cislo(nasobky) }}} A podobne upravíme funkciu delitele. Celý projekt je tu: [[attachment:nasobky_a_delitele_v2.tar.gz]]. == Špeciálna syntax pre dekorátory == Horeuvedený vzor považovali autori Pythonu za dostatočne dôležitý na to, aby mu vyhradili špeciálnu syntax. Nasledujúci kód v má v zásade rovnakú funkciu ako predošlý, líši sa iba syntaxou. Všimnite si, že špeciálna syntax sa nachádza ''pred'' funkciou, takže ju čitateľ kódu neprehliadne. {{{#!python # Teraz pouzijeme specialnu syntax, ktora zabezpeci # obalenie funkcie dekoratorom @skontroluj_cislo def nasobky(request,cislo_int): zoz_nasobkov=[] for i in range(11): zoz_nasobkov.append(Dvojica(i,i*cislo_int)) c=Context({'cislo':cislo_int,'vysledky':zoz_nasobkov}) t=loader.get_template("nasobky.html") return HttpResponse(t.render(c)) }}} Verzia so špeciálnou syntaxou je tu :[[attachment:nasobky_a_delitele_v2.1.tar.gz]] == Viac o dekorátoroch == Horeuvedený text vysvetľuje iba podstatu veci, ak sa chcete dozvedieť o dekorátoroch v Pythone viac, googlite. Django poskytuje niekoľko dekorátorov, ktoré slúžia na dekoráciu views a (typicky) kontrolujú request, či spĺňa nejakú predbežnú podmienku predtým, ako vykonajú normálny kód view. Napríklad {{{login_required}}} a podobne.