{"title":"Γράφοντας το πρώτο σας Django app, μέρος 3","version":"4.1","locale":"el","docname":"intro/tutorial03","url":"/el/4.1/intro/tutorial03/","canonical":"https://djangodocs.dev/el/4.1/intro/tutorial03/","summary":"This tutorial begins where Tutorial 2 left off. We’re continuing the web-poll application and will focus on creating the public interface – «views.» Που να ψάξετε…","html":"<h1>Γράφοντας το πρώτο σας Django app, μέρος 3<a class=\"heading-anchor\" href=\"#writing-your-first-django-app-part-3\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>This tutorial begins where <a class=\"reference internal\" href=\"/el/4.1/intro/tutorial02/\"><span class=\"doc\">Tutorial 2</span></a> left off. We’re\ncontinuing the web-poll application and will focus on creating the public\ninterface – «views.»</p>\n<aside class=\"admonition-where-to-get-help admonition\">\n<p class=\"admonition-title\">Που να ψάξετε για βοήθεια</p>\n<p>If you’re having trouble going through this tutorial, please head over to\nthe <a class=\"reference internal\" href=\"/el/4.1/faq/help/\"><span class=\"doc\">Getting Help</span></a> section of the FAQ.</p>\n</aside>\n<section id=\"overview\">\n<h2>Επισκόπηση<a class=\"heading-anchor\" href=\"#overview\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>A view is a «type» of web page in your Django application that generally serves\na specific function and has a specific template. For example, in a blog\napplication, you might have the following views:</p>\n<ul class=\"simple\">\n<li><p>Blog homepage – προβάλει τα μερικά από τα τελευταία entries (καταχωρήσεις).</p></li>\n<li><p>Σελίδα «λεπτομερειών» μιας entry (καταχώρησης) – μια permalink σελίδα για ένα συγκεκριμένο entry.</p></li>\n<li><p>Σελίδα archive ανά ημερολογιακό χρόνο – προβάλει όλους τους μήνες που έχουν καταχωρήσεις για το δοθέντα έτος.</p></li>\n<li><p>Σελίδα archive ανά ημερολογιακό μήνα – προβάλει όλες τις μέρες που έχουν καταχωρήσεις για το δοθέντα μήνα.</p></li>\n<li><p>Σελίδα archive ανά ημερολογιακή μέρα – προβάλει όλα τα entries μια συγκεκριμένη μέρα.</p></li>\n<li><p>Προσθήκη σχολίου – χειρίζεται τα σχόλια πάνω στα posts για ένα συγκεκριμένο entry.</p></li>\n</ul>\n<p>Στη δική μας εφαρμογή, θα έχουμε τα ακόλουθα τέσσερα views:</p>\n<ul class=\"simple\">\n<li><p>Αρχική σελίδα («index») ερωτήσεων – προβάλει τις τελευταίες ερωτήσεις.</p></li>\n<li><p>Σελίδα «λεπτομερειών» μιας ερώτησης – προβάλει μια ερώτηση, χωρίς αποτελέσματα, αλλά με μια φόρμα (η οποία θα περιέχει τις επιλογές της ερώτησης) προς ψήφιση.</p></li>\n<li><p>Σελίδα «αποτελεσμάτων» μιας ερώτησης – προβάλει τα αποτελέσματα μιας συγκεκριμένης ερώτησης.</p></li>\n<li><p>Προσθήκη ψήφου – χειρίζεται τη ψήφο μιας συγκεκριμένης επιλογής μιας συγκεκριμένης ερώτησης.</p></li>\n</ul>\n<p>In Django, web pages and other content are delivered by views. Each view is\nrepresented by a Python function (or method, in the case of class-based views).\nDjango will choose a view by examining the URL that’s requested (to be precise,\nthe part of the URL after the domain name).</p>\n<p>Now in your time on the web you may have come across such beauties as\n<code class=\"docutils literal notranslate\"><span class=\"pre\">ME2/Sites/dirmod.htm?sid=&amp;type=gen&amp;mod=Core+Pages&amp;gid=A6CD4967199A42D9B65B1B</span></code>.\nYou will be pleased to know that Django allows us much more elegant\n<em>URL patterns</em> than that.</p>\n<p>A URL pattern is the general form of a URL - for example:\n<code class=\"docutils literal notranslate\"><span class=\"pre\">/newsarchive/&lt;year&gt;/&lt;month&gt;/</span></code>.</p>\n<p>To get from a URL to a view, Django uses what are known as “URLconfs”. A\nURLconf maps URL patterns to views.</p>\n<p>This tutorial provides basic instruction in the use of URLconfs, and you can\nrefer to <a class=\"reference internal\" href=\"/el/4.1/topics/http/urls/\"><span class=\"doc\">URL dispatcher</span></a> for more information.</p>\n</section>\n<section id=\"writing-more-views\">\n<h2>Γράφοντας περισσότερα views<a class=\"heading-anchor\" href=\"#writing-more-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Ας προσθέσουμε τώρα μερικά views παραπάνω, στο αρχείο <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code>. Αυτά τα views είναι ελαφρώς διαφορετικά, επειδή παίρνουν και όρισμα (argument):</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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=\"Python code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">detail</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">question_id</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;You&#39;re looking at question </span><span class=\"si\">%s</span><span class=\"s2\">.&quot;</span> <span class=\"o\">%</span> <span class=\"n\">question_id</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">results</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">question_id</span><span class=\"p\">):</span>\n    <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;You&#39;re looking at the results of question </span><span class=\"si\">%s</span><span class=\"s2\">.&quot;</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"n\">response</span> <span class=\"o\">%</span> <span class=\"n\">question_id</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">vote</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">question_id</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;You&#39;re voting on question </span><span class=\"si\">%s</span><span class=\"s2\">.&quot;</span> <span class=\"o\">%</span> <span class=\"n\">question_id</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Wire these new views into the <code class=\"docutils literal notranslate\"><span class=\"pre\">polls.urls</span></code> module by adding the following\n<a class=\"reference internal\" href=\"/el/4.1/ref/urls/#django.urls.path\" title=\"django.urls.path\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">path()</span></code></a> calls:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/urls.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">path</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">views</span>\n\n<span class=\"n\">urlpatterns</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"c1\"># ex: /polls/</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">index</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;index&#39;</span><span class=\"p\">),</span>\n    <span class=\"c1\"># ex: /polls/5/</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;&lt;int:question_id&gt;/&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">detail</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;detail&#39;</span><span class=\"p\">),</span>\n    <span class=\"c1\"># ex: /polls/5/results/</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;&lt;int:question_id&gt;/results/&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">results</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;results&#39;</span><span class=\"p\">),</span>\n    <span class=\"c1\"># ex: /polls/5/vote/</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;&lt;int:question_id&gt;/vote/&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">vote</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;vote&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>Ρίξτε μια ματιά με τον browser σας στη σελίδα, «/polls/34/». Με το που πατήσετε enter, το GET request που κάνατε για αυτό το URL θα κάνει trigger το Django project σας, θα γίνει σκανάρισμα των URLs, θα ταιριάξει το δεύτερο URL pattern το οποίο με τη σειρά του θα καλέσει τη μέθοδο <code class=\"docutils literal notranslate\"><span class=\"pre\">detail()</span></code> και η τελευταία θα προβάλει το μήνυμα μαζί με το ID που εισήχθη στο URL (το response το οποίο επιστρέφει η <code class=\"docutils literal notranslate\"><span class=\"pre\">detail</span></code> συνάρτηση). Τώρα δοκιμάστε το «/polls/34/results/» και το «/polls/34/vote/» – αυτά τα URLs θα εμφανίσουν μια σελίδα placeholder για τα αποτελέσματα και τις ψηφοφορίες αντίστοιχα.</p>\n<p>When somebody requests a page from your website – say, «/polls/34/», Django\nwill load the <code class=\"docutils literal notranslate\"><span class=\"pre\">mysite.urls</span></code> Python module because it’s pointed to by the\n<a class=\"reference internal\" href=\"/el/4.1/ref/settings/#std-setting-ROOT_URLCONF\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ROOT_URLCONF</span></code></a> setting. It finds the variable named <code class=\"docutils literal notranslate\"><span class=\"pre\">urlpatterns</span></code>\nand traverses the patterns in order. After finding the match at <code class=\"docutils literal notranslate\"><span class=\"pre\">'polls/'</span></code>,\nit strips off the matching text (<code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;polls/&quot;</span></code>) and sends the remaining text –\n<code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;34/&quot;</span></code> – to the “polls.urls” URLconf for further processing. There it\nmatches <code class=\"docutils literal notranslate\"><span class=\"pre\">'&lt;int:question_id&gt;/'</span></code>, resulting in a call to the <code class=\"docutils literal notranslate\"><span class=\"pre\">detail()</span></code> view\nlike 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=\"n\">detail</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"o\">=&lt;</span><span class=\"n\">HttpRequest</span> <span class=\"nb\">object</span><span class=\"o\">&gt;</span><span class=\"p\">,</span> <span class=\"n\">question_id</span><span class=\"o\">=</span><span class=\"mi\">34</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">question_id=34</span></code> part comes from <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;int:question_id&gt;</span></code>. Using angle\nbrackets «captures» part of the URL and sends it as a keyword argument to the\nview function. The <code class=\"docutils literal notranslate\"><span class=\"pre\">question_id</span></code> part of the string defines the name that\nwill be used to identify the matched pattern, and the <code class=\"docutils literal notranslate\"><span class=\"pre\">int</span></code> part is a\nconverter that determines what patterns should match this part of the URL path.\nThe colon (<code class=\"docutils literal notranslate\"><span class=\"pre\">:</span></code>) separates the converter and pattern name.</p>\n</section>\n<section id=\"write-views-that-actually-do-something\">\n<h2>Γράφοντας views οι οποίες κάνουν κάτι<a class=\"heading-anchor\" href=\"#write-views-that-actually-do-something\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Κάθε view είναι υπεύθυνο στο να κάνει ένα από δύο πράγματα: να επιστρέφει ένα <a class=\"reference internal\" href=\"/el/4.1/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> object το οποίο περιέχει το περιεχόμενο για την σελίδα που ζητήθηκε ή να κάνει raise κάποιο exception όπως το <a class=\"reference internal\" href=\"/el/4.1/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a>. Τα υπόλοιπα εξαρτώνται από εσάς.</p>\n<p>Το view σας μπορεί να διαβάσει records από την βάση δεδομένων ή όχι. Μπορεί να χρησιμοποιήσει ένα template system όπως αυτό του Django – ή κάποιο τρίτο Python template system – ή όχι. Μπορεί να παράγει κάποιο PDF αρχείο, να εξάγει XML, να δημιουργεί κάποιο ZIP αρχείο, να εξάγει JSON δεδομένα, βασικά μπορεί να κάνει τα πάντα χρησιμοποιώντας οποιεσδήποτε βιβλιοθήκες Python επιθυμείτε.</p>\n<p>Το μόνο που απαιτείται από το Django είναι ένα <a class=\"reference internal\" href=\"/el/4.1/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> ή μια exception.</p>\n<p>Επειδή είναι βολικό, θα χρησιμοποιήσουμε το database API του Django, το οποίο καλύψαμε στον <a class=\"reference internal\" href=\"/el/4.1/intro/tutorial02/\"><span class=\"doc\">Οδηγό 2</span></a>. Παρακάτω βλέπετε ένα καινούργιο view με το όνομα <code class=\"docutils literal notranslate\"><span class=\"pre\">index()</span></code>, το οποίο εμφανίζει τις τελευταίες 5 ερωτήσεις (που υπάρχουν στην βάση δεδομένων), διαχωρισμένες με κόμμα, βάση της ημερομηνίας που καταχωρήθηκαν (δημιουργήθηκαν):</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponse</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">index</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">latest_question_list</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"s1\">&#39;-pub_date&#39;</span><span class=\"p\">)[:</span><span class=\"mi\">5</span><span class=\"p\">]</span>\n    <span class=\"n\">output</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;, &#39;</span><span class=\"o\">.</span><span class=\"n\">join</span><span class=\"p\">([</span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">question_text</span> <span class=\"k\">for</span> <span class=\"n\">q</span> <span class=\"ow\">in</span> <span class=\"n\">latest_question_list</span><span class=\"p\">])</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"n\">output</span><span class=\"p\">)</span>\n\n<span class=\"c1\"># Leave the rest of the views (detail, results, vote) unchanged</span>\n</code></pre></figure>\n<p>Υπάρχει ένα πρόβλημα εδώ, όμως: ο σχεδιασμός της σελίδας (design) είναι γραμμένος στο view. Αν χρειαστεί να αλλάξετε τον τρόπο εμφάνιση της σελίδας σας, θα χρειαστεί να επεξεργαστείτε αυτόν τον Python κώδικα. Ας κάνουμε κάτι καλύτερο. Ας χρησιμοποιήσουμε το template system του Django για να διαχωρίσουμε το design από τον Python κώδικα δημιουργώντας ένα template που το view μπορεί να χρησιμοποιήσει.</p>\n<p>Για αρχή, δημιουργήστε ένα φάκελο με το όνομα <code class=\"docutils literal notranslate\"><span class=\"pre\">templates</span></code> κάτω από τον φάκελο <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code>. Το Django θα κοιτάξει για templates εκεί.</p>\n<p>Η ρύθμιση <a class=\"reference internal\" href=\"/el/4.1/ref/settings/#std-setting-TEMPLATES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TEMPLATES</span></code></a> του project σας περιγράφει πως το Django θα φορτώνει και θα κάνει render τα templates. Η προεπιλεγμένη ρύθμιση στο αρχείο settings παραμετροποιεί το <code class=\"docutils literal notranslate\"><span class=\"pre\">DjangoTemplates</span></code> backend του οποίου η ρύθμιση <a class=\"reference internal\" href=\"/el/4.1/ref/settings/#std-setting-TEMPLATES-APP_DIRS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">APP_DIRS</span></code></a> είναι ρυθμισμένη στο <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>. Έτσι, το <code class=\"docutils literal notranslate\"><span class=\"pre\">DjangoTemplates</span></code> ψάχνει για ένα υπό-φάκελο «templates» σε κάθε εφαρμογή (app) που είναι περασμένη στη ρύθμιση <a class=\"reference internal\" href=\"/el/4.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a>.</p>\n<p>Within the <code class=\"docutils literal notranslate\"><span class=\"pre\">templates</span></code> directory you have just created, create another\ndirectory called <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code>, and within that create a file called\n<code class=\"docutils literal notranslate\"><span class=\"pre\">index.html</span></code>. In other words, your template should be at\n<code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates/polls/index.html</span></code>. Because of how the <code class=\"docutils literal notranslate\"><span class=\"pre\">app_directories</span></code>\ntemplate loader works as described above, you can refer to this template within\nDjango as <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/index.html</span></code>.</p>\n<aside class=\"admonition-template-namespacing admonition\">\n<p class=\"admonition-title\">Template namespacing</p>\n<p>Now we <em>might</em> be able to get away with putting our templates directly in\n<code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates</span></code> (rather than creating another <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> subdirectory),\nbut it would actually be a bad idea. Django will choose the first template\nit finds whose name matches, and if you had a template with the same name\nin a <em>different</em> application, Django would be unable to distinguish between\nthem. We need to be able to point Django at the right one, and the best\nway to ensure this is by <em>namespacing</em> them. That is, by putting those\ntemplates inside <em>another</em> directory named for the application itself.</p>\n</aside>\n<p>Βάλτε τον ακόλουθο κώδικα στο template:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates/polls/index.html</span></code></figcaption>\n<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\">if</span> <span class=\"nv\">latest_question_list</span> <span class=\"cp\">%}</span>\n    <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\">question</span> <span class=\"k\">in</span> <span class=\"nv\">latest_question_list</span> <span class=\"cp\">%}</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;/polls/</span><span class=\"cp\">{{</span> <span class=\"nv\">question.id</span> <span class=\"cp\">}}</span><span class=\"s\">/&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&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<span class=\"cp\">{%</span> <span class=\"k\">else</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>No polls are available.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n</code></pre></figure>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Σημείωση</p>\n<p>To make the tutorial shorter, all template examples use incomplete HTML. In\nyour own projects you should use <a class=\"reference external\" href=\"https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting_started#anatomy_of_an_html_document\">complete HTML documents</a>.</p>\n</aside>\n<p>Τώρα, ας ανανεώσουμε το <code class=\"docutils literal notranslate\"><span class=\"pre\">index</span></code> view μέσα στο αρχείο <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code> ούτως ώστε να χρησιμοποιήσει το νέο μας template:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.template</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">loader</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">index</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">latest_question_list</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"s1\">&#39;-pub_date&#39;</span><span class=\"p\">)[:</span><span class=\"mi\">5</span><span class=\"p\">]</span>\n    <span class=\"n\">template</span> <span class=\"o\">=</span> <span class=\"n\">loader</span><span class=\"o\">.</span><span class=\"n\">get_template</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls/index.html&#39;</span><span class=\"p\">)</span>\n    <span class=\"n\">context</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;latest_question_list&#39;</span><span class=\"p\">:</span> <span class=\"n\">latest_question_list</span><span class=\"p\">,</span>\n    <span class=\"p\">}</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">))</span>\n</code></pre></figure>\n<p>Αυτός ο κώδικας φορτώνει το template με το όνομα <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/index.html</span></code> και περνάει σε αυτό ένα context. Το context είναι ένα dictionary το οποίο αντιστοιχεί template variable ονόματα σε Python objects.</p>\n<p>Πηγαίνετε στη σελίδα με το browser σας στο «/polls/» και θα πρέπει να δείτε μια λίστα (με κουκίδες) η οποία περιέχει την ερώτηση «What’s up» που φτιάξαμε στον <a class=\"reference internal\" href=\"/el/4.1/intro/tutorial02/\"><span class=\"doc\">Οδηγό 2</span></a>. Το link δείχνει στην σελίδα με τις λεπτομέρειες της ερώτησης.</p>\n<section id=\"a-shortcut-render\">\n<h3>Η συντόμευση: <a class=\"reference internal\" href=\"/el/4.1/topics/http/shortcuts/#django.shortcuts.render\" title=\"django.shortcuts.render\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">render()</span></code></a><a class=\"heading-anchor\" href=\"#a-shortcut-render\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Είναι πολύ συνηθισμένο να φορτώνεται ένα template, να γεμίζεται ένα context και να επιστρέφεται ένα\n<a class=\"reference internal\" href=\"/el/4.1/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> object του οποίου το αποτέλεσμα θα είναι το rendered template. Το Django παρέχει μια συντόμευση για όλα αυτά. Ορίστε πάλι το <code class=\"docutils literal notranslate\"><span class=\"pre\">index()</span></code> view, γραμμένο από την αρχή:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.shortcuts</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">render</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">index</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">latest_question_list</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"s1\">&#39;-pub_date&#39;</span><span class=\"p\">)[:</span><span class=\"mi\">5</span><span class=\"p\">]</span>\n    <span class=\"n\">context</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s1\">&#39;latest_question_list&#39;</span><span class=\"p\">:</span> <span class=\"n\">latest_question_list</span><span class=\"p\">}</span>\n    <span class=\"k\">return</span> <span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"s1\">&#39;polls/index.html&#39;</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Σημειώστε ότι, αφού χρησιμοποιήσουμε την <a class=\"reference internal\" href=\"/el/4.1/topics/http/shortcuts/#django.shortcuts.render\" title=\"django.shortcuts.render\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">render()</span></code></a> για <em>όλες</em> τις views, δεν χρειάζεται πλέον να κάνουμε import τα <a class=\"reference internal\" href=\"/el/4.1/topics/templates/#module-django.template.loader\" title=\"django.template.loader\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">loader</span></code></a> και <a class=\"reference internal\" href=\"/el/4.1/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a>. Παραταύτα, θα χρειαστεί να κρατήσετε το <code class=\"docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code> αν έχετε ακόμη τις μεθόδους  για το``detail``, <code class=\"docutils literal notranslate\"><span class=\"pre\">results</span></code> και <code class=\"docutils literal notranslate\"><span class=\"pre\">vote</span></code> view.</p>\n<p>Η συνάρτηση <a class=\"reference internal\" href=\"/el/4.1/topics/http/shortcuts/#django.shortcuts.render\" title=\"django.shortcuts.render\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">render()</span></code></a> παίρνει ως πρώτο όρισμα το request object, ως δεύτερο το όνομα του template και ένα dictionary ως τρίτο προαιρετικό. Επιστρέφει ένα <a class=\"reference internal\" href=\"/el/4.1/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> object του δηλωθέν template το οποίο template έχει γίνει rendered βάση του δοθέν context.</p>\n</section>\n</section>\n<section id=\"raising-a-404-error\">\n<h2>Raising σφάλμα 404<a class=\"heading-anchor\" href=\"#raising-a-404-error\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Σε αυτό το σημείο θα πειράξουμε το view που αφορά στις λεπτομέρειες μιας ερώτησης – τη σελίδα, δηλαδή, η οποία εμφανίζει την ερώτηση για μια συγκεκριμένη ψηφοφορία. Αυτό είναι το view:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Http404</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.shortcuts</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">render</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n<span class=\"c1\"># ...</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">detail</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">question_id</span><span class=\"p\">):</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"n\">question</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"n\">question_id</span><span class=\"p\">)</span>\n    <span class=\"k\">except</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">DoesNotExist</span><span class=\"p\">:</span>\n        <span class=\"k\">raise</span> <span class=\"n\">Http404</span><span class=\"p\">(</span><span class=\"s2\">&quot;Question does not exist&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"s1\">&#39;polls/detail.html&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;question&#39;</span><span class=\"p\">:</span> <span class=\"n\">question</span><span class=\"p\">})</span>\n</code></pre></figure>\n<p>Το νέο concept εδώ είναι: Το view κάνει raise την exception <a class=\"reference internal\" href=\"/el/4.1/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a> αν η ερώτηση με το συγκεκριμένο ID δεν υπάρχει (στη βάση δεδομένων).</p>\n<p>Θα συζητήσουμε τι μπορείτε να βάλετε μέσα στο template με το όνομα <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/detail.html</span></code> λίγο αργότερα, αλλά τώρα αν βιάζεστε να δείτε πως θα φαίνεται γράψτε τα ακόλουθα στο αρχείο <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/detail.html</span></code>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates/polls/detail.html</span></code></figcaption>\n<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\">question</span> <span class=\"cp\">}}</span>\n</code></pre></figure>\n<p>Αυτό θα σας δώσει μια ιδέα.</p>\n<section id=\"a-shortcut-get-object-or-404\">\n<h3>Η συντόμευση: <a class=\"reference internal\" href=\"/el/4.1/topics/http/shortcuts/#django.shortcuts.get_object_or_404\" title=\"django.shortcuts.get_object_or_404\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">get_object_or_404()</span></code></a><a class=\"heading-anchor\" href=\"#a-shortcut-get-object-or-404\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Είναι συνηθισμένο να χρησιμοποιείται η μέθοδος <a class=\"reference internal\" href=\"/el/4.1/ref/models/querysets/#django.db.models.query.QuerySet.get\" title=\"django.db.models.query.QuerySet.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get()</span></code></a> η οποία να κάνει raise το exception <a class=\"reference internal\" href=\"/el/4.1/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a> αν το object δεν υπάρχει. Το Django σας παρέχει μια συντόμευση και γι’ αυτό. Παρακάτω φαίνεται το <code class=\"docutils literal notranslate\"><span class=\"pre\">detail()</span></code> view, γραμμένο από την αρχή (πάλι):</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.shortcuts</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">get_object_or_404</span><span class=\"p\">,</span> <span class=\"n\">render</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n<span class=\"c1\"># ...</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">detail</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">question_id</span><span class=\"p\">):</span>\n    <span class=\"n\">question</span> <span class=\"o\">=</span> <span class=\"n\">get_object_or_404</span><span class=\"p\">(</span><span class=\"n\">Question</span><span class=\"p\">,</span> <span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"n\">question_id</span><span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"s1\">&#39;polls/detail.html&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;question&#39;</span><span class=\"p\">:</span> <span class=\"n\">question</span><span class=\"p\">})</span>\n</code></pre></figure>\n<p>Η συνάρτηση <a class=\"reference internal\" href=\"/el/4.1/topics/http/shortcuts/#django.shortcuts.get_object_or_404\" title=\"django.shortcuts.get_object_or_404\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">get_object_or_404()</span></code></a> παίρνει ως πρώτο όρισμα ένα Django model και ένα αυθαίρετο αριθμό από arguments, τα οποία τα δίνει στην μέθοδο <a class=\"reference internal\" href=\"/el/4.1/ref/models/querysets/#django.db.models.query.QuerySet.get\" title=\"django.db.models.query.QuerySet.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get()</span></code></a> του manager του μοντέλου (model manager) που περάστηκε  ως πρώτο όρισμα. Η συνάρτηση αυτή κάνει raise το exception <a class=\"reference internal\" href=\"/el/4.1/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a> αν το object δεν υπάρχει.</p>\n<aside class=\"admonition-philosophy admonition\">\n<p class=\"admonition-title\">Φιλοσοφία</p>\n<p>Γιατί όμως χρησιμοποιούμε την βοηθητική συνάρτηση (helper function) <a class=\"reference internal\" href=\"/el/4.1/topics/http/shortcuts/#django.shortcuts.get_object_or_404\" title=\"django.shortcuts.get_object_or_404\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">get_object_or_404()</span></code></a> αντί να κάνουμε αυτόματα το catch του exception <a class=\"reference internal\" href=\"/el/4.1/ref/exceptions/#django.core.exceptions.ObjectDoesNotExist\" title=\"django.core.exceptions.ObjectDoesNotExist\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">ObjectDoesNotExist</span></code></a> σε ένα υψηλότερο επίπεδο; Επίσης, γιατί να βάλουμε το model API να κάνει raise το exception <a class=\"reference internal\" href=\"/el/4.1/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a> αντί του exception <a class=\"reference internal\" href=\"/el/4.1/ref/exceptions/#django.core.exceptions.ObjectDoesNotExist\" title=\"django.core.exceptions.ObjectDoesNotExist\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">ObjectDoesNotExist</span></code></a>;</p>\n<p>Η απάντηση είναι ίδια και στις δύο ερωτήσεις. Επειδή αυτό θα δεσμεύσει το επίπεδο του model με το επίπεδο του view. Ένας από τους πρωταρχικούς στόχους του Django είναι να διατηρηθεί η ανεξαρτητοποίηση και η μη σύνδεση μεταξύ οντοτήτων (το λεγόμενο loose coupling). Μερικά ελεγχόμενα couplings παρουσιάζονται στο module <a class=\"reference internal\" href=\"/el/4.1/topics/http/shortcuts/#module-django.shortcuts\" title=\"django.shortcuts: Convenience shortcuts that span multiple levels of Django's MVC stack.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.shortcuts</span></code></a>.</p>\n</aside>\n<p>Υπάρχει επίσης η συνάρτηση <a class=\"reference internal\" href=\"/el/4.1/topics/http/shortcuts/#django.shortcuts.get_list_or_404\" title=\"django.shortcuts.get_list_or_404\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">get_list_or_404()</span></code></a>, η οποία λειτουργεί πανομοιότυπα με την <a class=\"reference internal\" href=\"/el/4.1/topics/http/shortcuts/#django.shortcuts.get_object_or_404\" title=\"django.shortcuts.get_object_or_404\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">get_object_or_404()</span></code></a> – με τη μόνη διαφορά ότι χρησιμοποιεί την μέθοδο <a class=\"reference internal\" href=\"/el/4.1/ref/models/querysets/#django.db.models.query.QuerySet.filter\" title=\"django.db.models.query.QuerySet.filter\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">filter()</span></code></a> αντί της <a class=\"reference internal\" href=\"/el/4.1/ref/models/querysets/#django.db.models.query.QuerySet.get\" title=\"django.db.models.query.QuerySet.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get()</span></code></a>. Η <a class=\"reference internal\" href=\"/el/4.1/topics/http/shortcuts/#django.shortcuts.get_list_or_404\" title=\"django.shortcuts.get_list_or_404\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">get_list_or_404()</span></code></a> κάνει raise την exception <a class=\"reference internal\" href=\"/el/4.1/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a> αν η λίστα είναι κενή (άδεια).</p>\n</section>\n</section>\n<section id=\"use-the-template-system\">\n<h2>Χρησιμοποιώντας ένα template system<a class=\"heading-anchor\" href=\"#use-the-template-system\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Πίσω στο <code class=\"docutils literal notranslate\"><span class=\"pre\">detail()</span></code> view της εφαρμογής μας. Έχοντας το context variable με το όνομα <code class=\"docutils literal notranslate\"><span class=\"pre\">question</span></code>, το template <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/detail.html</span></code> θα δείχνει κάπως έτσι:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates/polls/detail.html</span></code></figcaption>\n<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\">h1</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">h1</span><span class=\"p\">&gt;</span>\n<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\">question.choice_set.all</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.choice_text</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></figure>\n<p>Το template system χρησιμοποιεί την σύνταξη της τελείας για να ψάχνει μέσα στα variable attributes. Στο παράδειγμα του <code class=\"docutils literal notranslate\"><span class=\"pre\">{{</span> <span class=\"pre\">question.question_text</span> <span class=\"pre\">}}</span></code>, το Django θα ψάξει πρώτα μέσα στο dictionary του object <code class=\"docutils literal notranslate\"><span class=\"pre\">question</span></code>. Αν δεν βρει τίποτα (δεν υπάρχει, δηλαδή, το key <code class=\"docutils literal notranslate\"><span class=\"pre\">question_text``στο</span> <span class=\"pre\">υποτιθέμενο</span> <span class=\"pre\">dictionary),</span> <span class=\"pre\">προσπαθεί</span> <span class=\"pre\">να</span> <span class=\"pre\">βρει</span> <span class=\"pre\">το</span> <span class=\"pre\">``question_text</span></code> σαν attribute του object – το οποίο στη συγκεκριμένη περίπτωση ισχύει. Αν όμως δεν υπήρχε, τότε θα έψαχνε σε μια λίστα να το βρει.</p>\n<p>Ο τρόπος για να καλείτε μεθόδους φαίνεται στο βρόγχο επανάληψης <a class=\"reference internal\" href=\"/el/4.1/ref/templates/builtins/#std-templatetag-for\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">for</span> <span class=\"pre\">%}</span></code></a>:  το <code class=\"docutils literal notranslate\"><span class=\"pre\">question.choice_set.all</span></code> μεταφράζεται ως Python κώδικας <code class=\"docutils literal notranslate\"><span class=\"pre\">question.choice_set.all()</span></code>, το οποίο επιστρέφει ένα iterable από <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code> objects και είναι βολικό προς χρήση (στην παρούσα) με τον βρόγχο επανάληψης <a class=\"reference internal\" href=\"/el/4.1/ref/templates/builtins/#std-templatetag-for\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">for</span> <span class=\"pre\">%}</span></code></a> (το οποίο αναφέρεται και ως <code class=\"docutils literal notranslate\"><span class=\"pre\">template</span> <span class=\"pre\">tag</span></code>).</p>\n<p>Δείτε το άρθρο <a class=\"reference internal\" href=\"/el/4.1/topics/templates/\"><span class=\"doc\">templates</span></a> για περισσότερα σχετικά με τα templates.</p>\n</section>\n<section id=\"removing-hardcoded-urls-in-templates\">\n<h2>Αφαίρεση των hardcoded URLs στα templates<a class=\"heading-anchor\" href=\"#removing-hardcoded-urls-in-templates\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Θυμηθείτε ότι πριν, δηλώσαμε στην HTML το link για την ερώτηση στο template <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/index.html</span></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=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;/polls/</span><span class=\"cp\">{{</span> <span class=\"nv\">question.id</span> <span class=\"cp\">}}</span><span class=\"s\">/&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>The problem with this hardcoded, tightly-coupled approach is that it becomes\nchallenging to change URLs on projects with a lot of templates. However, since\nyou defined the name argument in the <a class=\"reference internal\" href=\"/el/4.1/ref/urls/#django.urls.path\" title=\"django.urls.path\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">path()</span></code></a> functions in\nthe <code class=\"docutils literal notranslate\"><span class=\"pre\">polls.urls</span></code> module, you can remove a reliance on specific URL paths\ndefined in your url configurations by using the <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">url</span> <span class=\"pre\">%}</span></code> 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=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;&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=\"k\">url</span> <span class=\"s1\">&#39;detail&#39;</span> <span class=\"nv\">question.id</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Ο τρόπος με τον οποίο λειτουργεί αυτό το template tag είναι κοιτώντας τα URLs που έχετε ορίσει στο module <code class=\"docutils literal notranslate\"><span class=\"pre\">polls.urls</span></code>. Μπορείτε να δείτε ακριβώς σε ποιο URL έχει οριστεί το όνομα “detail” παρακάτω:</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=\"o\">...</span>\n<span class=\"c1\"># the &#39;name&#39; value as called by the {% url %} template tag</span>\n<span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;&lt;int:question_id&gt;/&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">detail</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;detail&#39;</span><span class=\"p\">),</span>\n<span class=\"o\">...</span>\n</code></pre></div>\n<p>Αν θέλετε να αλλάξετε το URL αυτού του view σε κάτι άλλο (ίσως στο <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/specifics/12/</span></code>), τότε αντί να ψάχνετε όλα τα templates που είχατε δηλώσει το παλιό URL προκειμένου να το αντικαταστήσετε με το καινούργιο, πολύ απλά πειράζετε ένα αρχείο (<code class=\"docutils literal notranslate\"><span class=\"pre\">polls/urls.py</span></code>) και όλα τα υπόλοιπα ανανεώνονται αυτόματα, χάρη στο template tag <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">url</span> <span class=\"pre\">%}</span></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=\"o\">...</span>\n<span class=\"c1\"># added the word &#39;specifics&#39;</span>\n<span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;specifics/&lt;int:question_id&gt;/&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">detail</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;detail&#39;</span><span class=\"p\">),</span>\n<span class=\"o\">...</span>\n</code></pre></div>\n</section>\n<section id=\"namespacing-url-names\">\n<h2>Χρησιμοποιώντας namespacing στα ονόματα των URL<a class=\"heading-anchor\" href=\"#namespacing-url-names\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Το project του οδηγού αυτού έχει μόνο μια εφαρμογή, την <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code>. Σε πραγματικά Django projects, ίσως να έχετε πέντε, δέκα, είκοσι ή περισσότερα apps. Πως μπορεί να ξέρει και να διαφοροποιεί το Django τα ονόματα των URLs ανάμεσα σε τόσα apps; Για παράδειγμα, η εφαρμογή <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> έχει ένα <code class=\"docutils literal notranslate\"><span class=\"pre\">detail</span></code> view και ίσως ένα άλλο app (στο ίδιο project) να έχει το ίδιο όνομα για ένα δικό του view. Όταν το Django συναντήσει το template tag <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">url</span> <span class=\"pre\">'detail'</span> <span class=\"pre\">%}</span></code> πως θα ξέρει σε ποιο view να αναφερθεί;</p>\n<p>Η απάντηση έρχεται με την προσθήκη namespaces στο URLconf. Στο αρχείο <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/urls.py</span></code>, προσθέστε μια μεταβλητή <code class=\"docutils literal notranslate\"><span class=\"pre\">app_name</span></code> ούτως ώστε να θέσετε το namespace για αυτό το app:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/urls.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">path</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">views</span>\n\n<span class=\"n\">app_name</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;polls&#39;</span>\n<span class=\"n\">urlpatterns</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">index</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;index&#39;</span><span class=\"p\">),</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;&lt;int:question_id&gt;/&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">detail</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;detail&#39;</span><span class=\"p\">),</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;&lt;int:question_id&gt;/results/&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">results</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;results&#39;</span><span class=\"p\">),</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;&lt;int:question_id&gt;/vote/&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">vote</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;vote&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>Τώρα, πηγαίνετε και αλλάξτε το αρχείο <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>polls/index.html``από:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates/polls/index.html</span></code></figcaption>\n<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\">li</span><span class=\"p\">&gt;&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=\"k\">url</span> <span class=\"s1\">&#39;detail&#39;</span> <span class=\"nv\">question.id</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n</code></pre></figure>\n<p>στο:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates/polls/index.html</span></code></figcaption>\n<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\">li</span><span class=\"p\">&gt;&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=\"k\">url</span> <span class=\"s1\">&#39;polls:detail&#39;</span> <span class=\"nv\">question.id</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n</code></pre></figure>\n<p>When you’re comfortable with writing views, read <a class=\"reference internal\" href=\"/el/4.1/intro/tutorial04/\"><span class=\"doc\">part 4 of this tutorial</span></a> to learn the basics about form processing and generic\nviews.</p>\n</section>","rootId":"writing-your-first-django-app-part-3","toc":[{"title":"Επισκόπηση","anchor":"overview","children":[]},{"title":"Γράφοντας περισσότερα views","anchor":"writing-more-views","children":[]},{"title":"Γράφοντας views οι οποίες κάνουν κάτι","anchor":"write-views-that-actually-do-something","children":[{"title":"Η συντόμευση: render()","anchor":"a-shortcut-render","children":[]}]},{"title":"Raising σφάλμα 404","anchor":"raising-a-404-error","children":[{"title":"Η συντόμευση: get_object_or_404()","anchor":"a-shortcut-get-object-or-404","children":[]}]},{"title":"Χρησιμοποιώντας ένα template system","anchor":"use-the-template-system","children":[]},{"title":"Αφαίρεση των hardcoded URLs στα templates","anchor":"removing-hardcoded-urls-in-templates","children":[]},{"title":"Χρησιμοποιώντας namespacing στα ονόματα των URL","anchor":"namespacing-url-names","children":[]}],"breadcrumbs":[{"docname":"intro/index","title":"Ξεκινώντας","url":"/el/4.1/intro/"}],"prev":{"docname":"intro/tutorial02","title":"Γράφοντας το πρώτο σας Django app, μέρος 2","url":"/el/4.1/intro/tutorial02/"},"next":{"docname":"intro/tutorial04","title":"Γράφοντας το πρώτο σας Django app, μέρος 4","url":"/el/4.1/intro/tutorial04/"},"formats":{"html":"/el/4.1/intro/tutorial03/","markdown":"/el/4.1/intro/tutorial03.md","json":"/el/4.1/intro/tutorial03.json"},"source":"https://github.com/django/django/blob/stable/4.1.x/docs/intro/tutorial03.txt","official":"https://docs.djangoproject.com/el/4.1/intro/tutorial03/","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","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}