{"title":"Γράφοντας δικά σας template tags και φίλτρα","version":"1.11","locale":"el","docname":"howto/custom-template-tags","url":"/el/1.11/howto/custom-template-tags/","canonical":"https://djangodocs.dev/el/1.11/howto/custom-template-tags/","summary":"Η γλώσσα template του Django έρχεται με μια μεγάλη ποικιλία από προεγκατεστημένα tags και φίλτρα που έχουν σχεδιαστεί για να αντιμετωπίσουν τις ανάγκες της…","html":"<h1>Γράφοντας δικά σας template tags και φίλτρα<a class=\"heading-anchor\" href=\"#custom-template-tags-and-filters\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Η γλώσσα template του Django έρχεται με μια μεγάλη ποικιλία από <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/\"><span class=\"doc\">προεγκατεστημένα tags και φίλτρα</span></a> που έχουν σχεδιαστεί για να αντιμετωπίσουν τις ανάγκες της παρουσίασης της εφαρμογής σας. Παρόλ” αυτά, ίσως χρειαστείτε κάποια λειτουργία η οποία δεν υπάρχει στο βασικό πακέτο των template tags και φίλτρων. Μπορείτε να επεκτείνετε την template μηχανή του Django ορίζοντας δικά σας tags και φίλτρα χρησιμοποιώντας, τι άλλο, Python. Αφού τα δημιουργήσετε μπορείτε να τα χρησιμοποιήσετε στα templates σας αφού πρώτα τα φορτώσετε με το tag <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/#std-templatetag-load\"><code class=\"xref std std-ttag docutils literal notranslate\">{% load %}</code></a>.</p>\n<section id=\"code-layout\">\n<h2>Διάταξη κώδικα<a class=\"heading-anchor\" href=\"#code-layout\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Το πιο κοινό μέρος για να προσδιορίσετε τα δικά σας template tags και φίλτρα είναι μέσα στη Django εφαρμογή σας. Αν σχετίζονται, δε, και με την ήδη υπάρχουσα εφαρμογή, τότε είναι πολύ λογικό να ζουν μέσα στο φάκελο της. Αν όχι, τότε μπορούν να προστεθούν σε κάποια καινούργια εφαρμογή. Αν τα δικά σας template tags και φίλτρα αφορούν γενικά το project ή κάποια άλλη λειτουργία, μπορείτε να φτιάξετε μια νέα εφαρμογή πχ my_utils και να τα αποθηκεύσετε εκεί. Όταν ένα Django app προστίθεται στη λίστα <a class=\"reference internal\" href=\"/el/1.11/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\">INSTALLED_APPS</code></a>, οποιοδήποτε tag που είναι ορισμένο στη συμβατική τοποθεσία που περιγράφεται παρακάτω, αυτόματα γίνεται διαθέσιμο για να φορτωθεί μέσα στα templates.</p>\n<p>Η εφαρμογή πρέπει να περιέχει ένα φάκελο <code class=\"docutils literal notranslate\">templatetags</code>, στο ίδιο επίπεδο με τα αρχεία <code class=\"docutils literal notranslate\">models.py</code>, <code class=\"docutils literal notranslate\">views.py</code>, κλπ. Αν ο φάκελος δεν υπάρχει ήδη, δημιουργήστε τον – μη ξεχάσετε να προσθέσετε το αρχείο <code class=\"docutils literal notranslate\">__init__.py</code> για να εξασφαλίσετε ότι ο φάκελος αυτός θα αντιμετωπιστεί ως ένα Python package.</p>\n<aside class=\"admonition-development-server-won-t-automatically-restart admonition\" role=\"note\">\n<p class=\"admonition-title\">Ο development server δεν θα επανεκκινήσει αυτόματα</p>\n<p>Αφού προσθέσετε το module <code class=\"docutils literal notranslate\">templatetags</code>, θα χρειαστεί να επανεκκινήσετε χειροκίνητα τον server πριν χρησιμοποιήσετε τα tags ή τα φίλτρα στα templates.</p>\n</aside>\n<p>Τα δικά σας tags και φίλτρα θα υπάρχουν σε ένα module (όποτε λέμε module εννοούμε ένα φάκελο μαζί με το κενό αρχείο <code class=\"docutils literal notranslate\">__init__.py</code> μέσα του) μέσα στο <code class=\"docutils literal notranslate\">templatetags</code>. Το όνομα αυτού του module θα είναι αυτό που θα χρησιμοποιείτε αργότερα, για να φορτώνετε τα tags/φίλτρα, οπότε να είστε προσεκτικοί στην επιλογή του ονόματος ούτως ώστε να μην προκύψουν modules με το ίδιο όνομα σε άλλη εφαρμογή.</p>\n<p>Για παράδειγμα, αν τα δικά σας tags/φίλτρα βρίσκονται σε ένα αρχείο με το όνομα <code class=\"docutils literal notranslate\">poll_extras.py</code>, η δομή των αρχείων της εφαρμογής σας θα δείχνει κάπως έτσι:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>polls<span class=\"o\">/</span>\n    <span class=\"fm\">__init__</span><span class=\"o\">.</span>py\n    models<span class=\"o\">.</span>py\n    templatetags<span class=\"o\">/</span>\n        <span class=\"fm\">__init__</span><span class=\"o\">.</span>py\n        poll_extras<span class=\"o\">.</span>py\n    views<span class=\"o\">.</span>py\n</code></pre></div>\n<p>Και μέσα στο template σας θα μπορείτε να κάνετε διαθέσιμα τα tags/φίλτρα αυτού του αρχείου ως εξής:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">load</span> <span class=\"nv\">poll_extras</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>Η εφαρμογή που περιέχει τα δικά σας tags πρέπει να βρίσκεται μέσα στα <a class=\"reference internal\" href=\"/el/1.11/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\">INSTALLED_APPS</code></a> προκειμένου το tag <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/#std-templatetag-load\"><code class=\"xref std std-ttag docutils literal notranslate\">{% load %}</code></a> να δουλέψει. Αυτό γίνεται για λόγους ασφαλείας: σας επιτρέπει να έχετε Python κώδικα από πολλές template βιβλιοθήκες σε μια μηχανή χωρίς να δοθεί πρόσβαση σε όλες αυτές για κάθε εγκατάσταση του Django.</p>\n<p>Δεν υπάρχει όριο στον αριθμό των modules που θα βάλετε μέσα στο <code class=\"docutils literal notranslate\">templatetags</code>. Θυμηθείτε όμως ότι το tag <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/#std-templatetag-load\"><code class=\"xref std std-ttag docutils literal notranslate\">{% load %}</code></a> θα φορτώσει τα tags/φίλτρα για το δοθέν όνομα του Python module που βρίσκεται μέσα στο <code class=\"docutils literal notranslate\">templatetags</code>, όχι το όνομα της εφαρμογής.</p>\n<p>Για να είναι μια έγκυρη tag βιβλιοθήκη, το module πρέπει να περιέχει μια μεταβλητή, επιπέδου module, με το όνομα <code class=\"docutils literal notranslate\">register</code>, ήτοι ένα instance της κλάσης <code class=\"docutils literal notranslate\">template.Library</code>, με την οποία όλα τα tags και τα φίλτρα θα γίνουν register. Επομένως, στην αρχή του module <code class=\"docutils literal notranslate\">poll_extras.py</code>, προσθέστε τα ακόλουθα:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django</span> <span class=\"kn\">import</span> template\n\nregister <span class=\"o\">=</span> template<span class=\"o\">.</span>Library<span class=\"p\">()</span>\n</code></pre></div>\n<p>Εναλλακτικά, τα modules του template tag μπορούν να γίνουν register μέσω του argument <code class=\"docutils literal notranslate\">'libraries'</code> της κλάσης <a class=\"reference internal\" href=\"/el/1.11/topics/templates/#django.template.backends.django.DjangoTemplates\" title=\"django.template.backends.django.DjangoTemplates\"><code class=\"xref py py-class docutils literal notranslate\">DjangoTemplates</code></a>. Αυτό είναι χρήσιμο αν θέλετε να χρησιμοποιήσετε ένα διαφορετικό label από το όνομα του module όταν φορτώνετε τα template tags. Επίσης σας επιτρέπει να κάνετε register τα tags χωρίς την εγκατάσταση κάποια εφαρμογής.</p>\n<aside class=\"admonition-behind-the-scenes admonition\" role=\"note\">\n<p class=\"admonition-title\">Πίσω από τις σκηνές</p>\n<p>Για πάρα πολλά παραδείγματα, διαβάστε τους πηγαίους κώδικες του Django σχετικά με τα προεγκατεστημένα φίλτρα και tags. Βρίσκονται στο <code class=\"docutils literal notranslate\">django/template/defaultfilters.py</code> και <code class=\"docutils literal notranslate\">django/template/defaulttags.py</code>, αντίστοιχα.</p>\n<p>Για περισσότερες πληροφορίες σχετικά με το tag <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/#std-templatetag-load\"><code class=\"xref std std-ttag docutils literal notranslate\">load</code></a>, διαβάστε το εγχειρίδιο του.</p>\n</aside>\n</section>\n<section id=\"writing-custom-template-filters\">\n<span id=\"howto-writing-custom-template-filters\"></span><h2>Γράφοντας δικά σας template φίλτρα<a class=\"heading-anchor\" href=\"#writing-custom-template-filters\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Τα παραμετροποιήσιμα φίλτρα είναι απλώς Python συναρτήσεις οι οποίες δέχονται ένα ή δύο arguments:</p>\n<ul class=\"simple\">\n<li><p>Την τιμή της μεταβλητής (input) – όχι απαραίτητα τύπου string.</p></li>\n<li><p>Την τιμή του argument (αν υπάρχει) – αυτή μπορεί να είναι μια προεπιλεγμένη τιμή ή να μην υπάρχει καθόλου.</p></li>\n</ul>\n<p>Για παράδειγμα, μέσα στη σύνταξη του φίλτρου <code class=\"docutils literal notranslate\">{{ var|foo:&quot;bar&quot; }}</code>, το φίλτρο <code class=\"docutils literal notranslate\">foo</code> θα λάβει μια μεταβλητή <code class=\"docutils literal notranslate\">var</code> (input) και ένα argument <code class=\"docutils literal notranslate\">&quot;bar&quot;</code>.</p>\n<p>Εφόσον η γλώσσα του template δεν παρέχει exception handling, κάθε exception που θα γίνει raised από ένα template filter θα εμφανιστεί ως server error. Επομένως, οι συναρτήσεις των φίλτρων θα πρέπει να αποφεύγουν να κάνουν raise τυχόν exceptions αν υπάρχει κάποια λογική τιμή να επιστραφεί, ως fallback. Σε περίπτωση κάποιου input λόγω του οποίου φαίνεται ξεκάθαρα κάποιο bug στο template, το να κάνετε raise κάποιο exception είναι καλύτερο από το να το αφήσετε απαρατήρητο κάτι το οποίο θα κρύψει το bug.</p>\n<p>Παρακάτω φαίνεται ένα παράδειγμα ορισμού ενός φίλτρου:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span> <span class=\"nf\">cut</span><span class=\"p\">(</span>value<span class=\"p\">,</span> arg<span class=\"p\">):</span>\n    <span class=\"sd\">&quot;&quot;&quot;Removes all values of arg from the given string&quot;&quot;&quot;</span>\n    <span class=\"k\">return</span> value<span class=\"o\">.</span>replace<span class=\"p\">(</span>arg<span class=\"p\">,</span> <span class=\"s1\">&#39;&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Και εδώ φαίνεται ένα παράδειγμα του πως θα χρησιμοποιηθεί αυτό το φίλτρο στο template:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{{</span> <span class=\"nv\">somevariable</span><span class=\"o\">|</span><span class=\"nf\">cut</span><span class=\"s2\">:&quot;0&quot;</span> <span class=\"cp\">}}</span>\n</code></pre></div>\n<p>Τα περισσότερα φίλτρα δεν παίρνουν arguments. Σε αυτή την περίπτωση, απλώς αφήστε το εκτός από την συνάρτηση σας. Παράδειγμα:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span> <span class=\"nf\">lower</span><span class=\"p\">(</span>value<span class=\"p\">):</span> <span class=\"c1\"># Only one argument.</span>\n    <span class=\"sd\">&quot;&quot;&quot;Converts a string into all lowercase&quot;&quot;&quot;</span>\n    <span class=\"k\">return</span> value<span class=\"o\">.</span>lower<span class=\"p\">()</span>\n</code></pre></div>\n<section id=\"registering-custom-filters\">\n<h3>Κάνοντας register τα δικά σας φίλτρα<a class=\"heading-anchor\" href=\"#registering-custom-filters\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.template.Library.filter\">\n<span class=\"sig-prename descclassname\">django.template.Library.</span><span class=\"sig-name descname\">filter</span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.template.Library.filter\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Όταν γράψετε τον ορισμό του φίλτρου σας, θα χρειαστεί να το κάνετε register με το instance της κλάσης <code class=\"docutils literal notranslate\">Library</code>, για να το κάνετε διαθέσιμο στη γλώσσα template του Django:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>register<span class=\"o\">.</span>filter<span class=\"p\">(</span><span class=\"s1\">&#39;cut&#39;</span><span class=\"p\">,</span> cut<span class=\"p\">)</span>\nregister<span class=\"o\">.</span>filter<span class=\"p\">(</span><span class=\"s1\">&#39;lower&#39;</span><span class=\"p\">,</span> lower<span class=\"p\">)</span>\n</code></pre></div>\n<p>Η μέθοδος <code class=\"docutils literal notranslate\">Library.filter()</code> παίρνει δύο ορίσματα:</p>\n<ol class=\"arabic simple\">\n<li><p>Το όνομα του φίλτρου – τύπου string.</p></li>\n<li><p>Τη συνάρτηση του φίλτρου – μια Python συνάρτηση (όχι το όνομα της συνάρτησης ως string).</p></li>\n</ol>\n<p>Μπορείτε, αντ” αυτού, να χρησιμοποιήσετε τη μέθοδο <code class=\"docutils literal notranslate\">register.filter()</code> ως decorator:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@register</span><span class=\"o\">.</span>filter<span class=\"p\">(</span>name<span class=\"o\">=</span><span class=\"s1\">&#39;cut&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">cut</span><span class=\"p\">(</span>value<span class=\"p\">,</span> arg<span class=\"p\">):</span>\n    <span class=\"k\">return</span> value<span class=\"o\">.</span>replace<span class=\"p\">(</span>arg<span class=\"p\">,</span> <span class=\"s1\">&#39;&#39;</span><span class=\"p\">)</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span>filter\n<span class=\"k\">def</span> <span class=\"nf\">lower</span><span class=\"p\">(</span>value<span class=\"p\">):</span>\n    <span class=\"k\">return</span> value<span class=\"o\">.</span>lower<span class=\"p\">()</span>\n</code></pre></div>\n<p>Αν δεν περάσετε το όρισμα <code class=\"docutils literal notranslate\">name</code>, όπως στο δεύτερο παράδειγμα παραπάνω, το Django θα χρησιμοποιήσει το όνομα της συνάρτησης ως το όνομα του φίλτρου.</p>\n<p>Εν τέλει, η μέθοδος <code class=\"docutils literal notranslate\">register.filter()</code> δέχεται τρία keyword arguments, το <code class=\"docutils literal notranslate\">is_safe</code>, το <code class=\"docutils literal notranslate\">needs_autoescape</code> και το <code class=\"docutils literal notranslate\">expects_localtime</code>. Αυτά τα arguments περιγράφονται στα <a class=\"reference internal\" href=\"#filters-auto-escaping\"><span class=\"std std-ref\">φίλτρα και auto-escaping</span></a> και στα <a class=\"reference internal\" href=\"#filters-timezones\"><span class=\"std std-ref\">φίλτρα και ζώνες ώρας</span></a> παρακάτω.</p>\n</section>\n<section id=\"template-filters-that-expect-strings\">\n<h3>Template φίλτρα που περιμένουν strings<a class=\"heading-anchor\" href=\"#template-filters-that-expect-strings\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.template.defaultfilters.stringfilter\">\n<span class=\"sig-prename descclassname\">django.template.defaultfilters.</span><span class=\"sig-name descname\">stringfilter</span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.template.defaultfilters.stringfilter\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Αν γράφετε ένα template φίλτρο το οποίο περιμένει ένα argument τύπου string ως πρώτο argument, θα πρέπει να χρησιμοποιήσετε τον decorator <code class=\"docutils literal notranslate\">stringfilter</code>. Αυτό θα μετατρέψει το object στην string τιμή του πριν περαστεί στη συνάρτηση σας:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django</span> <span class=\"kn\">import</span> template\n<span class=\"kn\">from</span> <span class=\"nn\">django.template.defaultfilters</span> <span class=\"kn\">import</span> stringfilter\n\nregister <span class=\"o\">=</span> template<span class=\"o\">.</span>Library<span class=\"p\">()</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span>filter\n<span class=\"nd\">@stringfilter</span>\n<span class=\"k\">def</span> <span class=\"nf\">lower</span><span class=\"p\">(</span>value<span class=\"p\">):</span>\n    <span class=\"k\">return</span> value<span class=\"o\">.</span>lower<span class=\"p\">()</span>\n</code></pre></div>\n<p>Με αυτό τον τρόπο, θα μπορείτε να περνάτε, ας πούμε, έναν integer σε αυτό το φίλτρο και αυτό δεν θα προκαλέσει κάποιο <code class=\"docutils literal notranslate\">AttributeError</code> (επειδή οι integers δεν έχουν την μέθοδο <code class=\"docutils literal notranslate\">lower()</code>).</p>\n</section>\n<section id=\"filters-and-auto-escaping\">\n<span id=\"filters-auto-escaping\"></span><h3>Φίλτρα και auto-escaping<a class=\"heading-anchor\" href=\"#filters-and-auto-escaping\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Όταν γράφετε ένα δικό σας φίλτρο, σκεφτείτε λιγάκι το πως θα αλληλεπιδρά με την auto-escaping συμπεριφορά του Django. Όταν λέμε auto-escaping εννοούμε τη δυνατότητα αυτόματης αποφυγής εμφάνισης συγκεκριμένων χαρακτήρων-λέξεων οι οποίοι αν εμφανιζόντουσαν θα προκαλούσαν, ενδεχομένως, πρόβλημα στο rendering της σελίδας. Σημειώστε ότι υπάρχουν τρεις τύποι strings οι οποίοι μπορούν να περαστούν μέσα σε κώδικα template:</p>\n<ul>\n<li><p><strong>Σκέτα strings</strong>: είναι τα παραδοσιακά Python strings, τύπου <code class=\"docutils literal notranslate\">str</code> ή <code class=\"docutils literal notranslate\">unicode</code>. Στην έξοδο, αυτά τα string γίνονται escaped αν το auto-escaping είναι ενεργοποιημένο, ειδάλλως παρουσιάζονται όπως είναι.</p></li>\n<li><p><strong>Ασφαλή strings</strong>: είναι τα strings τα οποία έχουν μαρκαριστεί ως ασφαλή από περαιτέρω escaping κατά την παρουσίαση τους. Όλα τα απαραίτητα escapings έχουν γίνει μέχρι εδώ. Χρησιμοποιούνται συνήθως για έξοδο η οποία περιέχει σκέτη HTML και προορίζεται να μεταφραστεί ως έχει από τη μεριά του client.</p>\n<p>Εσωτερικώς, αυτά τα strings είναι τύπου <code class=\"docutils literal notranslate\">SafeBytes</code> ή <code class=\"docutils literal notranslate\">SafeText</code>. Μοιράζονται μια κοινή κλάση της <code class=\"docutils literal notranslate\">SafeData</code>, με αποτέλεσμα να μπορείτε να κάνετε τεστ σε αυτά με κώδικα όπως:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">if</span> <span class=\"nb\">isinstance</span><span class=\"p\">(</span>value<span class=\"p\">,</span> SafeData<span class=\"p\">):</span>\n    <span class=\"c1\"># Do something with the &quot;safe&quot; string.</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n</li>\n</ul>\n<p>Ο κώδικας ενός template φίλτρου εμπίπτει σε μια από τις δύο ακόλουθες καταστάσεις:</p>\n<ol class=\"arabic\">\n<li><p>Your filter does not introduce any HTML-unsafe characters (<code class=\"docutils literal notranslate\">&lt;</code>, <code class=\"docutils literal notranslate\">&gt;</code>,\n<code class=\"docutils literal notranslate\">'</code>, <code class=\"docutils literal notranslate\">&quot;</code> or <code class=\"docutils literal notranslate\">&amp;</code>) into the result that were not already present. In\nthis case, you can let Django take care of all the auto-escaping\nhandling for you. All you need to do is set the <code class=\"docutils literal notranslate\">is_safe</code> flag to <code class=\"docutils literal notranslate\">True</code>\nwhen you register your filter function, like so:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@register</span><span class=\"o\">.</span>filter<span class=\"p\">(</span>is_safe<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">myfilter</span><span class=\"p\">(</span>value<span class=\"p\">):</span>\n    <span class=\"k\">return</span> value\n</code></pre></div>\n<p>Αυτό το flag λέει στο Django ότι αν ένα «ασφαλές» string περαστεί στο φίλτρο σας, το αποτέλεσμα θα εξακολουθήσει να είναι «ασφαλές» ακόμη και αν ένα μη-ασφαλές string περαστεί, το Django, αυτόματα θα το κάνει escape, εάν χρειαστεί.</p>\n<p>Μπορείτε να το σκεφτείτε αλλιώς: «αυτό το φίλτρο είναι ασφαλές – δεν υπάρχει πιθανότητα τυχόν μη ασφαλούς HTML».</p>\n<p>Ο λόγος που το flag <code class=\"docutils literal notranslate\">is_safe</code> είναι απαραίτητο είναι επειδή υπάρχουν πολλών ειδών λειτουργίες για τα strings οι οποίες θα μετατρέψουν ένα object τύπου <code class=\"docutils literal notranslate\">SafeData</code> πίσω σε ένα κανονικό object τύπου <code class=\"docutils literal notranslate\">str</code> ή <code class=\"docutils literal notranslate\">unicode</code> (παρά να προσπαθήσουν να πιάσουν όλα τα strings κάτι το οποίο είναι δύσκολο) και το Django θα επιδιορθώσει τυχόν ζημιά αφού το φίλτρο έχει ολοκληρώσει τις εργασίες του.</p>\n<p>Για παράδειγμα, ας υποθέσουμε ότι έχετε ένα φίλτρο το οποίο προσθέτει το string <code class=\"docutils literal notranslate\">xx</code> στο τέλος κάθε input. Επειδή αυτό δεν εισάγει επικινδύνους HTML χαρακτήρες στο αποτέλεσμα (εκτός αυτού που είναι ήδη παρόν), θα πρέπει να μαρκάρετε το φίλτρο σας με το <code class=\"docutils literal notranslate\">is_safe</code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@register</span><span class=\"o\">.</span>filter<span class=\"p\">(</span>is_safe<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">add_xx</span><span class=\"p\">(</span>value<span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"s1\">&#39;</span><span class=\"si\">%s</span><span class=\"s1\">xx&#39;</span> <span class=\"o\">%</span> value\n</code></pre></div>\n<p>Όταν αυτό το φίλτρο χρησιμοποιείται σε ένα template όπου το auto-escaping είναι ενεργοποιημένο, το Django θα κάνει escape την έξοδο οποτεδήποτε το input δεν είναι μαρκαρισμένο ως «ασφαλές».</p>\n<p>Από προεπιλογή, το flag <code class=\"docutils literal notranslate\">is_safe</code> είναι <code class=\"docutils literal notranslate\">False</code> και μπορείτε να το παραλείψετε από τα φίλτρα όπου δεν χρειάζεται.</p>\n<p>Να είστε προσεκτικοί όταν αποφασίζετε αν το φίλτρο σας αφήνει όντως τα safe strings ως safe. Εάν <em>αφαιρείτε</em> χαρακτήρες, μπορεί ακούσια να αφήσετε μη-ισορροπημένα HTML tags (χωρίς το start ή το end tag) ή οντότητες στο αποτέλεσμα. Για παράδειγμα, όταν αφαιρείτε ένα <code class=\"docutils literal notranslate\">&gt;</code> από το input μπορεί να μετατρέψει ένα <code class=\"docutils literal notranslate\">&lt;a&gt;</code> σε <code class=\"docutils literal notranslate\">&lt;a</code>, το οποίο θα χρειαστεί να γίνει escaped στην έξοδο για την αποφυγή τυχόν προβλημάτων. Ομοίως, η αφαίρεση του <code class=\"docutils literal notranslate\">;</code> μπορεί να μετατρέψει το <code class=\"docutils literal notranslate\">&amp;amp;</code> σε <code class=\"docutils literal notranslate\">&amp;amp</code>, η οποία δεν είναι πλέον μια έγκυρη οντότητα και επομένως χρειάζεται περαιτέρω escaping. Οι περισσότερες περιπτώσεις δεν θα είναι τόσο πολύπλοκες αλλά προσέχετε για τέτοιου είδους προβλήματα όταν επανεξετάζετε τον κώδικα σας.</p>\n<p>Μαρκάροντας ένα φίλτρο ως <code class=\"docutils literal notranslate\">is_safe</code> θα αναγκάσει την επιστρεφόμενη τιμή του φίλτρου να γίνει ένα string.  Αν το φίλτρο σας θα πρέπει να επιστρέψει μια τιμή τύπου boolean ή κάποια άλλη πέρα από string, μαρκάροντας το ως <code class=\"docutils literal notranslate\">is_safe</code> θα έχει πιθανόν ακούσιες συνέπειες (όπως τη μετατροπή της τιμής False τύπου boolean στο string “False”).</p>\n</li>\n<li><p>Εναλλακτικά, ο κώδικας του φίλτρου σας μπορεί να χειριστεί χειροκίνητα, τυχόν αναγκαίο escaping. Αυτό είναι απαραίτητο όταν εισάγετε καινούργιο HTML κώδικα στο αποτέλεσμα σας. Θα θέλετε να μαρκάρετε την έξοδο ως ασφαλή από περαιτέρω escaping ούτως ώστε ο HTML κώδικας να μην γίνει περαιτέρω escape, οπότε θα χρειαστεί εσείς να χειριστείτε το input.</p>\n<p>Για να μαρκάρετε την έξοδο ως ασφαλή string, χρησιμοποιήστε τη συνάρτηση <a class=\"reference internal\" href=\"/el/1.11/ref/utils/#django.utils.safestring.mark_safe\" title=\"django.utils.safestring.mark_safe\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.safestring.mark_safe()</code></a>.</p>\n<p>Προσέχετε όμως. Θα χρειαστεί να κάνετε παραπάνω πράγματα από το να μαρκάρετε μόνο την έξοδο ως ασφαλή. Θα χρειαστεί να εξασφαλίσετε ότι είναι <em>όντως</em> ασφαλή και ότι κάνετε εξαρτάται από το αν το auto-escaping είναι ενεργοποιημένο ή όχι. Η ιδέα είναι να γράφετε φίλτρα τα οποία μπορούν να δρουν σε templates όπου το auto-escaping είναι είτε ενεργοποιημένο ή όχι, προκειμένου να κάνετε ευκολότερη τη δουλειά για τους συντάκτες των templates.</p>\n<p>Για να ξέρει το φίλτρο σας την κατάσταση του auto-escaping, θέστε το flag <code class=\"docutils literal notranslate\">needs_autoescape</code> σε <code class=\"docutils literal notranslate\">True</code> όταν κάνετε register το φίλτρο σας. (Αν δεν θέσετε αυτό το flag, η προεπιλεγμένη του τιμή είναι <code class=\"docutils literal notranslate\">False</code>). Αυτό το flag λέει στο Django ότι η συνάρτηση του φίλτρου σας δέχεται ένα επιπλέον keyword argument, με το όνομα <code class=\"docutils literal notranslate\">autoescape</code>, δηλαδή <code class=\"docutils literal notranslate\">True</code> αν το auto-escaping είναι ενεργοποιημένο και <code class=\"docutils literal notranslate\">False</code> αν όχι. Προτείνεται να θέσετε την προεπιπλεγμένη τιμή της παραμέτρου <code class=\"docutils literal notranslate\">autoescape</code> σε <code class=\"docutils literal notranslate\">True</code>, ούτως ώστε αν καλέσετε τη συνάρτηση του φίλτρου σας από τον Python κώδικα σας, το φίλτρο σας θα έχει το escaping ενεργοποιημένο από προεπιλογή.</p>\n<p>Για παράδειγμα, ας γράψουμε ένα φίλτρο το οποίο δίνει έμφαση στον πρώτο χαρακτήρα ενός string:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django</span> <span class=\"kn\">import</span> template\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.html</span> <span class=\"kn\">import</span> conditional_escape\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.safestring</span> <span class=\"kn\">import</span> mark_safe\n\nregister <span class=\"o\">=</span> template<span class=\"o\">.</span>Library<span class=\"p\">()</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span>filter<span class=\"p\">(</span>needs_autoescape<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">initial_letter_filter</span><span class=\"p\">(</span>text<span class=\"p\">,</span> autoescape<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">):</span>\n    first<span class=\"p\">,</span> other <span class=\"o\">=</span> text<span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">],</span> text<span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:]</span>\n    <span class=\"k\">if</span> autoescape<span class=\"p\">:</span>\n        esc <span class=\"o\">=</span> conditional_escape\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        esc <span class=\"o\">=</span> <span class=\"k\">lambda</span> x<span class=\"p\">:</span> x\n    result <span class=\"o\">=</span> <span class=\"s1\">&#39;&lt;strong&gt;</span><span class=\"si\">%s</span><span class=\"s1\">&lt;/strong&gt;</span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> <span class=\"p\">(</span>esc<span class=\"p\">(</span>first<span class=\"p\">),</span> esc<span class=\"p\">(</span>other<span class=\"p\">))</span>\n    <span class=\"k\">return</span> mark_safe<span class=\"p\">(</span>result<span class=\"p\">)</span>\n</code></pre></div>\n<p>Tο flag <code class=\"docutils literal notranslate\">needs_autoescape</code> και το keyword argument <code class=\"docutils literal notranslate\">autoescape</code> σημαίνουν ότι η συνάρτηση μας θα ξέρει αν το automatic escaping είναι ενεργοποιημένο ή όχι όταν το φίλτρο μας τρέξει. Χρησιμοποιούμε το <code class=\"docutils literal notranslate\">autoescape</code> για να αποφασίσουμε αν τα input data (το string που πέρασε στο φίλτρο μέσα από την HTML) θα χρειαστεί να περάσουν μέσα από την μέθοδο <code class=\"docutils literal notranslate\">django.utils.html.conditional_escape</code> ή όχι. (Στην τελευταία περίπτωση χρησιμοποιούμε μια lambda συνάρτηση ως την «escape» συνάρτηση.) Η συνάρτηση <code class=\"docutils literal notranslate\">conditional_escape()</code> είναι σαν την <code class=\"docutils literal notranslate\">escape()</code> αλλά κάνει escape το input το οποίο <strong>δεν είναι</strong> instance της κλάσης <code class=\"docutils literal notranslate\">SafeData</code>. Αν ένα instance μιας κλάσης <code class=\"docutils literal notranslate\">SafeData</code> περαστεί στη συνάρτηση <code class=\"docutils literal notranslate\">conditional_escape()</code>, τα δεδομένα θα επιστραφούν ανέπαφα.</p>\n<p>Στο παραπάνω παράδειγμα, θυμόμαστε να μαρκάρουμε το αποτέλεσμα ως ασφαλή ούτως ώστε η HTML που θα εισαχθεί απ” ευθείας μέσα στο template να μην υποστεί περαιτέρω escaping.</p>\n<p>Δεν υπάρχει λόγος να ανησυχούμε για το flag <code class=\"docutils literal notranslate\">is_safe</code> σε αυτή την περίπτωση (παρόλου που το περιλαμβάνουμε δεν βλάπτει κανέναν). Οποτεδήποτε χειρίζεστε χειροκίνητα τα θέματα του auto-escaping και επιστρέφετε ένα ασφαλή string, το flag <code class=\"docutils literal notranslate\">is_safe</code> δεν θα αλλάξει τίποτα με τον ένα ή τον άλλο τρόπο.</p>\n</li>\n</ol>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Προειδοποίηση</p>\n<p>Αποφεύγοντας τα τρωτά σημεία του XSS όταν επαναχρησιμοποιείτε τα προεγκατεστημένα φίλτρα του Django</p>\n<p>Τα προεγκατεστημένα φίλτρα του Django έχουν το <code class=\"docutils literal notranslate\">autoescape=True</code> από προεπιλογή, προκειμένου να έχουν την κατάλληλη autoescaping συμπεριφορά και για να αποφύγουν το τρωτό σημείο ενός cross-site script.</p>\n<p>Σε παλαιότερες εκδόσεις του Django, να είστε προσεκτικοί όταν χρησιμοποιείτε τα προεγκατεστημένα φίλτρα του Django επειδή η προεπιλεγμένη τιμή του keyword argument <code class=\"docutils literal notranslate\">autoescape</code> είναι <code class=\"docutils literal notranslate\">None</code>. Θα χρειαστεί να το δηλώσετε ως <code class=\"docutils literal notranslate\">autoescape=True</code> για να έχετε autoescaping.</p>\n<p>Για παράδειγμα, αν θέλετε να γράψετε ένα δικό σας φίλτρο με το όνομα <code class=\"docutils literal notranslate\">urlize_and_linebreaks</code> το οποίο συνδυάζει το φίλτρο <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/#std-templatefilter-urlize\"><code class=\"xref std std-tfilter docutils literal notranslate\">urlize</code></a> με <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/#std-templatefilter-linebreaksbr\"><code class=\"xref std std-tfilter docutils literal notranslate\">linebreaksbr</code></a>, τότε το φίλτρο σας θα έδειχνε κάπως έτσι:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.template.defaultfilters</span> <span class=\"kn\">import</span> linebreaksbr<span class=\"p\">,</span> urlize\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span>filter<span class=\"p\">(</span>needs_autoescape<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">urlize_and_linebreaks</span><span class=\"p\">(</span>text<span class=\"p\">,</span> autoescape<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> linebreaksbr<span class=\"p\">(</span>\n        urlize<span class=\"p\">(</span>text<span class=\"p\">,</span> autoescape<span class=\"o\">=</span>autoescape<span class=\"p\">),</span>\n        autoescape<span class=\"o\">=</span>autoescape\n    <span class=\"p\">)</span>\n</code></pre></div>\n<p>Μετά το:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{{</span> <span class=\"nv\">comment</span><span class=\"o\">|</span><span class=\"nf\">urlize_and_linebreaks</span> <span class=\"cp\">}}</span>\n</code></pre></div>\n<p>θα ήταν ισοδύναμο με αυτό:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{{</span> <span class=\"nv\">comment</span><span class=\"o\">|</span><span class=\"nf\">urlize</span><span class=\"o\">|</span><span class=\"nf\">linebreaksbr</span> <span class=\"cp\">}}</span>\n</code></pre></div>\n</aside>\n</section>\n<section id=\"filters-and-time-zones\">\n<span id=\"filters-timezones\"></span><h3>Φίλτρα και ζώνες ώρας<a class=\"heading-anchor\" href=\"#filters-and-time-zones\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Αν γράφετε δικά σας φίλτρα τα οποία δρουν σε objects του τύπου <a class=\"reference external\" href=\"https://docs.python.org/3/library/datetime.html#datetime.datetime\" title=\"(στη Python έκδοση 3.14)\"><code class=\"xref py py-class docutils literal notranslate\">datetime</code></a>, συνήθως θα το κάνετε register με το flag <code class=\"docutils literal notranslate\">expects_localtime</code> ως <code class=\"docutils literal notranslate\">True</code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@register</span><span class=\"o\">.</span>filter<span class=\"p\">(</span>expects_localtime<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">businesshours</span><span class=\"p\">(</span>value<span class=\"p\">):</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"k\">return</span> <span class=\"mi\">9</span> <span class=\"o\">&lt;=</span> value<span class=\"o\">.</span>hour <span class=\"o\">&lt;</span> <span class=\"mi\">17</span>\n    <span class=\"k\">except</span> <span class=\"ne\">AttributeError</span><span class=\"p\">:</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;&#39;</span>\n</code></pre></div>\n<p>Όταν αυτό το flag είναι <code class=\"docutils literal notranslate\">True</code>, αν η πρώτη παράμετρος του φίλτρου σας είναι ένα datetime με επίγνωση της ζώνης ώρας (time zone aware datetime), το Django θα το μετατρέψει στην τρέχουσα ζώνη ώρας, κατά περίπτωση, πριν το περάσει στο φίλτρο σας, σύμφωνα με τους <a class=\"reference internal\" href=\"/el/1.11/topics/i18n/timezones/#time-zones-in-templates\"><span class=\"std std-ref\">κανόνες μετατροπής ζωνών ώρας στα templates</span></a>.</p>\n</section>\n</section>\n<section id=\"writing-custom-template-tags\">\n<span id=\"howto-writing-custom-template-tags\"></span><h2>Γράφοντας δικάς σας template tags<a class=\"heading-anchor\" href=\"#writing-custom-template-tags\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Τα tags είναι περισσότερο πολύπλοκα από τα φίλτρα, επειδή τα tags μπορούν να κάνουν τα πάντα. Το Django παρέχει έναν αριθμό από συντομεύσεις που κάνει τη συγγραφή των περισσότερων τύπων tags ευκολότερη. Πρώτα θα εξερευνήσουμε αυτές τις συντομεύσεις και ύστερα θα εξηγήσουμε πως να γράψετε ένα tag από την αρχή για τις περιπτώσεις που κάποια συντόμευση δεν σας καλύπτει.</p>\n<section id=\"simple-tags\">\n<span id=\"howto-custom-template-tags-simple-tags\"></span><h3>Απλά tags<a class=\"heading-anchor\" href=\"#simple-tags\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.template.Library.simple_tag\">\n<span class=\"sig-prename descclassname\">django.template.Library.</span><span class=\"sig-name descname\">simple_tag</span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.template.Library.simple_tag\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Πολλά template tags παίρνουν έναν αριθμό από παραμέτρους – strings ή μεταβλητές template – και επιστρέφουν ένα αποτέλεσμα αφού κάνουν κάποια επεξεργασία βασιζόμενα στις παραμέτρους και σε τυχόν εξωτερικές πληροφορίες. Για παράδειγμα, ένα tag με το όνομα <code class=\"docutils literal notranslate\">current_time</code> μπορεί να δεχτεί ένα string μορφοποίησης και να επιστρέψει την ώρα ως string, μορφοποιημένη σύμφωνα με αυτό που περάστηκε.</p>\n<p>Για να διευκολύνουμε τη δημιουργία αυτού του τύπου των tags, το Django παρέχει μια βοηθητική συνάρτηση, τη <code class=\"docutils literal notranslate\">simple_tag</code>. Αυτή η συνάρτηση, η οποία είναι μέθοδος της κλάσης <code class=\"docutils literal notranslate\">django.template.Library</code>, δέχεται μια συνάρτηση η οποία δέχεται παραμέτρους ανεξαρτήτως αριθμού, την κάνει wrap σε μια render συνάρτηση και άλλων απαραίτητων στοιχείων που αναφέρθηκαν παραπάνω και την κάνει register με το σύστημα του template.</p>\n<p>Η συνάρτηση μας <code class=\"docutils literal notranslate\">current_time</code> θα μπορούσε, επομένως, να γραφτεί κάπως έτσι:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span> <span class=\"nn\">datetime</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django</span> <span class=\"kn\">import</span> template\n\nregister <span class=\"o\">=</span> template<span class=\"o\">.</span>Library<span class=\"p\">()</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span>simple_tag\n<span class=\"k\">def</span> <span class=\"nf\">current_time</span><span class=\"p\">(</span>format_string<span class=\"p\">):</span>\n    <span class=\"k\">return</span> datetime<span class=\"o\">.</span>datetime<span class=\"o\">.</span>now<span class=\"p\">()</span><span class=\"o\">.</span>strftime<span class=\"p\">(</span>format_string<span class=\"p\">)</span>\n</code></pre></div>\n<p>Μερικά πράγματα που πρέπει να σημειώσετε για την βοηθητική συνάρτηση <code class=\"docutils literal notranslate\">simple_tag</code>:</p>\n<ul class=\"simple\">\n<li><p>Ο έλεγχος του αριθμού των απαιτούμενων παραμέτρων κλπ, έχει ήδη γίνει τη στιγμή που η συνάρτηση μας καλείται, οπότε δεν θα χρειαστεί να γίνει κάτι τέτοιο.</p></li>\n<li><p>Τα εισαγωγικά (<code class=\"docutils literal notranslate\">””</code> ή <code class=\"docutils literal notranslate\">''</code>) γύρω από την παράμετρο (αν υπάρχουν) έχουν ήδη αποκοπεί, οπότε έχουμε να κάνουμε με ένα απλό string μέσα στη συνάρτηση του template tag.</p></li>\n<li><p>Αν η παράμετρος ήταν μια μεταβλητή template, τότε η συνάρτηση μας θα περνούσε την τιμή της μεταβλητής και όχι την ίδια τη μεταβλητή.</p></li>\n</ul>\n<p>Σε αντίθεση με λειτουργίες άλλων tags, το <code class=\"docutils literal notranslate\">simple_tag</code> περνάει την έξοδο του μέσα από τη συνάρτηση <a class=\"reference internal\" href=\"/el/1.11/ref/utils/#django.utils.html.conditional_escape\" title=\"django.utils.html.conditional_escape\"><code class=\"xref py py-func docutils literal notranslate\">conditional_escape()</code></a> αν το template context είναι σε λειτουργία autoescape, για να εξασφαλίσει σωστή HTML και για να σας προστατέψει από τρωτά σημεία του XSS.</p>\n<p>Αν δεν επιθυμείτε κάποιο πρόσθετο escaping, θα χρειαστεί να χρησιμοποιήσετε τη συνάρτηση <a class=\"reference internal\" href=\"/el/1.11/ref/utils/#django.utils.safestring.mark_safe\" title=\"django.utils.safestring.mark_safe\"><code class=\"xref py py-func docutils literal notranslate\">mark_safe()</code></a> αν είστε απόλυτα σίγουροι ότι ο κώδικας σας δεν είναι ευάλωτος σε XSS επιθέσεις. Για το χτίσιμο μικρών HTML αποσπασμάτων, η χρήση της συνάρτησης <a class=\"reference internal\" href=\"/el/1.11/ref/utils/#django.utils.html.format_html\" title=\"django.utils.html.format_html\"><code class=\"xref py py-func docutils literal notranslate\">format_html()</code></a> προτείνεται έναντι της <code class=\"docutils literal notranslate\">mark_safe()</code>.</p>\n<p>Αν το template tag χρειάζεται να έχει πρόσβαση στο τρέχων template context, μπορείτε να χρησιμοποιήσετε την παράμετρο <code class=\"docutils literal notranslate\">takes_context</code> όταν κάνετε register το tag σας:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@register</span><span class=\"o\">.</span>simple_tag<span class=\"p\">(</span>takes_context<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">current_time</span><span class=\"p\">(</span>context<span class=\"p\">,</span> format_string<span class=\"p\">):</span>\n    timezone <span class=\"o\">=</span> context<span class=\"p\">[</span><span class=\"s1\">&#39;timezone&#39;</span><span class=\"p\">]</span>\n    <span class=\"k\">return</span> your_get_current_time_method<span class=\"p\">(</span>timezone<span class=\"p\">,</span> format_string<span class=\"p\">)</span>\n</code></pre></div>\n<p>Σημειώστε ότι η πρώτη παράμετρος <em>πρέπει</em> να ονομαστεί <code class=\"docutils literal notranslate\">context</code>.</p>\n<p>Για περισσότερες πληροφορίες σχετικά με τη λειτουργία της παραμέτρου <code class=\"docutils literal notranslate\">takes_context</code>, δείτε στην ενότητα <a class=\"reference internal\" href=\"#howto-custom-template-tags-inclusion-tags\"><span class=\"std std-ref\">inclusion tags</span></a>.</p>\n<p>Αν χρειαστεί να μετονομάσετε το tag σας, μπορείτε να του δώσετε ένα δικό σας όνομα:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>register<span class=\"o\">.</span>simple_tag<span class=\"p\">(</span><span class=\"k\">lambda</span> x<span class=\"p\">:</span> x <span class=\"o\">-</span> <span class=\"mi\">1</span><span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;minusone&#39;</span><span class=\"p\">)</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span>simple_tag<span class=\"p\">(</span>name<span class=\"o\">=</span><span class=\"s1\">&#39;minustwo&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">some_function</span><span class=\"p\">(</span>value<span class=\"p\">):</span>\n    <span class=\"k\">return</span> value <span class=\"o\">-</span> <span class=\"mi\">2</span>\n</code></pre></div>\n<p>Οι συναρτήσεις <code class=\"docutils literal notranslate\">simple_tag</code> μπορούν να δεχτούν απεριόριστο αριθμό από positional ή keyword arguments. Για παράδειγμα:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@register</span><span class=\"o\">.</span>simple_tag\n<span class=\"k\">def</span> <span class=\"nf\">my_tag</span><span class=\"p\">(</span>a<span class=\"p\">,</span> b<span class=\"p\">,</span> <span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n    warning <span class=\"o\">=</span> kwargs<span class=\"p\">[</span><span class=\"s1\">&#39;warning&#39;</span><span class=\"p\">]</span>\n    profile <span class=\"o\">=</span> kwargs<span class=\"p\">[</span><span class=\"s1\">&#39;profile&#39;</span><span class=\"p\">]</span>\n    <span class=\"o\">...</span>\n    <span class=\"k\">return</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>Μετά, στο template, όλα τα arguments διαχωρισμένα με κενά (space character) μπορούν να περαστούν στο template tag. Όπως και στην Python, οι τιμές των keyword arguments ορίζονται με το σύμβολο της ισότητας (»<code class=\"docutils literal notranslate\">=</code>») και πρέπει να δηλωθούν μετά τα positional arguments. Για παράδειγμα:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">my_tag</span> <span class=\"m\">123</span> <span class=\"s2\">&quot;abcd&quot;</span> <span class=\"nv\">book.title</span> <span class=\"nv\">warning</span><span class=\"o\">=</span><span class=\"nv\">message</span><span class=\"o\">|</span><span class=\"nf\">lower</span> <span class=\"nv\">profile</span><span class=\"o\">=</span><span class=\"nv\">user.profile</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>Είναι πιθανόν να αποθηκεύσετε το αποτέλεσμα ενός tag σε μια template μεταβλητή παρά να την εμφανίζετε απ” ευθείας στο template σας. Αυτό γίνεται χρησιμοποιώντας το argument <code class=\"docutils literal notranslate\">as</code> ακολουθούμενο από το όνομα της template μεταβλητής όπου και θα αποθηκευτεί. Με αυτό τον τρόπο μπορείτε να εκτυπώσετε την τιμή αυτή οπουδήποτε αλλού στο template σας ή και με κάποια επιπλέον επεξεργασία (είτε σε αλλο tag ή φίλτρο):</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">current_time</span> <span class=\"s2\">&quot;%Y-%m-%d %I:%M %p&quot;</span> <span class=\"k\">as</span> <span class=\"nv\">the_time</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>The time is <span class=\"cp\">{{</span> <span class=\"nv\">the_time</span> <span class=\"cp\">}}</span>.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n</section>\n<section id=\"inclusion-tags\">\n<span id=\"howto-custom-template-tags-inclusion-tags\"></span><h3>Inclusion tags<a class=\"heading-anchor\" href=\"#inclusion-tags\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.template.Library.inclusion_tag\">\n<span class=\"sig-prename descclassname\">django.template.Library.</span><span class=\"sig-name descname\">inclusion_tag</span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.template.Library.inclusion_tag\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Ένας άλλο κοινός τύπος ενός template tag είναι ο τύπος που εμφανίζει κάποια δεδομένα κάνοντας rendering <em>ένα άλλο</em> template. Για παράδειγμα, το admin interface του Django χρησιμοποιεί δικά του template tags για να εμφανίζει τα κουμπιά στο κάτω μέρος της σελίδας της φόρμας που προσθέτετε ή αλλάζετε κάποιο object. Αυτά τα κουμπιά δείχουν παντού το ίδιο, αλλά το target του link αλάζει ανάλογα το object που επεξεργάζεται εκείνη τη στιγμή – αποτελούν λοιπόν μια τέλεια περίπτωση για τη χρήση μικρών template το οποίο είναι γεμάτο λεπτομέρειες από το τρέχων object. (Στην περίπτωση του admin, το tag ονομάζεται <code class=\"docutils literal notranslate\">submit_row</code>.)</p>\n<p>Αυτού του είδους τα tags ονομάζονται «inclusion tags».</p>\n<p>Η συγγραφή των inclusion tags φαίνεται καλύτερα μέσα από ένα παράδειγμα. Ας γράψουμε ένα tag το οποίο εξάγει μια λίστα από επιλογές για ένα δοθέν <code class=\"docutils literal notranslate\">Poll</code> object, το οποίο δημιουργήθηκε μέσα από το <a class=\"reference internal\" href=\"/el/1.11/intro/tutorial02/#creating-models\"><span class=\"std std-ref\">δεύτερο μέρος του οδηγού μας</span></a>. Θα χρησιμοποιήσουμε το tag ως εξής:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">show_results</span> <span class=\"nv\">poll</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>…και η έξοδος του θα μοιάζει κάπως έτσι:</p>\n<div class=\"code-block\" data-language=\"html\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Html</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Html code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n  <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>First choice<span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n  <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>Second choice<span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n  <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>Third choice<span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Πρώτα, πρέπει να ορίσετε τη συνάρτηση η οποία παίρνει το argument και επιστρέφει ένα dictionary από δεδομένα. Το σημαντικό εδώ είναι ότι το μόνο που χρειάζεται να επιστρέψουμε είναι ένα dictionary, όχι κάτι περίπλοκο. Αυτό θα χρησιμοποιηθεί ως template context για το κομμάτι του template. Παράδειγμα:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span> <span class=\"nf\">show_results</span><span class=\"p\">(</span>poll<span class=\"p\">):</span>\n    choices <span class=\"o\">=</span> poll<span class=\"o\">.</span>choice_set<span class=\"o\">.</span>all<span class=\"p\">()</span>\n    <span class=\"k\">return</span> <span class=\"p\">{</span><span class=\"s1\">&#39;choices&#39;</span><span class=\"p\">:</span> choices<span class=\"p\">}</span>\n</code></pre></div>\n<p>Επόμενο βήμα είναι να δημιουργήσετε το template το οποίο θα κάνει render την έξοδο του tag. Αυτό το template είναι ένα μόνιμο χαρακτηριστικό του tag: το προσδιορίζει ο συντάκτης του tag και όχι ο σχεδιαστής του template. Εν ακολουθία του παραδείγματος μας, το template είναι πολύ απλό:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">choice</span> <span class=\"k\">in</span> <span class=\"nv\">choices</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span> <span class=\"cp\">{{</span> <span class=\"nv\">choice</span> <span class=\"cp\">}}</span> <span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Τώρα, δημιουργήστε και κάντε register το inclusion tag καλώντας τη μέθοδο <code class=\"docutils literal notranslate\">inclusion_tag()</code> σε ένα object της κλάσης <code class=\"docutils literal notranslate\">Library</code>. Ακολουθώντας το παράδειγμα μας, αν το παραπάνω template βρίσκεται σε ένα αρχείο με το όνομα <code class=\"docutils literal notranslate\">results.html</code> σε κάποιο φάκελο που είναι ανιχνεύσιμος από τον template loader, θα κάναμε register το tag κάπως έτσι:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"c1\"># Here, register is a django.template.Library instance, as before</span>\n<span class=\"nd\">@register</span><span class=\"o\">.</span>inclusion_tag<span class=\"p\">(</span><span class=\"s1\">&#39;results.html&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">show_results</span><span class=\"p\">(</span>poll<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>Εναλλακτικά μπορείτε να κάνετε register το inclusion tag χρησιμοποιώντας ένα instance της κλάσης :class:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>django.template.</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.template.loader</span> <span class=\"kn\">import</span> get_template\nt <span class=\"o\">=</span> get_template<span class=\"p\">(</span><span class=\"s1\">&#39;results.html&#39;</span><span class=\"p\">)</span>\nregister<span class=\"o\">.</span>inclusion_tag<span class=\"p\">(</span>t<span class=\"p\">)(</span>show_results<span class=\"p\">)</span>\n</code></pre></div>\n<p>…όταν πρωτο-δημιουργείτε τη συνάρτηση.</p>\n<p>Μερικές φορές, τα inclusion tags μπορεί να χρειάζονται έναν μεγάλο αριθμό από παραμέτρους, κάνοντας δύσκολο για τους συντάκτες των templates να περάσουν όλες τις παραμέτρους και να θυμούνται τη σειρά τους. Για την αντιμετώπιση αυτού του προβλήματος, το Django προσφέρει την επιλογή <code class=\"docutils literal notranslate\">takes_context</code> τύπου boolean για inclusion tags. Αν τη θέσετε <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>True       `` όταν δημιουργείτε τη συνάρτηση, το tag δεν θα έχει απαιτούμενες παραμέτρους και η Python συνάρτηση του tag θα έχει μόνο μια παράμετρο – το template context όπως είναι όταν κλήθηκε το tag.</p>\n<p>Για παράδειγμα, ας υποθέσουμε ότι γράφετε ένα inclusion tag το οποίο θα χρησιμοποιείται πάντα σε κάποιο context που περιέχει τις μεταβλητές <code class=\"docutils literal notranslate\">home_link</code> και <code class=\"docutils literal notranslate\">home_title</code> οι οποίες θα οδηγούν πίσω στην αρχική σελίδα. Η Python συνάρτηση του tag θα δείχνει κάπως έτσι:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@register</span><span class=\"o\">.</span>inclusion_tag<span class=\"p\">(</span><span class=\"s1\">&#39;link.html&#39;</span><span class=\"p\">,</span> takes_context<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">jump_link</span><span class=\"p\">(</span>context<span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;link&#39;</span><span class=\"p\">:</span> context<span class=\"p\">[</span><span class=\"s1\">&#39;home_link&#39;</span><span class=\"p\">],</span>\n        <span class=\"s1\">&#39;title&#39;</span><span class=\"p\">:</span> context<span class=\"p\">[</span><span class=\"s1\">&#39;home_title&#39;</span><span class=\"p\">],</span>\n    <span class=\"p\">}</span>\n</code></pre></div>\n<p>Σημειώστε ότι η πρώτη παράμετρος της συνάρτησης <em>πρέπει</em> να ονομάζεται <code class=\"docutils literal notranslate\">context</code>.</p>\n<p>Στη γραμμή <code class=\"docutils literal notranslate\">register.inclusion_tag()</code>, προσδιορίσαμε το keyword argument <code class=\"docutils literal notranslate\">takes_context=True</code> και το όνομα του template. Το template <code class=\"docutils literal notranslate\">link.html</code> θα δείχνει κάπως έτσι:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code>Jump directly to <span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{{</span> <span class=\"nv\">link</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">title</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>.\n</code></pre></div>\n<p>Έπειτα, κάθε φορά που θέλετε να χρησιμοποιήσετε αυτό το tag, φορτώστε τη βιβλιοθήκη (<code class=\"docutils literal notranslate\">{% load &lt;όνομα_αρχείου&gt; %}</code>) και καλέσετε τη χωρίς ορίσματα, ως εξής:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">jump_link</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>Σημειώστε ότι, όταν χρησιμοποιείτε το <code class=\"docutils literal notranslate\">takes_context=True</code>, δεν χρειάζεται να περάσετε παραμέτρους μέσα στο template tag. Αυτόματα, έχει πρόσβαση στο template context.</p>\n<p>Η προεπιλεγμένη τιμή της παραμέτρου <code class=\"docutils literal notranslate\">takes_context</code> είναι <code class=\"docutils literal notranslate\">False</code>. Όταν τη θέτετε <code class=\"docutils literal notranslate\">True</code>, περνάει το context object μέσα στο tag, όπως σε αυτό το παράδειγμα. Αυτή είναι η μόνη διαφορά μεταξύ αυτής της περίπτωσης και του προηγούμενου <code class=\"docutils literal notranslate\">inclusion_tag</code> παραδείγματος.</p>\n<p>Οι συναρτήσεις των <code class=\"docutils literal notranslate\">inclusion_tag</code> μπορούν να δεχτούν αναρίθμητα positional ή keyword arguments. Για παράδειγμα:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@register</span><span class=\"o\">.</span>inclusion_tag<span class=\"p\">(</span><span class=\"s1\">&#39;my_template.html&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">my_tag</span><span class=\"p\">(</span>a<span class=\"p\">,</span> b<span class=\"p\">,</span> <span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n    warning <span class=\"o\">=</span> kwargs<span class=\"p\">[</span><span class=\"s1\">&#39;warning&#39;</span><span class=\"p\">]</span>\n    profile <span class=\"o\">=</span> kwargs<span class=\"p\">[</span><span class=\"s1\">&#39;profile&#39;</span><span class=\"p\">]</span>\n    <span class=\"o\">...</span>\n    <span class=\"k\">return</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>Μετά, στο template, όλα τα arguments διαχωρισμένα με κενά (space character) μπορούν να περαστούν στο template tag. Όπως και στην Python, οι τιμές των keyword arguments ορίζονται με το σύμβολο της ισότητας (»<code class=\"docutils literal notranslate\">=</code>») και πρέπει να δηλωθούν μετά τα positional arguments. Για παράδειγμα:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">my_tag</span> <span class=\"m\">123</span> <span class=\"s2\">&quot;abcd&quot;</span> <span class=\"nv\">book.title</span> <span class=\"nv\">warning</span><span class=\"o\">=</span><span class=\"nv\">message</span><span class=\"o\">|</span><span class=\"nf\">lower</span> <span class=\"nv\">profile</span><span class=\"o\">=</span><span class=\"nv\">user.profile</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n</section>\n<section id=\"assignment-tags\">\n<h3>Assignment tags<a class=\"heading-anchor\" href=\"#assignment-tags\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.template.Library.assignment_tag\">\n<span class=\"sig-prename descclassname\">django.template.Library.</span><span class=\"sig-name descname\">assignment_tag</span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.template.Library.assignment_tag\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<aside class=\"version-note version-deprecated\" data-version=\"1.9\" role=\"note\">\n<p class=\"version-note-title\">Deprecated since Django 1.9</p><p><span class=\"versionmodified deprecated\">Αποσύρθηκε στην έκδοση 1.9: </span>Το <code class=\"docutils literal notranslate\">simple_tag</code> θα πρέπει να χρησιμοποιείται καθώς μπορεί πλέον να αποθηκεύει αποτελέσματα σε μια μεταβλητή template.</p>\n</aside>\n<p>Για την διευκόλυνση της δημιουργίας μια μεταβλητής στο template context μέσω των tags, το Django παρέχει μια βοηθητική συνάρτηση, την <code class=\"docutils literal notranslate\">assignment_tag</code>. Αυτή η συνάρτηση δουλεύει με τον ίδιο τρόπο όπως η μέθοδος <a class=\"reference internal\" href=\"#django.template.Library.simple_tag\" title=\"django.template.Library.simple_tag\"><code class=\"xref py py-meth docutils literal notranslate\">simple_tag()</code></a> με τη μόνη διαφορά ότι η <code class=\"docutils literal notranslate\">assignment_tag</code> αποθηκεύει το αποτέλεσμα του tag σε μια μεταβλητή του context αντί να την εκτυπώνει απ” ευθείας στο template.</p>\n<p>Η προηγούμενη συνάρτηση <code class=\"docutils literal notranslate\">current_time</code> θα μπορούσε, επομένως, να γραφτεί ως:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@register</span><span class=\"o\">.</span>assignment_tag\n<span class=\"k\">def</span> <span class=\"nf\">get_current_time</span><span class=\"p\">(</span>format_string<span class=\"p\">):</span>\n    <span class=\"k\">return</span> datetime<span class=\"o\">.</span>datetime<span class=\"o\">.</span>now<span class=\"p\">()</span><span class=\"o\">.</span>strftime<span class=\"p\">(</span>format_string<span class=\"p\">)</span>\n</code></pre></div>\n<p>Μπορείτε πλέον να αποθηκεύσετε το αποτέλεσμα σε μια μεταβλητή του template χρησιμοποιώντας το argument <code class=\"docutils literal notranslate\">as</code> ακολουθούμενο από το όνομα της μεταβλητής. Έπειτα μπορείτε να εκτυπώσετε την τιμή της μεταβλητής οπουδήποτε μέσα στο template επιθυμείτε:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">get_current_time</span> <span class=\"s2\">&quot;%Y-%m-%d %I:%M %p&quot;</span> <span class=\"k\">as</span> <span class=\"nv\">the_time</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>The time is <span class=\"cp\">{{</span> <span class=\"nv\">the_time</span> <span class=\"cp\">}}</span>.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n</section>\n<section id=\"advanced-custom-template-tags\">\n<h3>Παραμετροποιήσιμα template tags για προχωρημένους<a class=\"heading-anchor\" href=\"#advanced-custom-template-tags\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Μερικές φορές τα βασικά χαρακτηριστικά για τη δημιουργία του δικού σας template tag δεν είναι αρκετά. Μην ανησυχείτε, το Django σας δίνει πλήρη πρόσβαση στα εσωτερικά που απαιτούνται για να φτιάξετε ένα template tag από την αρχή.</p>\n</section>\n<section id=\"a-quick-overview\">\n<h3>Μια γρήγορη ματιά<a class=\"heading-anchor\" href=\"#a-quick-overview\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Το σύστημα του template λειτουργεί ακολουθώντας μια διαδικασία δύο σταδίων: compiling και rendering. Για να ορίσετε ένα δικό σας template tag, πρέπει να προσδιορίσετε πως δουλεύει το compilation και πως το rendering.</p>\n<p>Όταν το Django συντάσσει (compiles) ένα template, χωρίζει το κείμενο του template σε μια λίστα από “”nodes””. Κάθε node είναι ένα instance της κλάσης <code class=\"docutils literal notranslate\">django.template.Node</code> και έχει μια μέθοδο <code class=\"docutils literal notranslate\">render()</code>. Ένα compiled template είναι, απλώς, μια λίστα από objects τύπου <code class=\"docutils literal notranslate\">Node</code>. Όταν καλείτε τη μέθοδο <code class=\"docutils literal notranslate\">render()</code> σε ένα compiled template object, το template καλεί τη μέθοδο <code class=\"docutils literal notranslate\">render()</code> για καθένα <code class=\"docutils literal notranslate\">Node</code> που βρίσκεται στη λίστα του, με το δοθέν context. Τα αποτελέσματα ενώνονται όλα μεταξύ τους για να συνθέσουν την έξοδο του template.</p>\n<p>Επομένως, για να ορίσετε ένα δικό σας template tag, προσδιορίζετε πως ένα template tag μετατρέπεται σε ένα <code class=\"docutils literal notranslate\">Node</code> (η συνάρτηση του compilation) και τι κάνει η μέθοδος <code class=\"docutils literal notranslate\">render()</code> του node.</p>\n</section>\n<section id=\"writing-the-compilation-function\">\n<h3>Γράφοντας τη συνάρτηση του compilation<a class=\"heading-anchor\" href=\"#writing-the-compilation-function\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Για κάθε template tag που βρίσκει ο template parser, καλείται μια Python συνάρτηση με τα περιεχόμενα του tag και το ίδιο το parser object. Αυτή η συνάρτηση είναι υπεύθυνη να επιστρέψει ένα instance του <code class=\"docutils literal notranslate\">Node</code> βασιζόμενη στα περιεχόμενα του tag.</p>\n<p>Για παράδειγμα, ας γράψουμε μια πλήρης υλοποίηση του απλού μας template tag, <code class=\"docutils literal notranslate\">{% current_time %}</code>, το οποίο εμφανίζει την τρέχουσα ημερομηνία/ώρα, μορφοποιημένη σύμφωνα με τις παραμέτρους (σύνταξη func:~time.strftime) που δόθηκαν στο tag. Είναι καλή ιδέα να αποφασίσετε τη σύνταξη του tag πριν από οτιδήποτε άλλο. Στη δικιά μας περίπτωση, ας πούμε ότι το tag θα πρέπει να χρησιμοποιείται κάπως έτσι:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>The time is <span class=\"cp\">{%</span> <span class=\"k\">current_time</span> <span class=\"s2\">&quot;%Y-%m-%d %I:%M %p&quot;</span> <span class=\"cp\">%}</span>.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Ο parser για αυτή τη συνάρτηση θα πρέπει να παίρνει την παράμετρο και να δημιουργεί ένα object του <code class=\"docutils literal notranslate\">Node</code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django</span> <span class=\"kn\">import</span> template\n\n<span class=\"k\">def</span> <span class=\"nf\">do_current_time</span><span class=\"p\">(</span>parser<span class=\"p\">,</span> token<span class=\"p\">):</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"c1\"># split_contents() knows not to split quoted strings.</span>\n        tag_name<span class=\"p\">,</span> format_string <span class=\"o\">=</span> token<span class=\"o\">.</span>split_contents<span class=\"p\">()</span>\n    <span class=\"k\">except</span> <span class=\"ne\">ValueError</span><span class=\"p\">:</span>\n        <span class=\"k\">raise</span> template<span class=\"o\">.</span>TemplateSyntaxError<span class=\"p\">(</span>\n            <span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag requires a single argument&quot;</span> <span class=\"o\">%</span> token<span class=\"o\">.</span>contents<span class=\"o\">.</span>split<span class=\"p\">()[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n        <span class=\"p\">)</span>\n    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"p\">(</span>format_string<span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"o\">==</span> format_string<span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">]</span> <span class=\"ow\">and</span> format_string<span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"ow\">in</span> <span class=\"p\">(</span><span class=\"s1\">&#39;&quot;&#39;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;&#39;&quot;</span><span class=\"p\">)):</span>\n        <span class=\"k\">raise</span> template<span class=\"o\">.</span>TemplateSyntaxError<span class=\"p\">(</span>\n            <span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag&#39;s argument should be in quotes&quot;</span> <span class=\"o\">%</span> tag_name\n        <span class=\"p\">)</span>\n    <span class=\"k\">return</span> CurrentTimeNode<span class=\"p\">(</span>format_string<span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">])</span>\n</code></pre></div>\n<p>Σημειώσεις</p>\n<ul class=\"simple\">\n<li><p>Η παράμετρος <code class=\"docutils literal notranslate\">parser</code> είναι ένα template parser object. Δεν το χρειαζόμαστε σε αυτό το παράδειγμα.</p></li>\n<li><p>Το <code class=\"docutils literal notranslate\">token.contents</code> είναι ένα string των περιεχομένων του tag. Στο δικό μας παράδειγμα, είναι το <code class=\"docutils literal notranslate\">'current_time &quot;%Y-%m-%d %I:%M %p&quot;'</code>.</p></li>\n<li><p>Η μέθοδος <code class=\"docutils literal notranslate\">token.split_contents()</code> διαχωρίζει, με βάση τον χαρακτήρα του διαστήματος, τις παραμέτρους ενώ παράλληλα κρατάει τα strings, ανέπαφα, με τον χαρακτήρα που έχουν δηλωθεί (<code class=\"docutils literal notranslate\">’...’</code> ή <code class=\"docutils literal notranslate\">”...”</code>). Αν χρησιμοποιούνταν η <code class=\"docutils literal notranslate\">token.contents.split()</code> τότε θα διαχώριζε <em>όλα</em> τα περιεχόμενα του tag με βάση το χαρακτήρα του διαστήματος, συμπεριλαμβανομένων και των κενών που υπάρχουν στο string. Αυτό βέβαια δεν είναι βολικό. Καλό είναι, λοιπόν, να χρησιμοποιείτε τη μέθοδο <code class=\"docutils literal notranslate\">token.split_contents()</code>.</p></li>\n<li><p>Η συνάρτηση που φτιάξαμε, είναι υπεύθυνη να κάνει raise το exception <code class=\"docutils literal notranslate\">django.template.TemplateSyntaxError</code>, με βοηθητικά μηνύματα για τυχόν συντακτικά λάθη.</p></li>\n<li><p>Τα exceptions τύπου <code class=\"docutils literal notranslate\">TemplateSyntaxError</code> χρησιμοποιούν τη μεταβλητή <code class=\"docutils literal notranslate\">tag_name</code>. Μην γράφετε μόνοι σας το όνομα του tag στα μηνύματα σφάλματος, επειδή αυτό δεσμεύει το όνομα του tag με τη συνάρτηση σας. Το <code class=\"docutils literal notranslate\">token.contents.split()[0]</code> θα περιέχει “”πάντα”” το όνομα του tag σας – ακόμη και αν το tag δεν έχει παραμέτρους.</p></li>\n<li><p>The function returns a <code class=\"docutils literal notranslate\">CurrentTimeNode</code> with everything the node needs\nto know about this tag. In this case, it just passes the argument –\n<code class=\"docutils literal notranslate\">&quot;%Y-%m-%d %I:%M %p&quot;</code>. The leading and trailing quotes from the\ntemplate tag are removed in <code class=\"docutils literal notranslate\">format_string[1:-1]</code>.</p></li>\n<li><p>Το parsing γίνεται σε πολύ χαμηλό επίπεδο. Οι Django developers έχουν πειραματιστεί στο να γράφουν μικρά frameworks πάνω σε αυτό το σύστημα parsing, χρησιμοποιώντας τεχνικές όπως οι γραμματικές EBNF (EBNF grammars), αλλά αυτά τα πειράματα έκαναν την μηχανή του template πολύ αργή. Γίνεται, λοιπόν, σε χαμηλό επίπεδο επειδή αυτό είναι γρηγορότερο.</p></li>\n</ul>\n</section>\n<section id=\"writing-the-renderer\">\n<h3>Γράφοντας τον renderer<a class=\"heading-anchor\" href=\"#writing-the-renderer\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Το δεύτερο βήμα για τη δημιουργία δικών μας tags είναι ο ορισμός της subclass της <code class=\"docutils literal notranslate\">Node</code> η οποία έχει μια μέθοδο <code class=\"docutils literal notranslate\">render()</code>.</p>\n<p>Συνεχίζοντας το παραπάνω παράδειγμα, χρειάζεται να ορίσουμε το <code class=\"docutils literal notranslate\">CurrentTimeNode</code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span> <span class=\"nn\">datetime</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django</span> <span class=\"kn\">import</span> template\n\n<span class=\"k\">class</span> <span class=\"nc\">CurrentTimeNode</span><span class=\"p\">(</span>template<span class=\"o\">.</span>Node<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> format_string<span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span>format_string <span class=\"o\">=</span> format_string\n\n    <span class=\"k\">def</span> <span class=\"nf\">render</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> context<span class=\"p\">):</span>\n        <span class=\"k\">return</span> datetime<span class=\"o\">.</span>datetime<span class=\"o\">.</span>now<span class=\"p\">()</span><span class=\"o\">.</span>strftime<span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>format_string<span class=\"p\">)</span>\n</code></pre></div>\n<p>Σημειώσεις</p>\n<ul class=\"simple\">\n<li><p>Η μέθοδος <code class=\"docutils literal notranslate\">__init__()</code> λαμβάνει τη μεταβλητή <code class=\"docutils literal notranslate\">format_string</code> από τη συνάρτηση <code class=\"docutils literal notranslate\">do_current_time()</code>. Πάντα να περνάτε τυχόν options/parameters/arguments σε ένα <code class=\"docutils literal notranslate\">Node</code> μέσω της <code class=\"docutils literal notranslate\">__init__()</code> μεθόδου του.</p></li>\n<li><p>Η μέθοδος <code class=\"docutils literal notranslate\">render()</code> είναι εκεί όπου γίνονται όλα.</p></li>\n<li><p>Η <code class=\"docutils literal notranslate\">render()</code> θα πρέπει γενικά να αποτυγχάνει σιωπηρά, ειδικά σε παραγωγικό περιβάλλον (production environment). Ωστόσο, σε μερικές περιπτώσεις, ειδικά αν το <code class=\"docutils literal notranslate\">context.template.engine.debug</code> είναι <code class=\"docutils literal notranslate\">True</code>, αυτή η μέθοδος θα πρέπει να κάνει raise ένα exception για να κάνει το debugging ευκολότερο. Για παράδειγμα, πολλά προεγκατεστημένα tags του Django κάνουν raise το <code class=\"docutils literal notranslate\">django.template.TemplateSyntaxError</code> αν λάβουν λάθος αριθμό ή τύπο παραμέτρων.</p></li>\n</ul>\n<p>Τελικώς, αυτή η αποσύνδεση μεταξύ του compilation και του rendering έχει ως αποτέλεσμα ένα αποδοτικό σύστημα template, επειδή ένα template μπορεί να κάνει render πολλαπλά contexts χωρίς να χρειαστεί να γίνει parsed πολλές φορές.</p>\n</section>\n<section id=\"auto-escaping-considerations\">\n<span id=\"tags-auto-escaping\"></span><h3>Εκτιμήσεις σχετικά με το auto-escaping<a class=\"heading-anchor\" href=\"#auto-escaping-considerations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Η έξοδος των template tags <strong>δεν</strong> περνούν αυτόματα μέσα από auto-escaping φίλτρα (εκτός της μεθόδου <a class=\"reference internal\" href=\"#django.template.Library.simple_tag\" title=\"django.template.Library.simple_tag\"><code class=\"xref py py-meth docutils literal notranslate\">simple_tag()</code></a>, όπως περιγράφηκε παραπάνω). Ωστόσο, υπάρχουν ακόμη μερικά πράγματα που πρέπει να έχετε στο νου σας όταν γράφετε ένα template tag.</p>\n<p>Αν η συνάρτηση <code class=\"docutils literal notranslate\">render()</code> του template σας αποθηκεύει το αποτέλεσμα σε μια context variable (αντί να επιστρέφει το αποτέλεσμα σε ένα string), θα πρέπει να φροντίσει να καλέσει την <code class=\"docutils literal notranslate\">mark_safe()</code>, αν αυτό είναι απαραίτητο. Όταν η μεταβλητή γίνει, τελικώς, rendered (εμφανιστεί-τυπωθεί στο template, αν θέλετε), θα επηρεαστεί από τη ρύθμιση του auto-escape (αναλόγως αν είναι ενεργοποιημένη ή όχι), οπότε το περιεχόμενο που πρέπει να είναι safe από περαιτέρω escaping χρειάζεται να μαρκαριστεί.</p>\n<p>Επίσης, αν το template tag σας δημιουργεί ένα καινούργιο context για να εκτελέσει κάποιο sub-rendering, θέστε το attribute του auto-escape στην τιμή του τρέχοντος context. Η μέθοδος <code class=\"docutils literal notranslate\">__init__</code> για την κλάση <code class=\"docutils literal notranslate\">Context</code> δέχεται μια παράμετρο με το όνομα <code class=\"docutils literal notranslate\">autoescape</code>, την οποία μπορείτε να χρησιμοποιήσετε για αυτό το σκοπό. Για παράδειγμα:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.template</span> <span class=\"kn\">import</span> Context\n\n<span class=\"k\">def</span> <span class=\"nf\">render</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> context<span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    new_context <span class=\"o\">=</span> Context<span class=\"p\">({</span><span class=\"s1\">&#39;var&#39;</span><span class=\"p\">:</span> obj<span class=\"p\">},</span> autoescape<span class=\"o\">=</span>context<span class=\"o\">.</span>autoescape<span class=\"p\">)</span>\n    <span class=\"c1\"># ... Do something with new_context ...</span>\n</code></pre></div>\n<p>Αυτό δεν είναι μια συνηθισμένη περίπτωση, αλλά είναι χρήσιμο να το ξέρετε αν κάνετε rendering ένα template εσείς οι ίδιοι.</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span> <span class=\"nf\">render</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> context<span class=\"p\">):</span>\n    t <span class=\"o\">=</span> context<span class=\"o\">.</span>template<span class=\"o\">.</span>engine<span class=\"o\">.</span>get_template<span class=\"p\">(</span><span class=\"s1\">&#39;small_fragment.html&#39;</span><span class=\"p\">)</span>\n    <span class=\"k\">return</span> t<span class=\"o\">.</span>render<span class=\"p\">(</span>Context<span class=\"p\">({</span><span class=\"s1\">&#39;var&#39;</span><span class=\"p\">:</span> obj<span class=\"p\">},</span> autoescape<span class=\"o\">=</span>context<span class=\"o\">.</span>autoescape<span class=\"p\">))</span>\n</code></pre></div>\n<p>Αν δεν περνάγαμε την τιμή του <code class=\"docutils literal notranslate\">context.autoescape</code> στο νέο μας <code class=\"docutils literal notranslate\">Context</code> σε αυτό το παράδειγμα, τα αποτελέσματα θα γινόντουσαν <em>πάντα</em> αυτόματα escaped, κάτι το οποίο μπορεί να μην ήταν η επιθυμητική συμπεριφορά αν το template tag χρησιμοποιούταν μέσα στο block tag <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/#std-templatetag-autoescape\"><code class=\"xref std std-ttag docutils literal notranslate\">{% autoescape off %}</code></a>.</p>\n</section>\n<section id=\"thread-safety-considerations\">\n<span id=\"template-tag-thread-safety\"></span><h3>Εκτιμήσεις σχετικά με την ασφάλεια των threads<a class=\"heading-anchor\" href=\"#thread-safety-considerations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Όταν ένα node γίνει parsed, η <code class=\"docutils literal notranslate\">render</code> μέθοδος του μπορεί να καλεστεί πολλές φορές. Επειδή το Django, μερικές φορές, τρέχει σε περιβάλλοντα multi-threaded, ένα απλό node μπορεί ταυτοχρόνως να γίνει rendering με διαφορετικά contexts ως response για δύο ξεχωριστά requests. Επομένως, είναι σημαντικό να εξασφαλίσετε ότι τα template tags σας είναι thread safe.</p>\n<p>Για να το εξασφαλίσετε αυτό, δεν θα πρέπει να αποθηκεύετε ποτέ τις πληροφορίες της κατάστασης στο ίδιο το node. Για παράδειγμα, το Django παρέχει ένα προεγκατεστημένο template tag <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/#std-templatetag-cycle\"><code class=\"xref std std-ttag docutils literal notranslate\">cycle</code></a> το οποίο ανατρέχει μια λίστα από δοθέντα strings κάθε φορά που γίνεται rendered:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">o</span> <span class=\"k\">in</span> <span class=\"nv\">some_list</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">tr</span> <span class=\"na\">class</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">cycle</span> <span class=\"s1\">&#39;row1&#39;</span> <span class=\"s1\">&#39;row2&#39;</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>\n        ...\n    <span class=\"p\">&lt;/</span><span class=\"nt\">tr</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>Μια απλοϊκή υλοποίηση του <code class=\"docutils literal notranslate\">CycleNode</code> θα έμοιαζε κάπως έτσι:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span> <span class=\"nn\">itertools</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django</span> <span class=\"kn\">import</span> template\n\n<span class=\"k\">class</span> <span class=\"nc\">CycleNode</span><span class=\"p\">(</span>template<span class=\"o\">.</span>Node<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> cyclevars<span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span>cycle_iter <span class=\"o\">=</span> itertools<span class=\"o\">.</span>cycle<span class=\"p\">(</span>cyclevars<span class=\"p\">)</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">render</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> context<span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"nb\">next</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>cycle_iter<span class=\"p\">)</span>\n</code></pre></div>\n<p>Αλλά, ας υποθέσουμε ότι την ίδια χρονική στιγμή, δύο templates κάνουν rendering το κομμάτι του template παραπάνω:</p>\n<ol class=\"arabic simple\">\n<li><p>Το Thread 1 πραγματοποιεί την πρώτη επανάληψη του βρόγχου, η μέθοδος <code class=\"docutils literal notranslate\">CycleNode.render()</code> επιστρέφει “row1”</p></li>\n<li><p>Το Thread 2 πραγματοποιεί την πρώτη επανάληψη του βρόγχου, η μέθοδος <code class=\"docutils literal notranslate\">CycleNode.render()</code> επιστρέφει “row2”</p></li>\n<li><p>Το Thread 1 πραγματοποιεί την δεύτερη επανάληψη του βρόγχου, η μέθοδος <code class=\"docutils literal notranslate\">CycleNode.render()</code> επιστρέφει “row1”</p></li>\n<li><p>Το Thread 2 πραγματοποιεί την δεύτερη επανάληψη του βρόγχου, η μέθοδος <code class=\"docutils literal notranslate\">CycleNode.render()</code> επιστρέφει “row2”</p></li>\n</ol>\n<p>Το CycleNode κάνει την επανάληψη (iterating), αλλά την κάνει καθολικά (globally). Όσον αφορά τα Thread 1 και Thread 2, το καθένα επιστρέφει πάντα την ίδια τιμή. Αυτό, φυσικά, δεν είναι αυτό που θέλουμε!</p>\n<p>Για την αποφυγή τέτοιων καταστάσεων, το Django παρέχει ένα <code class=\"docutils literal notranslate\">render_context</code> το οποίο σχετίζεται με το <code class=\"docutils literal notranslate\">context</code> του template το οποίο γίνεται εκείνη τη στιγμή rendered. Το <code class=\"docutils literal notranslate\">render_context</code> συμπεριφέρεται όπως ένα Python dictionary και θα πρέπει να χρησιμοποιείται για να αποθηκεύονται οι καταστάσεις του <code class=\"docutils literal notranslate\">Node</code> μεταξύ κλήσεων της μεθόδου <code class=\"docutils literal notranslate\">render</code>.</p>\n<p>Ας αλλάξουμε την υλοποίηση της κλάσης <code class=\"docutils literal notranslate\">CycleNode</code> για να χρησιμοποιεί το <code class=\"docutils literal notranslate\">render_context</code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span> <span class=\"nc\">CycleNode</span><span class=\"p\">(</span>template<span class=\"o\">.</span>Node<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> cyclevars<span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span>cyclevars <span class=\"o\">=</span> cyclevars\n\n    <span class=\"k\">def</span> <span class=\"nf\">render</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> context<span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"bp\">self</span> <span class=\"ow\">not</span> <span class=\"ow\">in</span> context<span class=\"o\">.</span>render_context<span class=\"p\">:</span>\n            context<span class=\"o\">.</span>render_context<span class=\"p\">[</span><span class=\"bp\">self</span><span class=\"p\">]</span> <span class=\"o\">=</span> itertools<span class=\"o\">.</span>cycle<span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>cyclevars<span class=\"p\">)</span>\n        cycle_iter <span class=\"o\">=</span> context<span class=\"o\">.</span>render_context<span class=\"p\">[</span><span class=\"bp\">self</span><span class=\"p\">]</span>\n        <span class=\"k\">return</span> <span class=\"nb\">next</span><span class=\"p\">(</span>cycle_iter<span class=\"p\">)</span>\n</code></pre></div>\n<p>Σημειώστε ότι δεν είναι καθόλου λάθος να αποθηκεύετε ως attribute καθολικές πληροφορίες οι οποίες δεν αλλάζουν κατά τη διάρκεια της ζωής ενός <code class=\"docutils literal notranslate\">Node</code>. Στην περίπτωση του <code class=\"docutils literal notranslate\">CycleNode</code>, το argument <code class=\"docutils literal notranslate\">cyclevars</code> δεν αλλάζει μετά την αρχικοποίηση του <code class=\"docutils literal notranslate\">Node</code>, οπότε δεν χρειάζεται να το βάλουμε μέσα στο <code class=\"docutils literal notranslate\">render_context</code>. Αλλά η πληροφορία της κατάστασης η οποία είναι συγκεκριμένη στο template το οποίο γίνεται rendered, όπως η τρέχουσα επανάληψη βρόγχου του <code class=\"docutils literal notranslate\">CycleNode</code>, θα πρέπει να αποθηκευτεί μέσα στο <code class=\"docutils literal notranslate\">render_context</code>.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Σημείωση</p>\n<p>Σημειώστε το πως χρησιμοποιήσαμε το <code class=\"docutils literal notranslate\">self</code> για να έχουμε πρόσβαση σε συγκεκριμένη πληροφορία του <code class=\"docutils literal notranslate\">CycleNode</code> μέσα από το <code class=\"docutils literal notranslate\">render_context</code>. Μπορεί να υπάρχουν πολλαπλά <code class=\"docutils literal notranslate\">CycleNodes</code> μέσα σε ένα template, οπότε πρέπει να είμαστε προσεκτικοί να μην αφαιρέσουμε την πληροφορία της κατάστασης άλλου node. Ο πιο εύκολος τρόπος για να επιτευχθεί κάτι τέτοιο είναι πάντα να χρησιμοποιείτε το <code class=\"docutils literal notranslate\">self</code> ως το key μέσα στο <code class=\"docutils literal notranslate\">render_context</code>. Αν παρακολουθείτε πολλές ματαβλητές κατάστασης (state variables), κάντε το <code class=\"docutils literal notranslate\">render_context[self]</code> ένα dictionary.</p>\n</aside>\n</section>\n<section id=\"registering-the-tag\">\n<h3>Κάνοντας register το tag<a class=\"heading-anchor\" href=\"#registering-the-tag\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Τέλος, κάντε register το tag με το instance του module <code class=\"docutils literal notranslate\">Library</code>, όπως εξηγήθηκε στην ενότητα <a class=\"reference internal\" href=\"#howto-writing-custom-template-tags\"><span class=\"std std-ref\">γράφοντας δικά σας template φίλτρα</span></a> παραπάνω. Παράδειγμα:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>register<span class=\"o\">.</span>tag<span class=\"p\">(</span><span class=\"s1\">&#39;current_time&#39;</span><span class=\"p\">,</span> do_current_time<span class=\"p\">)</span>\n</code></pre></div>\n<p>Η μέθοδος <code class=\"docutils literal notranslate\">tag()</code> λαμβάνει δύο arguments:</p>\n<ol class=\"arabic simple\">\n<li><p>Το όνομα του template tag – ένα string. Αν αυτό παραλειφθεί, θα χρησιμοποιηθεί το όνομα της συνάρτησης του compilation.</p></li>\n<li><p>Τη συνάρτηση του φίλτρου – μια Python συνάρτηση (όχι το όνομα της συνάρτησης ως string).</p></li>\n</ol>\n<p>Όπως και με το registration των φιλτρών, μπορείτε να χρησιμοποιήσετε έναν decorator:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@register</span><span class=\"o\">.</span>tag<span class=\"p\">(</span>name<span class=\"o\">=</span><span class=\"s2\">&quot;current_time&quot;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">do_current_time</span><span class=\"p\">(</span>parser<span class=\"p\">,</span> token<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n\n<span class=\"nd\">@register</span><span class=\"o\">.</span>tag\n<span class=\"k\">def</span> <span class=\"nf\">shout</span><span class=\"p\">(</span>parser<span class=\"p\">,</span> token<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>Αν παραλείψετε την παράμετρο <code class=\"docutils literal notranslate\">name</code>, όπως στο δεύτερο παράδειγμα παραπάνω, το Django θα χρησιμοποιήσει το όνομα της συνάρτησης ως το όνομα του tag.</p>\n</section>\n<section id=\"passing-template-variables-to-the-tag\">\n<h3>Περνώντας template μεταβλητές στο tag<a class=\"heading-anchor\" href=\"#passing-template-variables-to-the-tag\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Όπως γνωρίζετε μπορείτε να περάσετε οποιοδήποτε αριθμό από παραμέτρους σε ένα template tag και χρησιμοποιώντας τη μέθοδο <code class=\"docutils literal notranslate\">token.split_contents()</code> οι παράμετροι θα είναι διαθέσιμες σε εσάς ως strings. Ωστόσο, χρειάζεται λίγη περισσότερη δουλειά για να περάσετε δυναμικό περιεχόμενο (μια template μεταβλητή) στο template tag ως παράμετρο.</p>\n<p>Ενώ τα προηγούμενα παραδείγματα μορφοποιούσαν την τρέχουσα ώρα σε ένα string και επέστρεφαν το string, υποθέστε τώρα ότι θέλετε να περάσετε ένα <a class=\"reference internal\" href=\"/el/1.11/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\">DateTimeField</code></a> από ένα object και θέλετε το template tag να μορφοποιήσει αυτό το object (αυτή την ημερομηνία-ώρα, αν θέλετε):</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>This post was last updated at <span class=\"cp\">{%</span> <span class=\"k\">format_time</span> <span class=\"nv\">blog_entry.date_updated</span> <span class=\"s2\">&quot;%Y-%m-%d %I:%M %p&quot;</span> <span class=\"cp\">%}</span>.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Αρχικά, η μέθοδος <code class=\"docutils literal notranslate\">token.split_contents()</code> θα επιστρέψει τρεις τιμές:</p>\n<ol class=\"arabic simple\">\n<li><p>Το όνομα του tag, <code class=\"docutils literal notranslate\">format_time</code>.</p></li>\n<li><p>Το string <code class=\"docutils literal notranslate\">'blog_entry.date_updated'</code> (χωρίς τα μονά εισαγωγικά).</p></li>\n<li><p>Το string που θα χρησιμοποιηθεί για την μορφοποίηση <code class=\"docutils literal notranslate\">'&quot;%Y-%m-%d %I:%M %p&quot;'</code>. Η επιστρεφόμενη τιμή από τη μέθοδο <code class=\"docutils literal notranslate\">split_contents()</code> θα συμπεριλάβει τα διπλά εισαγωγικά στην αρχή και το τέλος των strings (όπως ακριβώς εισήχθησαν στο tag μέσα στο template).</p></li>\n</ol>\n<p>Τώρα το tag θα αρχίσει να μοιάζει κάπως έτσι:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django</span> <span class=\"kn\">import</span> template\n\n<span class=\"k\">def</span> <span class=\"nf\">do_format_time</span><span class=\"p\">(</span>parser<span class=\"p\">,</span> token<span class=\"p\">):</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"c1\"># split_contents() knows not to split quoted strings.</span>\n        tag_name<span class=\"p\">,</span> date_to_be_formatted<span class=\"p\">,</span> format_string <span class=\"o\">=</span> token<span class=\"o\">.</span>split_contents<span class=\"p\">()</span>\n    <span class=\"k\">except</span> <span class=\"ne\">ValueError</span><span class=\"p\">:</span>\n        <span class=\"k\">raise</span> template<span class=\"o\">.</span>TemplateSyntaxError<span class=\"p\">(</span>\n            <span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag requires exactly two arguments&quot;</span> <span class=\"o\">%</span> token<span class=\"o\">.</span>contents<span class=\"o\">.</span>split<span class=\"p\">()[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n        <span class=\"p\">)</span>\n    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"p\">(</span>format_string<span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"o\">==</span> format_string<span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">]</span> <span class=\"ow\">and</span> format_string<span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"ow\">in</span> <span class=\"p\">(</span><span class=\"s1\">&#39;&quot;&#39;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;&#39;&quot;</span><span class=\"p\">)):</span>\n        <span class=\"k\">raise</span> template<span class=\"o\">.</span>TemplateSyntaxError<span class=\"p\">(</span>\n            <span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag&#39;s argument should be in quotes&quot;</span> <span class=\"o\">%</span> tag_name\n        <span class=\"p\">)</span>\n    <span class=\"k\">return</span> FormatTimeNode<span class=\"p\">(</span>date_to_be_formatted<span class=\"p\">,</span> format_string<span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">])</span>\n</code></pre></div>\n<p>Θα χρειαστεί επίσης να αλλάξετε και τον renderer για να λάβει τα πραγματικά περιεχόμενα του <code class=\"docutils literal notranslate\">date_updated</code> property του object <code class=\"docutils literal notranslate\">blog_entry</code>. Αυτό μπορεί να επιτευχθεί χρησιμοποιώντας την κλάση <code class=\"docutils literal notranslate\">Variable()</code> μέσα στο <code class=\"docutils literal notranslate\">django.template</code>.</p>\n<p>Για να χρησιμοποιήσετε την κλάση <code class=\"docutils literal notranslate\">Variable</code>, απλώς αρχικοποιήστε τη με το όνομα της μεταβλητής η οποία θα γίνει resolved και μετά καλέστε τη μέθοδο <code class=\"docutils literal notranslate\">variable.resolve(context)</code>. Άρα, για παράδειγμα:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span> <span class=\"nc\">FormatTimeNode</span><span class=\"p\">(</span>template<span class=\"o\">.</span>Node<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> date_to_be_formatted<span class=\"p\">,</span> format_string<span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span>date_to_be_formatted <span class=\"o\">=</span> template<span class=\"o\">.</span>Variable<span class=\"p\">(</span>date_to_be_formatted<span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span>format_string <span class=\"o\">=</span> format_string\n\n    <span class=\"k\">def</span> <span class=\"nf\">render</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> context<span class=\"p\">):</span>\n        <span class=\"k\">try</span><span class=\"p\">:</span>\n            actual_date <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>date_to_be_formatted<span class=\"o\">.</span>resolve<span class=\"p\">(</span>context<span class=\"p\">)</span>\n            <span class=\"k\">return</span> actual_date<span class=\"o\">.</span>strftime<span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>format_string<span class=\"p\">)</span>\n        <span class=\"k\">except</span> template<span class=\"o\">.</span>VariableDoesNotExist<span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"s1\">&#39;&#39;</span>\n</code></pre></div>\n<p>Η αναζήτηση της μεταβλητής (variable resolution) θα κάνει throw ένα exception <code class=\"docutils literal notranslate\">VariableDoesNotExist</code> αν δεν μπορεί να γίνει resolve το string (<code class=\"docutils literal notranslate\">'blog_entry.date_updated'</code>) που περάστηκε στο τρέχων context της σελίδας.</p>\n</section>\n<section id=\"setting-a-variable-in-the-context\">\n<h3>Θέτοντας μια μεταβλητή στο context<a class=\"heading-anchor\" href=\"#setting-a-variable-in-the-context\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Το παραπάνω παράδειγμα απλώς εξάγει μια τιμή. Γενικότερα, είναι περισσότερο ευέλικτο αν τα template tags σας θέτουν template μεταβλητές αντί να εξάγουν (εκτυπώνουν) τις τιμές τους. Με αυτό τον τρόπο, οι συντάκτες των template θα μπορούν να επαναχρησιμοποιούν τις τιμές τις οποίες δημιούργησαν τα template tags σας.</p>\n<p>Για να θέσετε μια μεταβλητή στο context, απλώς χρησιμοποιήστε την εκχώρηση της στο dictionary του context object μέσα στη μέθοδο <code class=\"docutils literal notranslate\">render()</code>. Παρακάτω φαίνεται μια ενημερωμένη έκδοση της κλάσης <code class=\"docutils literal notranslate\">CurrentTimeNode</code> η οποία θέτει την template μεταβλητή <code class=\"docutils literal notranslate\">current_time</code> αντί απλώς να την εκτυπώνει:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span> <span class=\"nn\">datetime</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django</span> <span class=\"kn\">import</span> template\n\n<span class=\"k\">class</span> <span class=\"nc\">CurrentTimeNode2</span><span class=\"p\">(</span>template<span class=\"o\">.</span>Node<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> format_string<span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span>format_string <span class=\"o\">=</span> format_string\n    <span class=\"k\">def</span> <span class=\"nf\">render</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> context<span class=\"p\">):</span>\n        context<span class=\"p\">[</span><span class=\"s1\">&#39;current_time&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> datetime<span class=\"o\">.</span>datetime<span class=\"o\">.</span>now<span class=\"p\">()</span><span class=\"o\">.</span>strftime<span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>format_string<span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;&#39;</span>\n</code></pre></div>\n<p>Σημειώστε ότι η μέθοδος <code class=\"docutils literal notranslate\">render()</code> επιστρέφει ένα κενό string. Η <code class=\"docutils literal notranslate\">render()</code> θα πρέπει πάντα να επιστρέφει ένα string. Αν το μόνο που κάνει ένα template tag είναι να ορίζει μια μεταβλητή, τότε η <code class=\"docutils literal notranslate\">render()</code> θα πρέπει να επιστρέφει ένα κενό string.</p>\n<p>Παρακάτω φαίνεται πως μπορείτε να χρησιμοποιείτε τη νέα αυτή έκδοση του tag:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">current_time</span> <span class=\"s2\">&quot;%Y-%M-%d %I:%M %p&quot;</span> <span class=\"cp\">%}</span><span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>The time is <span class=\"cp\">{{</span> <span class=\"nv\">current_time</span> <span class=\"cp\">}}</span>.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<aside class=\"admonition-variable-scope-in-context admonition\" role=\"note\">\n<p class=\"admonition-title\">Το variable scope του context</p>\n<p>Οποιαδήποτε μεταβλητή οριστεί στο context, θα είναι διαθέσιμη στο ίδιο <code class=\"docutils literal notranslate\">block</code> του template στο οποίο ορίστηκε. Αυτή η συμπεριφορά είναι σκόπιμη. Παρέχει ένα scope για μεταβλητές ούτως ώστε να μην συγκρούονται με κάποιο context από άλλα blocks.</p>\n</aside>\n<p>Αλλά υπάρχει ένα πρόβλημα με την κλάση <code class=\"docutils literal notranslate\">CurrentTimeNode2</code>: Το όνομα της μεταβλητής <code class=\"docutils literal notranslate\">current_time</code> είναι γραμμένο hard-coded. Αυτό σημαίνει ότι πρέπει να σιγουρευτείτε πως το template σας δεν χρησιμοποιεί πουθενά αλλού το <code class=\"docutils literal notranslate\">{{ current_time }}</code>, επειδή το <code class=\"docutils literal notranslate\">{% current_time %}</code> θα έκανε overwrite την τιμή της μεταβλητής. Μια πιο καθαρή λύση είναι να κάνετε το template tag να προσδιορίσει ένα όνομα για τη μεταβλητή, ως εξής:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">current_time</span> <span class=\"s2\">&quot;%Y-%M-%d %I:%M %p&quot;</span> <span class=\"k\">as</span> <span class=\"nv\">my_current_time</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>The current time is <span class=\"cp\">{{</span> <span class=\"nv\">my_current_time</span> <span class=\"cp\">}}</span>.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Για να το κάνετε αυτό, θα χρειαστεί να αλλάξετε και τη συνάρτηση του compilation και την κλάση <code class=\"docutils literal notranslate\">Node</code>, ως εξής:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span> <span class=\"nn\">re</span>\n\n<span class=\"k\">class</span> <span class=\"nc\">CurrentTimeNode3</span><span class=\"p\">(</span>template<span class=\"o\">.</span>Node<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> format_string<span class=\"p\">,</span> var_name<span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span>format_string <span class=\"o\">=</span> format_string\n        <span class=\"bp\">self</span><span class=\"o\">.</span>var_name <span class=\"o\">=</span> var_name\n    <span class=\"k\">def</span> <span class=\"nf\">render</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> context<span class=\"p\">):</span>\n        context<span class=\"p\">[</span><span class=\"bp\">self</span><span class=\"o\">.</span>var_name<span class=\"p\">]</span> <span class=\"o\">=</span> datetime<span class=\"o\">.</span>datetime<span class=\"o\">.</span>now<span class=\"p\">()</span><span class=\"o\">.</span>strftime<span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>format_string<span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;&#39;</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">do_current_time</span><span class=\"p\">(</span>parser<span class=\"p\">,</span> token<span class=\"p\">):</span>\n    <span class=\"c1\"># This version uses a regular expression to parse tag contents.</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"c1\"># Splitting by None == splitting by spaces.</span>\n        tag_name<span class=\"p\">,</span> arg <span class=\"o\">=</span> token<span class=\"o\">.</span>contents<span class=\"o\">.</span>split<span class=\"p\">(</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n    <span class=\"k\">except</span> <span class=\"ne\">ValueError</span><span class=\"p\">:</span>\n        <span class=\"k\">raise</span> template<span class=\"o\">.</span>TemplateSyntaxError<span class=\"p\">(</span>\n            <span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag requires arguments&quot;</span> <span class=\"o\">%</span> token<span class=\"o\">.</span>contents<span class=\"o\">.</span>split<span class=\"p\">()[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n        <span class=\"p\">)</span>\n    m <span class=\"o\">=</span> re<span class=\"o\">.</span>search<span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;(.*?) as (\\w+)&#39;</span><span class=\"p\">,</span> arg<span class=\"p\">)</span>\n    <span class=\"k\">if</span> <span class=\"ow\">not</span> m<span class=\"p\">:</span>\n        <span class=\"k\">raise</span> template<span class=\"o\">.</span>TemplateSyntaxError<span class=\"p\">(</span><span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag had invalid arguments&quot;</span> <span class=\"o\">%</span> tag_name<span class=\"p\">)</span>\n    format_string<span class=\"p\">,</span> var_name <span class=\"o\">=</span> m<span class=\"o\">.</span>groups<span class=\"p\">()</span>\n    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"p\">(</span>format_string<span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"o\">==</span> format_string<span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">]</span> <span class=\"ow\">and</span> format_string<span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"ow\">in</span> <span class=\"p\">(</span><span class=\"s1\">&#39;&quot;&#39;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;&#39;&quot;</span><span class=\"p\">)):</span>\n        <span class=\"k\">raise</span> template<span class=\"o\">.</span>TemplateSyntaxError<span class=\"p\">(</span>\n            <span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> tag&#39;s argument should be in quotes&quot;</span> <span class=\"o\">%</span> tag_name\n        <span class=\"p\">)</span>\n    <span class=\"k\">return</span> CurrentTimeNode3<span class=\"p\">(</span>format_string<span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">],</span> var_name<span class=\"p\">)</span>\n</code></pre></div>\n<p>Η διαφορά εδώ είναι ότι η μέθοδος <code class=\"docutils literal notranslate\">do_current_time()</code> παίρνει το format μορφοποίησης και το όνομα της μεταβλητής και δίνει και τα δύο στην κλάση <code class=\"docutils literal notranslate\">CurrentTimeNode3</code>.</p>\n<p>Τέλος, αν θέλετε μόνο να έχετε μια απλή σύνταξη για το δικό σας template tag που αλληλεπιδρά με το context και το ενημερώνει, σκεφτείτε να χρησιμοποιήσετε τη συντόμευση <a class=\"reference internal\" href=\"#django.template.Library.simple_tag\" title=\"django.template.Library.simple_tag\"><code class=\"xref py py-meth docutils literal notranslate\">simple_tag()</code></a>, η οποία υποστηρίζει τον ορισμό μεταβλητής της εξόδου ενός tag (μέσω της λέξη-κλειδί <code class=\"docutils literal notranslate\">as</code>, όπως είδαμε παραπάνω).</p>\n</section>\n<section id=\"parsing-until-another-block-tag\">\n<h3>Κάνοντας parsing μέχρι να βρεθεί κάποιο άλλο block tag<a class=\"heading-anchor\" href=\"#parsing-until-another-block-tag\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Τα template tags μπορούν να δουλέψουν αλυσιδωτά. Για παράδειγμα, το στάνταρντ tag <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/#std-templatetag-comment\"><code class=\"xref std std-ttag docutils literal notranslate\">{% comment %}</code></a> αγνοεί τα πάντα μέχρι να βρει το tag <code class=\"docutils literal notranslate\">{% endcomment %}</code>. Για να δημιουργήσετε ένα template tag όπως αυτό, χρησιμοποιήστε τη μέθοδο <code class=\"docutils literal notranslate\">parser.parse()</code> μέσα στη συνάρτηση του compilation.</p>\n<p>Εδώ φαίνεται η υλοποίηση της απλοποιημένης έκδοσης του tag <code class=\"docutils literal notranslate\">{% comment %}</code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span> <span class=\"nf\">do_comment</span><span class=\"p\">(</span>parser<span class=\"p\">,</span> token<span class=\"p\">):</span>\n    nodelist <span class=\"o\">=</span> parser<span class=\"o\">.</span>parse<span class=\"p\">((</span><span class=\"s1\">&#39;endcomment&#39;</span><span class=\"p\">,))</span>\n    parser<span class=\"o\">.</span>delete_first_token<span class=\"p\">()</span>\n    <span class=\"k\">return</span> CommentNode<span class=\"p\">()</span>\n\n<span class=\"k\">class</span> <span class=\"nc\">CommentNode</span><span class=\"p\">(</span>template<span class=\"o\">.</span>Node<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"nf\">render</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> context<span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;&#39;</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Σημείωση</p>\n<p>Η υλοποίηση του tag <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/#std-templatetag-comment\"><code class=\"xref std std-ttag docutils literal notranslate\">{% comment %}</code></a> διαφέρει ελαφρώς στο ότι  επιτρέπει την εμφάνιση broken template tags μεταξύ του <code class=\"docutils literal notranslate\">{% comment %}</code> και του <code class=\"docutils literal notranslate\">{% endcomment %}</code>. Το κάνει αυτό καλώντας τη μέθοδο <code class=\"docutils literal notranslate\">parser.skip_past('endcomment')</code> αντί της <code class=\"docutils literal notranslate\">parser.parse(('endcomment',))</code> ακολουθούμενη από τη μέθοδο <code class=\"docutils literal notranslate\">parser.delete_first_token()</code>, με αποτέλεσμα την αποφυγή της δημιουργίας μιας λίστας από nodes.</p>\n</aside>\n<p>Η μέθοδος <code class=\"docutils literal notranslate\">parser.parse()</code> παίρνει ένα tuple από ονόματα block tags “”να γίνει parse μέχρι””. Επιστρέφει ένα instance του <code class=\"docutils literal notranslate\">django.template.NodeList</code>, το οποίο είναι μια λίστα από <code class=\"docutils literal notranslate\">Node</code> objects τα οποία βρήκε ο parser “”πριν”” βρει κάποιο από τα tags που είναι μέσα στο tuple.</p>\n<p>Στο <code class=\"docutils literal notranslate\">&quot;nodelist = parser.parse(('endcomment',))&quot;</code> στο παραπάνω παράδειγμα, η <code class=\"docutils literal notranslate\">nodelist</code> είναι μια λίστα από όλα τα nodes μεταξύ του <code class=\"docutils literal notranslate\">{% comment %}</code> και του <code class=\"docutils literal notranslate\">{% endcomment %}</code>, χωρίς τα ίδια τα <code class=\"docutils literal notranslate\">{% comment %}</code> και <code class=\"docutils literal notranslate\">{% endcomment %}</code>.</p>\n<p>Αφού καλεστεί η <code class=\"docutils literal notranslate\">parser.parse()</code>, ο parser δεν έχει «καταναλώσει» ακόμα το <code class=\"docutils literal notranslate\">{% endcomment %}</code> tag, οπότε ο κώδικας χρειάζεται να καλέσει ρητώς τη μέθοδο <code class=\"docutils literal notranslate\">parser.delete_first_token()</code>.</p>\n<p>Η μέθοδος <code class=\"docutils literal notranslate\">CommentNode.render()</code> απλώς επιστρέφει ένα κενό string. Οτιδήποτε μεταξύ του <code class=\"docutils literal notranslate\">{% comment %}</code> και <code class=\"docutils literal notranslate\">{% endcomment %}</code> αγνοείται.</p>\n</section>\n<section id=\"parsing-until-another-block-tag-and-saving-contents\">\n<h3>Κάνοντας parsing μέχρι να βρεθεί κάποιο άλλο block tag και αποθήκευση περιεχομένων<a class=\"heading-anchor\" href=\"#parsing-until-another-block-tag-and-saving-contents\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Στο προηγούμενο παράδειγμα, η συνάρτηση <code class=\"docutils literal notranslate\">do_comment()</code> απέρριπτε τα πάντα μεταξύ του blck tag <code class=\"docutils literal notranslate\">{% comment %}</code> και <code class=\"docutils literal notranslate\">{% endcomment %}</code>, επειδή θεωρούνταν σχόλια και αυτά δεν γινόντουσαν render στην τελική σελίδα που θα έβλεπε ο χρήστης. Αντί να γίνεται αυτό, μπορείτε να κάνετε κάτι με τον κώδικα μεταξύ των block tags.</p>\n<p>Για παράδειγμα, εδώ φαίνεται ένα παραμετροποιήσιμο template tag, με το όνομα <code class=\"docutils literal notranslate\">{% upper %}</code>, το οποίο μετατρέπει σε κεφαλαία γράμματα όλους τους χαρακτήρες μεταξύ του ίδιου και του <code class=\"docutils literal notranslate\">{% endupper %}</code>.</p>\n<p>Χρήση</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">upper</span> <span class=\"cp\">%}</span>This will appear in uppercase, <span class=\"cp\">{{</span> <span class=\"nv\">your_name</span> <span class=\"cp\">}}</span>.<span class=\"cp\">{%</span> <span class=\"k\">endupper</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>Όπως στο προηγούμενο παράδειγμα, θα χρησιμοποιήσουμε τη μέθοδο <code class=\"docutils literal notranslate\">parser.parse()</code>. Αλλά αυτή τη φορά, θα περάσουμε τη <code class=\"docutils literal notranslate\">nodelist</code> στο <code class=\"docutils literal notranslate\">Node</code>, εν αντιθέσει με την προηγούμενη φορά που επιστρέφαμε το <code class=\"docutils literal notranslate\">CommentNode()</code> χωρίς κάποιο <code class=\"docutils literal notranslate\">nodelist</code> μέσα:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span> <span class=\"nf\">do_upper</span><span class=\"p\">(</span>parser<span class=\"p\">,</span> token<span class=\"p\">):</span>\n    nodelist <span class=\"o\">=</span> parser<span class=\"o\">.</span>parse<span class=\"p\">((</span><span class=\"s1\">&#39;endupper&#39;</span><span class=\"p\">,))</span>\n    parser<span class=\"o\">.</span>delete_first_token<span class=\"p\">()</span>\n    <span class=\"k\">return</span> UpperNode<span class=\"p\">(</span>nodelist<span class=\"p\">)</span>\n\n<span class=\"k\">class</span> <span class=\"nc\">UpperNode</span><span class=\"p\">(</span>template<span class=\"o\">.</span>Node<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> nodelist<span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span>nodelist <span class=\"o\">=</span> nodelist\n    <span class=\"k\">def</span> <span class=\"nf\">render</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> context<span class=\"p\">):</span>\n        output <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>nodelist<span class=\"o\">.</span>render<span class=\"p\">(</span>context<span class=\"p\">)</span>\n        <span class=\"k\">return</span> output<span class=\"o\">.</span>upper<span class=\"p\">()</span>\n</code></pre></div>\n<p>Η μοναδική καινούργια έννοια εδώ είναι το <code class=\"docutils literal notranslate\">self.nodelist.render(context)</code> μέσα στη μέθοδο <code class=\"docutils literal notranslate\">UpperNode.render()</code>.</p>\n<p>Για περισσότερα παραδείγματα περίπλοκων renderings, δείτε τον πηγαίο κώδικα του tag <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/#std-templatetag-for\"><code class=\"xref std std-ttag docutils literal notranslate\">{% for %}</code></a> στο αρχείο <code class=\"docutils literal notranslate\">django/template/defaulttags.py</code> και το tag <a class=\"reference internal\" href=\"/el/1.11/ref/templates/builtins/#std-templatetag-if\"><code class=\"xref std std-ttag docutils literal notranslate\">{% if %}</code></a> στο αρχείο <code class=\"docutils literal notranslate\">django/template/smartif.py</code>.</p>\n</section>\n</section>","rootId":"custom-template-tags-and-filters","toc":[{"title":"Διάταξη κώδικα","anchor":"code-layout","children":[]},{"title":"Γράφοντας δικά σας template φίλτρα","anchor":"writing-custom-template-filters","children":[{"title":"Κάνοντας register τα δικά σας φίλτρα","anchor":"registering-custom-filters","children":[]},{"title":"Template φίλτρα που περιμένουν strings","anchor":"template-filters-that-expect-strings","children":[]},{"title":"Φίλτρα και auto-escaping","anchor":"filters-and-auto-escaping","children":[]},{"title":"Φίλτρα και ζώνες ώρας","anchor":"filters-and-time-zones","children":[]}]},{"title":"Γράφοντας δικάς σας template tags","anchor":"writing-custom-template-tags","children":[{"title":"Απλά tags","anchor":"simple-tags","children":[]},{"title":"Inclusion tags","anchor":"inclusion-tags","children":[]},{"title":"Assignment tags","anchor":"assignment-tags","children":[]},{"title":"Παραμετροποιήσιμα template tags για προχωρημένους","anchor":"advanced-custom-template-tags","children":[]},{"title":"Μια γρήγορη ματιά","anchor":"a-quick-overview","children":[]},{"title":"Γράφοντας τη συνάρτηση του compilation","anchor":"writing-the-compilation-function","children":[]},{"title":"Γράφοντας τον renderer","anchor":"writing-the-renderer","children":[]},{"title":"Εκτιμήσεις σχετικά με το auto-escaping","anchor":"auto-escaping-considerations","children":[]},{"title":"Εκτιμήσεις σχετικά με την ασφάλεια των threads","anchor":"thread-safety-considerations","children":[]},{"title":"Κάνοντας register το tag","anchor":"registering-the-tag","children":[]},{"title":"Περνώντας template μεταβλητές στο tag","anchor":"passing-template-variables-to-the-tag","children":[]},{"title":"Θέτοντας μια μεταβλητή στο context","anchor":"setting-a-variable-in-the-context","children":[]},{"title":"Κάνοντας parsing μέχρι να βρεθεί κάποιο άλλο block tag","anchor":"parsing-until-another-block-tag","children":[]},{"title":"Κάνοντας parsing μέχρι να βρεθεί κάποιο άλλο block tag και αποθήκευση περιεχομένων","anchor":"parsing-until-another-block-tag-and-saving-contents","children":[]}]}],"breadcrumbs":[{"docname":"howto/index","title":"Οδηγοί «Πως-να»","url":"/el/1.11/howto/"}],"prev":{"docname":"howto/custom-lookups","title":"Παραμετροποιήσιμα Lookups","url":"/el/1.11/howto/custom-lookups/"},"next":{"docname":"howto/custom-file-storage","title":"Γράφοντας ένα δικό σας σύστημα αποθήκευσης (storage system)","url":"/el/1.11/howto/custom-file-storage/"},"formats":{"html":"/el/1.11/howto/custom-template-tags/","markdown":"/el/1.11/howto/custom-template-tags.md","json":"/el/1.11/howto/custom-template-tags.json"},"source":"https://github.com/django/django/blob/stable/1.11.x/docs/howto/custom-template-tags.txt","official":"https://docs.djangoproject.com/el/1.11/howto/custom-template-tags/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10"],"inLocales":["en","fr","ja","id","pt-br","ko","es","el","pl"]}