{"title":"Skriva din första Django-app, del 4","version":"5.2","locale":"sv","docname":"intro/tutorial04","url":"/sv/5.2/intro/tutorial04/","canonical":"https://djangodocs.dev/sv/5.2/intro/tutorial04/","summary":"Denna handledning börjar där Tutorial 3 slutade. Vi fortsätter med web-poll applikationen och kommer att fokusera på formulärbehandling och att minska vår kod. Var…","html":"<h1>Skriva din första Django-app, del 4<a class=\"heading-anchor\" href=\"#writing-your-first-django-app-part-4\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Denna handledning börjar där <a class=\"reference internal\" href=\"/sv/5.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a> slutade. Vi fortsätter med web-poll applikationen och kommer att fokusera på formulärbehandling och att minska vår kod.</p>\n<aside class=\"admonition-where-to-get-help admonition\">\n<p class=\"admonition-title\">Var du kan få hjälp:</p>\n<p>Om du har problem med att gå igenom den här handledningen kan du gå till avsnittet <a class=\"reference internal\" href=\"/sv/5.2/faq/help/\"><span class=\"doc\">Att få hjälp</span></a> i FAQ.</p>\n</aside>\n<section id=\"write-a-minimal-form\">\n<h2>Skriv ett minimalt formulär<a class=\"heading-anchor\" href=\"#write-a-minimal-form\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Låt oss uppdatera vår mall för detaljer om omröstningen (”polls/detail.html”) från den senaste handledningen, så att mallen innehåller ett HTML-element <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;form&gt;</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\">form</span> <span class=\"na\">action</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;polls:vote&#39;</span> <span class=\"nv\">question.id</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span> <span class=\"na\">method</span><span class=\"o\">=</span><span class=\"s\">&quot;post&quot;</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">csrf_token</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">fieldset</span><span class=\"p\">&gt;</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">legend</span><span class=\"p\">&gt;&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;&lt;/</span><span class=\"nt\">legend</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">error_message</span> <span class=\"cp\">%}</span><span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">strong</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">error_message</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">strong</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span><span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</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\">input</span> <span class=\"na\">type</span><span class=\"o\">=</span><span class=\"s\">&quot;radio&quot;</span> <span class=\"na\">name</span><span class=\"o\">=</span><span class=\"s\">&quot;choice&quot;</span> <span class=\"na\">id</span><span class=\"o\">=</span><span class=\"s\">&quot;choice</span><span class=\"cp\">{{</span> <span class=\"nb\">forloop</span><span class=\"nv\">.counter</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span> <span class=\"na\">value</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{{</span> <span class=\"nv\">choice.id</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">label</span> <span class=\"na\">for</span><span class=\"o\">=</span><span class=\"s\">&quot;choice</span><span class=\"cp\">{{</span> <span class=\"nb\">forloop</span><span class=\"nv\">.counter</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</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\">label</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">br</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\">fieldset</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">input</span> <span class=\"na\">type</span><span class=\"o\">=</span><span class=\"s\">&quot;submit&quot;</span> <span class=\"na\">value</span><span class=\"o\">=</span><span class=\"s\">&quot;Vote&quot;</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">form</span><span class=\"p\">&gt;</span>\n</code></pre></figure>\n<p>En snabb genomgång:</p>\n<ul class=\"simple\">\n<li><p>Ovanstående mall visar en alternativknapp för varje frågealternativ. Varje alternativknapps <code class=\"docutils literal notranslate\"><span class=\"pre\">värde</span></code> är det associerade frågevalets ID. Namnet på varje alternativknapp är ”val”. Det betyder att när någon väljer en av alternativknapparna och skickar in formuläret, skickar den POST-data <code class=\"docutils literal notranslate\"><span class=\"pre\">choice=#</span></code> där # är ID för det valda valet. Detta är det grundläggande konceptet för HTML-formulär.</p></li>\n<li><p>Vi ställer in formulärets <code class=\"docutils literal notranslate\"><span class=\"pre\">action</span></code> till <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">url</span> <span class=\"pre\">'polls:vote'</span> <span class=\"pre\">question.id</span> <span class=\"pre\">%}</span></code>, och vi ställer in <code class=\"docutils literal notranslate\"><span class=\"pre\">method=&quot;post&quot;</span></code>. Att använda <code class=\"docutils literal notranslate\"><span class=\"pre\">method=&quot;post&quot;</span></code> (i motsats till <code class=\"docutils literal notranslate\"><span class=\"pre\">method=&quot;get&quot;</span></code>) är mycket viktigt, eftersom handlingen att skicka in detta formulär kommer att ändra data på serversidan. När du skapar ett formulär som ändrar data på serversidan, använd <code class=\"docutils literal notranslate\"><span class=\"pre\">method=&quot;post&quot;</span></code>. Detta tips är inte specifikt för Django; det är bra webbutvecklingspraxis i allmänhet.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">forloop.counter</span></code> anger hur många gånger <a class=\"reference internal\" href=\"/sv/5.2/ref/templates/builtins/#std-templatetag-for\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">for</span></code></a>-taggen har gått igenom sin loop</p></li>\n<li><p>Eftersom vi skapar ett POST-formulär (som kan ha effekten av att ändra data) måste vi oroa oss för Cross Site Request Forgeries. Tack och lov behöver du inte oroa dig för hårt, eftersom Django kommer med ett användbart system för att skydda mot det. Kort sagt, alla POST-formulär som är inriktade på interna webbadresser bör använda <a class=\"reference internal\" href=\"/sv/5.2/ref/templates/builtins/#std-templatetag-csrf_token\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">csrf_token</span> <span class=\"pre\">%}</span></code></a> malltagg.</p></li>\n</ul>\n<p>Låt oss nu skapa en Django-vy som hanterar de inskickade uppgifterna och gör något med dem. Kom ihåg att vi i <a class=\"reference internal\" href=\"/sv/5.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a> skapade en URLconf för polls-programmet som innehåller den här raden:</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=\"n\">path</span><span class=\"p\">(</span><span class=\"s2\">&quot;&lt;int:question_id&gt;/vote/&quot;</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=\"s2\">&quot;vote&quot;</span><span class=\"p\">),</span>\n</code></pre></figure>\n<p>Vi skapade också en dummyimplementering av funktionen <code class=\"docutils literal notranslate\"><span class=\"pre\">vote()</span></code>. Låt oss skapa en riktig version. Lägg till följande i <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code>:</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.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">F</span>\n<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><span class=\"p\">,</span> <span class=\"n\">HttpResponseRedirect</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\">get_object_or_404</span><span class=\"p\">,</span> <span class=\"n\">render</span>\n<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\">reverse</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\">Choice</span><span class=\"p\">,</span> <span class=\"n\">Question</span>\n\n\n<span class=\"c1\"># ...</span>\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=\"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\">try</span><span class=\"p\">:</span>\n        <span class=\"n\">selected_choice</span> <span class=\"o\">=</span> <span class=\"n\">question</span><span class=\"o\">.</span><span class=\"n\">choice_set</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\">request</span><span class=\"o\">.</span><span class=\"n\">POST</span><span class=\"p\">[</span><span class=\"s2\">&quot;choice&quot;</span><span class=\"p\">])</span>\n    <span class=\"k\">except</span> <span class=\"p\">(</span><span class=\"ne\">KeyError</span><span class=\"p\">,</span> <span class=\"n\">Choice</span><span class=\"o\">.</span><span class=\"n\">DoesNotExist</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Redisplay the question voting form.</span>\n        <span class=\"k\">return</span> <span class=\"n\">render</span><span class=\"p\">(</span>\n            <span class=\"n\">request</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;polls/detail.html&quot;</span><span class=\"p\">,</span>\n            <span class=\"p\">{</span>\n                <span class=\"s2\">&quot;question&quot;</span><span class=\"p\">:</span> <span class=\"n\">question</span><span class=\"p\">,</span>\n                <span class=\"s2\">&quot;error_message&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;You didn&#39;t select a choice.&quot;</span><span class=\"p\">,</span>\n            <span class=\"p\">},</span>\n        <span class=\"p\">)</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        <span class=\"n\">selected_choice</span><span class=\"o\">.</span><span class=\"n\">votes</span> <span class=\"o\">=</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;votes&quot;</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"mi\">1</span>\n        <span class=\"n\">selected_choice</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n        <span class=\"c1\"># Always return an HttpResponseRedirect after successfully dealing</span>\n        <span class=\"c1\"># with POST data. This prevents data from being posted twice if a</span>\n        <span class=\"c1\"># user hits the Back button.</span>\n        <span class=\"k\">return</span> <span class=\"n\">HttpResponseRedirect</span><span class=\"p\">(</span><span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s2\">&quot;polls:results&quot;</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"o\">=</span><span class=\"p\">(</span><span class=\"n\">question</span><span class=\"o\">.</span><span class=\"n\">id</span><span class=\"p\">,)))</span>\n</code></pre></figure>\n<p>Den här koden innehåller några saker som vi ännu inte har gått igenom i den här handledningen:</p>\n<ul>\n<li><p><a class=\"reference internal\" href=\"/sv/5.2/ref/request-response/#django.http.HttpRequest.POST\" title=\"django.http.HttpRequest.POST\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">request.POST</span></code></a> är ett ordboksliknande objekt som låter dig komma åt inskickade data med nyckelnamn. I det här fallet returnerar <code class=\"docutils literal notranslate\"><span class=\"pre\">request.POST['choice']</span></code> ID:t för det valda valet som en sträng. <a class=\"reference internal\" href=\"/sv/5.2/ref/request-response/#django.http.HttpRequest.POST\" title=\"django.http.HttpRequest.POST\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">request.POST</span></code></a>-värden är alltid strängar.</p>\n<p>Observera att Django också tillhandahåller <a class=\"reference internal\" href=\"/sv/5.2/ref/request-response/#django.http.HttpRequest.GET\" title=\"django.http.HttpRequest.GET\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">request.GET</span></code></a> för åtkomst till GET-data på samma sätt - men vi använder uttryckligen <a class=\"reference internal\" href=\"/sv/5.2/ref/request-response/#django.http.HttpRequest.POST\" title=\"django.http.HttpRequest.POST\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">request.POST</span></code></a> i vår kod för att säkerställa att data endast ändras via ett POST-anrop.</p>\n</li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">request.POST['choice']</span></code> kommer att ge upphov till <a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#KeyError\" title=\"(in Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">KeyError</span></code></a> om <code class=\"docutils literal notranslate\"><span class=\"pre\">choice</span></code> inte angavs i POST-data. Ovanstående kod kontrollerar för <a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#KeyError\" title=\"(in Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">KeyError</span></code></a> och visar frågeformuläret på nytt med ett felmeddelande om <code class=\"docutils literal notranslate\"><span class=\"pre\">choice</span></code> inte har angetts.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">F(&quot;votes&quot;)</span> <span class=\"pre\">+</span> <span class=\"pre\">1</span></code> <a class=\"reference internal\" href=\"/sv/5.2/ref/models/expressions/#avoiding-race-conditions-using-f\"><span class=\"std std-ref\">instruerar databasen</span></a> att öka antalet röster med 1.</p></li>\n<li><p>Efter att ha ökat antalet val returnerar koden en <a class=\"reference internal\" href=\"/sv/5.2/ref/request-response/#django.http.HttpResponseRedirect\" title=\"django.http.HttpResponseRedirect\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponseRedirect</span></code></a> snarare än en vanlig <a class=\"reference internal\" href=\"/sv/5.2/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>. <a class=\"reference internal\" href=\"/sv/5.2/ref/request-response/#django.http.HttpResponseRedirect\" title=\"django.http.HttpResponseRedirect\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponseRedirect</span></code></a> tar ett enda argument: URL:en till vilken användaren kommer att omdirigeras (se följande punkt för hur vi konstruerar URL:en i det här fallet).</p>\n<p>Som Python-kommentaren ovan påpekar bör du alltid returnera en <a class=\"reference internal\" href=\"/sv/5.2/ref/request-response/#django.http.HttpResponseRedirect\" title=\"django.http.HttpResponseRedirect\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponseRedirect</span></code></a> efter framgångsrik hantering av POST-data. Det här tipset är inte specifikt för Django; det är god praxis för webbutveckling i allmänhet.</p>\n</li>\n<li><p>Vi använder funktionen <a class=\"reference internal\" href=\"/sv/5.2/ref/urlresolvers/#django.urls.reverse\" title=\"django.urls.reverse\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">reverse()</span></code></a> i konstruktören <a class=\"reference internal\" href=\"/sv/5.2/ref/request-response/#django.http.HttpResponseRedirect\" title=\"django.http.HttpResponseRedirect\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponseRedirect</span></code></a> i det här exemplet. Denna funktion hjälper till att undvika att behöva hårdkoda en URL i vyfunktionen. Den får namnet på den vy som vi vill skicka kontroll till och den variabla delen av URL-mönstret som pekar på den vyn. I det här fallet, med hjälp av URLconf som vi ställde in i <a class=\"reference internal\" href=\"/sv/5.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>, kommer detta <a class=\"reference internal\" href=\"/sv/5.2/ref/urlresolvers/#django.urls.reverse\" title=\"django.urls.reverse\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">reverse()</span></code></a>-anrop att returnera en sträng som</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=\"s2\">&quot;/polls/3/results/&quot;</span>\n</code></pre></div>\n<p>där <code class=\"docutils literal notranslate\"><span class=\"pre\">3</span></code> är värdet av <code class=\"docutils literal notranslate\"><span class=\"pre\">question.id</span></code>. Denna omdirigerade URL kommer sedan att anropa vyn <code class=\"docutils literal notranslate\"><span class=\"pre\">'results</span></code> för att visa den slutliga sidan.</p>\n</li>\n</ul>\n<p>Som nämnts i <a class=\"reference internal\" href=\"/sv/5.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a> är <code class=\"docutils literal notranslate\"><span class=\"pre\">request</span></code> ett <a class=\"reference internal\" href=\"/sv/5.2/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpRequest</span></code></a>-objekt. För mer information om <a class=\"reference internal\" href=\"/sv/5.2/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpRequest</span></code></a>-objekt, se <a class=\"reference internal\" href=\"/sv/5.2/ref/request-response/\"><span class=\"doc\">dokumentation om begäran och svar</span></a>.</p>\n<p>När någon har röstat på en fråga omdirigeras vyn <code class=\"docutils literal notranslate\"><span class=\"pre\">vote()</span></code> till resultatsidan för frågan. Låt oss skriva den vyn:</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\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\">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=\"s2\">&quot;polls/results.html&quot;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s2\">&quot;question&quot;</span><span class=\"p\">:</span> <span class=\"n\">question</span><span class=\"p\">})</span>\n</code></pre></figure>\n<p>Detta är nästan exakt samma sak som vyn <code class=\"docutils literal notranslate\"><span class=\"pre\">detail()</span></code> från <a class=\"reference internal\" href=\"/sv/5.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>. Den enda skillnaden är mallnamnet. Vi kommer att åtgärda denna redundans senare.</p>\n<p>Skapa nu mallen <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/results.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/results.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\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=\"cp\">{{</span> <span class=\"nv\">choice.votes</span> <span class=\"cp\">}}</span> vote<span class=\"cp\">{{</span> <span class=\"nv\">choice.votes</span><span class=\"o\">|</span><span class=\"nf\">pluralize</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\n<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=\"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>Vote again?<span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>\n</code></pre></figure>\n<p>Gå nu till <code class=\"docutils literal notranslate\"><span class=\"pre\">/polls/1/</span></code> i din webbläsare och rösta på frågan. Du bör se en resultatsida som uppdateras varje gång du röstar. Om du skickar in formuläret utan att ha gjort något val bör du se ett felmeddelande.</p>\n</section>\n<section id=\"use-generic-views-less-code-is-better\">\n<h2>Använd generiska vyer: Mindre kod är bättre<a class=\"heading-anchor\" href=\"#use-generic-views-less-code-is-better\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Vyerna <code class=\"docutils literal notranslate\"><span class=\"pre\">detail()</span></code> (från <a class=\"reference internal\" href=\"/sv/5.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>) och <code class=\"docutils literal notranslate\"><span class=\"pre\">results()</span></code> är mycket korta - och, som nämnts ovan, överflödiga. Vyn <code class=\"docutils literal notranslate\"><span class=\"pre\">index()</span></code>, som visar en lista med omröstningar, är liknande.</p>\n<p>Dessa vyer representerar ett vanligt fall av grundläggande webbutveckling: hämta data från databasen enligt en parameter som skickas i webbadressen, ladda en mall och returnera den renderade mallen. Eftersom detta är så vanligt tillhandahåller Django en genväg, kallad ”generic views” -systemet.</p>\n<p>Generiska vyer abstraherar vanliga mönster till den punkt där du inte ens behöver skriva Python-kod för att skriva en app. Till exempel abstraherar de generiska vyerna <a class=\"reference internal\" href=\"/sv/5.2/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> och <a class=\"reference internal\" href=\"/sv/5.2/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> begreppen ”visa en lista med objekt” respektive ”visa en detaljsida för en viss typ av objekt”.</p>\n<p>Låt oss konvertera vår poll-app till att använda det generiska vy-systemet, så att vi kan ta bort en hel del av vår egen kod. Vi måste ta några steg för att göra konverteringen. Vi kommer att göra det:</p>\n<ol class=\"arabic simple\">\n<li><p>Konvertera URLconf.</p></li>\n<li><p>Ta bort några av de gamla, onödiga vyerna.</p></li>\n<li><p>Introducera nya vyer baserade på Djangos generiska vyer.</p></li>\n</ol>\n<p>Läs vidare för mer information.</p>\n<aside class=\"admonition-why-the-code-shuffle admonition\">\n<p class=\"admonition-title\">Varför kodomläggningen?</p>\n<p>När du skriver en Django-app utvärderar du i allmänhet om generiska vyer passar bra för ditt problem, och du använder dem från början, snarare än att refaktorisera din kod halvvägs igenom. Men denna handledning har avsiktligt fokuserat på att skriva vyerna ”på det hårda sättet” fram till nu, för att fokusera på kärnkoncept.</p>\n<p>Du bör kunna grundläggande matematik innan du börjar använda en miniräknare.</p>\n</aside>\n<section id=\"amend-urlconf\">\n<h3>Ändra URLconf<a class=\"heading-anchor\" href=\"#amend-urlconf\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Först öppnar du URLconf i <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/urls.py</span></code> och ändrar den så här:</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=\"s2\">&quot;polls&quot;</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=\"s2\">&quot;&quot;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">IndexView</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">(),</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;index&quot;</span><span class=\"p\">),</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s2\">&quot;&lt;int:pk&gt;/&quot;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">DetailView</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">(),</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;detail&quot;</span><span class=\"p\">),</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s2\">&quot;&lt;int:pk&gt;/results/&quot;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">ResultsView</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">(),</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;results&quot;</span><span class=\"p\">),</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s2\">&quot;&lt;int:question_id&gt;/vote/&quot;</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=\"s2\">&quot;vote&quot;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>Observera att namnet på det matchade mönstret i söksträngarna för det andra och tredje mönstret har ändrats från <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;question_id&gt;</span></code> till <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;pk&gt;</span></code>. Detta är nödvändigt eftersom vi kommer att använda den generiska vyn <a class=\"reference internal\" href=\"/sv/5.2/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> för att ersätta våra vyer <code class=\"docutils literal notranslate\"><span class=\"pre\">detail()</span></code> och <code class=\"docutils literal notranslate\"><span class=\"pre\">results()</span></code>, och den förväntar sig att det primära nyckelvärdet som fångas från URL:en ska heta <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;pk&quot;</span></code>.</p>\n</section>\n<section id=\"amend-views\">\n<h3>Ändra synpunkter<a class=\"heading-anchor\" href=\"#amend-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Därefter ska vi ta bort våra gamla vyer <code class=\"docutils literal notranslate\"><span class=\"pre\">index</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">detail</span></code> och <code class=\"docutils literal notranslate\"><span class=\"pre\">results</span></code> och använda Djangos generiska vyer istället. För att göra det, öppna filen <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code> och ändra den så här:</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.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">F</span>\n<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\">HttpResponseRedirect</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\">get_object_or_404</span><span class=\"p\">,</span> <span class=\"n\">render</span>\n<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\">reverse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">generic</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\">Choice</span><span class=\"p\">,</span> <span class=\"n\">Question</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">IndexView</span><span class=\"p\">(</span><span class=\"n\">generic</span><span class=\"o\">.</span><span class=\"n\">ListView</span><span class=\"p\">):</span>\n    <span class=\"n\">template_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;polls/index.html&quot;</span>\n    <span class=\"n\">context_object_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;latest_question_list&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_queryset</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;Return the last five published questions.&quot;&quot;&quot;</span>\n        <span class=\"k\">return</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=\"s2\">&quot;-pub_date&quot;</span><span class=\"p\">)[:</span><span class=\"mi\">5</span><span class=\"p\">]</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">DetailView</span><span class=\"p\">(</span><span class=\"n\">generic</span><span class=\"o\">.</span><span class=\"n\">DetailView</span><span class=\"p\">):</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Question</span>\n    <span class=\"n\">template_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;polls/detail.html&quot;</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">ResultsView</span><span class=\"p\">(</span><span class=\"n\">generic</span><span class=\"o\">.</span><span class=\"n\">DetailView</span><span class=\"p\">):</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Question</span>\n    <span class=\"n\">template_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;polls/results.html&quot;</span>\n\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=\"c1\"># same as above, no changes needed.</span>\n    <span class=\"o\">...</span>\n</code></pre></figure>\n<p>Varje generisk vy måste veta vilken modell den ska agera utifrån. Detta tillhandahålls antingen med attributet <code class=\"docutils literal notranslate\"><span class=\"pre\">model</span></code> (i detta exempel <code class=\"docutils literal notranslate\"><span class=\"pre\">model</span> <span class=\"pre\">=</span> <span class=\"pre\">Question</span></code> för <code class=\"docutils literal notranslate\"><span class=\"pre\">DetailView</span></code> och <code class=\"docutils literal notranslate\"><span class=\"pre\">ResultsView</span></code>) eller genom att definiera metoden <a class=\"reference internal\" href=\"/sv/5.2/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.get_queryset\" title=\"django.views.generic.list.MultipleObjectMixin.get_queryset\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code></a> (som visas i <code class=\"docutils literal notranslate\"><span class=\"pre\">IndexView</span></code>).</p>\n<p>Som standard använder den generiska vyn <a class=\"reference internal\" href=\"/sv/5.2/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> en mall som heter <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;app</span> <span class=\"pre\">name&gt;/&lt;model</span> <span class=\"pre\">name&gt;_detail.html</span></code>. I vårt fall skulle den använda mallen <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;polls/question_detail.html&quot;</span></code>. Attributet <code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> används för att tala om för Django att använda ett specifikt mallnamn istället för det autogenererade standardmallnamnet. Vi anger också <code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> för listvyn <code class=\"docutils literal notranslate\"><span class=\"pre\">results</span></code> - detta säkerställer att resultatvyn och detaljvyn har ett annat utseende när de renderas, även om de båda är en <a class=\"reference internal\" href=\"/sv/5.2/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> bakom kulisserna.</p>\n<p>På samma sätt använder den generiska vyn <a class=\"reference internal\" href=\"/sv/5.2/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> en standardmall som heter <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;app</span> <span class=\"pre\">name&gt;/&lt;model</span> <span class=\"pre\">name&gt;_list.html</span></code>; vi använder <code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> för att tala om för <a class=\"reference internal\" href=\"/sv/5.2/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> att använda vår befintliga mall <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;polls/index.html&quot;</span></code>.</p>\n<p>I tidigare delar av handledningen har mallarna försetts med en kontext som innehåller kontextvariablerna <code class=\"docutils literal notranslate\"><span class=\"pre\">question</span></code> och <code class=\"docutils literal notranslate\"><span class=\"pre\">latest_question_list</span></code>. För <code class=\"docutils literal notranslate\"><span class=\"pre\">DetailView</span></code> tillhandahålls <code class=\"docutils literal notranslate\"><span class=\"pre\">question</span></code>-variabeln automatiskt - eftersom vi använder en Django-modell (<code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code>) kan Django bestämma ett lämpligt namn för kontextvariabeln. För ListView är dock den automatiskt genererade kontextvariabeln <code class=\"docutils literal notranslate\"><span class=\"pre\">question_list</span></code>. För att åsidosätta detta tillhandahåller vi attributet <code class=\"docutils literal notranslate\"><span class=\"pre\">context_object_name</span></code>, som anger att vi vill använda <code class=\"docutils literal notranslate\"><span class=\"pre\">latest_question_list</span></code> istället. Som ett alternativt tillvägagångssätt kan du ändra dina mallar för att matcha de nya standardkontextvariablerna - men det är mycket lättare att berätta för Django att använda den variabel du vill ha.</p>\n<p>Kör servern och använd din nya polling-app baserad på generiska vyer.</p>\n<p>För fullständig information om generiska vyer, se <a class=\"reference internal\" href=\"/sv/5.2/topics/class-based-views/\"><span class=\"doc\">dokumentation om generiska vyer</span></a>.</p>\n<p>När du känner dig bekväm med formulär och generiska vyer kan du läsa <a class=\"reference internal\" href=\"/sv/5.2/intro/tutorial05/\"><span class=\"doc\">del 5 av denna handledning</span></a> för att lära dig hur du testar vår polls app.</p>\n</section>\n</section>","rootId":"writing-your-first-django-app-part-4","toc":[{"title":"Skriv ett minimalt formulär","anchor":"write-a-minimal-form","children":[]},{"title":"Använd generiska vyer: Mindre kod är bättre","anchor":"use-generic-views-less-code-is-better","children":[{"title":"Ändra URLconf","anchor":"amend-urlconf","children":[]},{"title":"Ändra synpunkter","anchor":"amend-views","children":[]}]}],"breadcrumbs":[{"docname":"intro/index","title":"Kom igång","url":"/sv/5.2/intro/"}],"prev":{"docname":"intro/tutorial03","title":"Skriva din första Django-app, del 3","url":"/sv/5.2/intro/tutorial03/"},"next":{"docname":"intro/tutorial05","title":"Skriva din första Django-app, del 5","url":"/sv/5.2/intro/tutorial05/"},"formats":{"html":"/sv/5.2/intro/tutorial04/","markdown":"/sv/5.2/intro/tutorial04.md","json":"/sv/5.2/intro/tutorial04.json"},"source":"https://github.com/django/django/blob/stable/5.2.x/docs/intro/tutorial04.txt","official":"https://docs.djangoproject.com/sv/5.2/intro/tutorial04/","inVersions":["6.1","6.0","5.2"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}