{"title":"Menulis aplikasi Django pertama anda, bagian 4","version":"4.2","locale":"id","docname":"intro/tutorial04","url":"/id/4.2/intro/tutorial04/","canonical":"https://djangodocs.dev/id/4.2/intro/tutorial04/","summary":"Tutorial ini memulai dimana Tutorial 3 ditinggalkan. Kami sedang melanjutkan aplikasi poling jaringan dan akan fokus pada pengolahan formulit dan memotong…","html":"<h1>Menulis aplikasi Django pertama anda, bagian 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>Tutorial ini memulai dimana <a class=\"reference internal\" href=\"/id/4.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a> ditinggalkan. Kami sedang melanjutkan aplikasi poling jaringan dan akan fokus pada pengolahan formulit dan memotong kode kami.</p>\n<aside class=\"admonition-where-to-get-help admonition\" role=\"note\">\n<p class=\"admonition-title\">Dimana mendapatkan bantuan:</p>\n<p>Jika anda memiliki masalah melalui tutorial ini, harap geser ke <a class=\"reference internal\" href=\"/id/4.2/faq/help/\"><span class=\"doc\">Getting Help</span></a> bagian dari FAQ.</p>\n</aside>\n<section id=\"write-a-minimal-form\">\n<h2>Tulis sebuah formulir minimal<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>Mari kita memperbaharui cetakan rincian jejak pendapat (&quot;polls/detail.html&quot;) dari tutorial terakhir, sehingga cetakan mengandung sebuah unsur <code class=\"docutils literal notranslate\">&lt;form&gt;</code> HTML:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/templates/polls/detail.html</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>Laporan cepat :</p>\n<ul class=\"simple\">\n<li><p>Cetakan diatas menampilkan tombol radio untuk setiap pilihan pertanyaan. <code class=\"docutils literal notranslate\">nilai</code> dari setiap tombol adalah ID pilihan pertanyaan dikaitkan. <code class=\"docutils literal notranslate\">name</code> dari setiap tombol radio adalah <code class=\"docutils literal notranslate\">&quot;pilihan&quot;</code>. itu berarti, ketika seseorang memilih satu dari tombol radio dan mengajukan formulir, itu akan mengirim data POST <code class=\"docutils literal notranslate\">choice=#</code> dimana # adalah ID dari pilihan terpilih. Ini adalah konsep dasar dari formulir HTML.</p></li>\n<li><p>Kami mensetel <code class=\"docutils literal notranslate\">action</code> formulir menjadi <code class=\"docutils literal notranslate\">{% url 'polls:vote' question.id %}</code>, dan kami mensetel <code class=\"docutils literal notranslate\">method=&quot;post&quot;</code>. Menggunakan <code class=\"docutils literal notranslate\">method=&quot;post&quot;</code> (sebagai lawan <code class=\"docutils literal notranslate\">method=&quot;get&quot;</code>) adalah sangat penting, karena tindakan mengajukan formulir ini akan merubah data sisi-peladen. Kapanpun anda membuat sebuah formulir yang merubah data sisi-peladen, gunakan <code class=\"docutils literal notranslate\">method=&quot;post&quot;</code>. Saran ini tidak khusus pada Django; itu adalah praktik pengembangan jaringan baik secara umum.</p></li>\n<li><p><code class=\"docutils literal notranslate\">forloop.counter</code> mengindikasikan seberapa kali the <code class=\"xref std std-ttag docutils literal notranslate\">untuk</code> etiket telah melalui putarannya</p></li>\n<li><p>Sejak kami membuat formulir POST (yang dapat memiliki pengaruh dari merubah data), kami perlu khawatir mengenai Cross Site Request Forgeries. Untungnya, anda tidak perlu khawatir terlalu keras, karena Django datang dengan sistem sangat membantu untuk perlindungan terhadapnya. Pendeknya, semua formulir POST yang menyasarkan pada URL dalam harus menggunakan etiket cetakan <a class=\"reference internal\" href=\"/id/4.2/ref/templates/builtins/#std-templatetag-csrf_token\"><code class=\"xref std std-ttag docutils literal notranslate\">{% csrf_token %}</code></a>.</p></li>\n</ul>\n<p>Sekarang, mari kita membuat tampilan Django yang menangani data diajukan dan melakukan sesuatu dengannya. Ingat, di <a class=\"reference internal\" href=\"/id/4.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>, kami membuat URLconf untuk aplikasi jejak pendapat yang menyertakan baris ini:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/urls.py</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>path<span class=\"p\">(</span><span class=\"s2\">&quot;&lt;int:question_id&gt;/vote/&quot;</span><span class=\"p\">,</span> views<span class=\"o\">.</span>vote<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;vote&quot;</span><span class=\"p\">),</span>\n</code></pre></figure>\n<p>Kami juga membuat penerapan tiruan dari fungsi <code class=\"docutils literal notranslate\">vote()</code>. mari kita membuat versi sebenarnya. Tambah berikut ke <code class=\"docutils literal notranslate\">polls/views.py</code>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/views.py</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=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse<span class=\"p\">,</span> HttpResponseRedirect\n<span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> get_object_or_404<span class=\"p\">,</span> render\n<span class=\"kn\">from</span> <span class=\"nn\">django.urls</span> <span class=\"kn\">import</span> reverse\n\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> Choice<span class=\"p\">,</span> Question\n\n\n<span class=\"c1\"># ...</span>\n<span class=\"k\">def</span> <span class=\"nf\">vote</span><span class=\"p\">(</span>request<span class=\"p\">,</span> question_id<span class=\"p\">):</span>\n    question <span class=\"o\">=</span> get_object_or_404<span class=\"p\">(</span>Question<span class=\"p\">,</span> pk<span class=\"o\">=</span>question_id<span class=\"p\">)</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        selected_choice <span class=\"o\">=</span> question<span class=\"o\">.</span>choice_set<span class=\"o\">.</span>get<span class=\"p\">(</span>pk<span class=\"o\">=</span>request<span class=\"o\">.</span>POST<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> Choice<span class=\"o\">.</span>DoesNotExist<span class=\"p\">):</span>\n        <span class=\"c1\"># Redisplay the question voting form.</span>\n        <span class=\"k\">return</span> render<span class=\"p\">(</span>\n            request<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> question<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        selected_choice<span class=\"o\">.</span>votes <span class=\"o\">+=</span> <span class=\"mi\">1</span>\n        selected_choice<span class=\"o\">.</span>save<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> HttpResponseRedirect<span class=\"p\">(</span>reverse<span class=\"p\">(</span><span class=\"s2\">&quot;polls:results&quot;</span><span class=\"p\">,</span> args<span class=\"o\">=</span><span class=\"p\">(</span>question<span class=\"o\">.</span>id<span class=\"p\">,)))</span>\n</code></pre></figure>\n<p>Kode ini menyertakan beberapa hal kami belum tangani di tutorial ini:</p>\n<ul>\n<li><p><a class=\"reference internal\" href=\"/id/4.2/ref/request-response/#django.http.HttpRequest.POST\" title=\"django.http.HttpRequest.POST\"><code class=\"xref py py-attr docutils literal notranslate\">request.POST</code></a> adalah obyek seperti-kamus yang membiarkan anda akses data diajukan oleh nama kunci. Di kasus ini, <code class=\"docutils literal notranslate\">request.POST['choice']</code> mengembalikan ID dari pilihan terpilih, sebagai string. Nilai <a class=\"reference internal\" href=\"/id/4.2/ref/request-response/#django.http.HttpRequest.POST\" title=\"django.http.HttpRequest.POST\"><code class=\"xref py py-attr docutils literal notranslate\">request.POST</code></a> selalu string.</p>\n<p>Catat bahwa Django juga menyediakan <a class=\"reference internal\" href=\"/id/4.2/ref/request-response/#django.http.HttpRequest.GET\" title=\"django.http.HttpRequest.GET\"><code class=\"xref py py-attr docutils literal notranslate\">request.GET</code></a> untuk mengakses data GET di cara sama -- tetapi kami eksplisit menggunakan <a class=\"reference internal\" href=\"/id/4.2/ref/request-response/#django.http.HttpRequest.POST\" title=\"django.http.HttpRequest.POST\"><code class=\"xref py py-attr docutils literal notranslate\">request.POST</code></a> di kode kami, untuk memastikan bahwa data hanya diubah melalui panggilan POST.</p>\n</li>\n<li><p><code class=\"docutils literal notranslate\">request.POST['choice']</code> akan menaikkan <a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#KeyError\" title=\"(di Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\">KeyError</code></a> jika <code class=\"docutils literal notranslate\">pilihan</code> tidak disediakan di data POST. Kode diatas memeriksa untuk <a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#KeyError\" title=\"(di Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\">KeyError</code></a> dan menampilkan kembali formulir pertanyaan dengan pesan kesalahan jika <code class=\"docutils literal notranslate\">pilihan</code> tidak diberikan.</p></li>\n<li><p>Setelah menaikkan jumlah pilihan, kode mengembalikan sebuah <a class=\"reference internal\" href=\"/id/4.2/ref/request-response/#django.http.HttpResponseRedirect\" title=\"django.http.HttpResponseRedirect\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponseRedirect</code></a> daripada <a class=\"reference internal\" href=\"/id/4.2/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponse</code></a> biasa. <a class=\"reference internal\" href=\"/id/4.2/ref/request-response/#django.http.HttpResponseRedirect\" title=\"django.http.HttpResponseRedirect\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponseRedirect</code></a> mengambil argumen tunggal: URL dimana pengguna akan dialihkan (lihat titik berikut untuk bagaimana membangun URL di kasus ini).</p>\n<p>Seperti ditunjukkan komentar Python diatas, aanda harus selalu mengembalikan <a class=\"reference internal\" href=\"/id/4.2/ref/request-response/#django.http.HttpResponseRedirect\" title=\"django.http.HttpResponseRedirect\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponseRedirect</code></a> setelah berhasil berurusan dengan data POST. Saran ini tidak khusus pada Django; itu adalah praktik pengembangan jaringan bagus secara umum.</p>\n</li>\n<li><p>Kami sedang menggunakan fungsi <a class=\"reference internal\" href=\"/id/4.2/ref/urlresolvers/#django.urls.reverse\" title=\"django.urls.reverse\"><code class=\"xref py py-func docutils literal notranslate\">reverse()</code></a> di pembangun <a class=\"reference internal\" href=\"/id/4.2/ref/request-response/#django.http.HttpResponseRedirect\" title=\"django.http.HttpResponseRedirect\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponseRedirect</code></a> di contoh ini. Fungsi ini membantu mengindari memiliki URL kode keras di fungsi tampilan. Itu diberikan nama dari tampilan yang kami ingin melewatkan kendali ke dan bagian variabel dari corak URL yang menunjuk ke tampilan itu. Dalam kasus ini, menggunakan URLconf kami setel di <a class=\"reference internal\" href=\"/id/4.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>, panggilan <a class=\"reference internal\" href=\"/id/4.2/ref/urlresolvers/#django.urls.reverse\" title=\"django.urls.reverse\"><code class=\"xref py py-func docutils literal notranslate\">reverse()</code></a> ini akan mengembalikan deretan karakter seperti</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>dimana <code class=\"docutils literal notranslate\">3</code> adalah nilai dari <code class=\"docutils literal notranslate\">question.id</code>. Ini URL dialihkan akan memanggil tampilan <code class=\"docutils literal notranslate\">'results'</code> untuk menampilkan halaman akhir.</p>\n</li>\n</ul>\n<p>Seperti disebutkan di <a class=\"reference internal\" href=\"/id/4.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>, <code class=\"docutils literal notranslate\">request</code> adalah sebuah obyek <a class=\"reference internal\" href=\"/id/4.2/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\">HttpRequest</code></a>. Untuk lebih pada obyek <a class=\"reference internal\" href=\"/id/4.2/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\">HttpRequest</code></a>, lihat <a class=\"reference internal\" href=\"/id/4.2/ref/request-response/\"><span class=\"doc\">permintaan dan tanggapan dokumentasi</span></a>.</p>\n<p>Setelah seseorang memilih di pertanyaan, tampilan <code class=\"docutils literal notranslate\">vote()</code> mengalihkan ke halaman hasil untuk pertanyaan. Mari kita tulis tampilan itu:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/views.py</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=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> get_object_or_404<span class=\"p\">,</span> render\n\n\n<span class=\"k\">def</span> <span class=\"nf\">results</span><span class=\"p\">(</span>request<span class=\"p\">,</span> question_id<span class=\"p\">):</span>\n    question <span class=\"o\">=</span> get_object_or_404<span class=\"p\">(</span>Question<span class=\"p\">,</span> pk<span class=\"o\">=</span>question_id<span class=\"p\">)</span>\n    <span class=\"k\">return</span> render<span class=\"p\">(</span>request<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> question<span class=\"p\">})</span>\n</code></pre></figure>\n<p>Ini hampir tepat sama seperti tampilan <code class=\"docutils literal notranslate\">detail()</code> dari <a class=\"reference internal\" href=\"/id/4.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>. Perbedaannya adalah hanya nama cetakan. Kami akan memperbaiki kelebihan ini kemudian.</p>\n<p>Sekarang, buat cetakan <code class=\"docutils literal notranslate\">polls/result.html</code>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/templates/polls/results.html</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>Sekarang, pergi ke <code class=\"docutils literal notranslate\">/polls/1/</code> di perambah anda dan pilih di pertanyaan. Anda seharusnya melihat halaman hasil yang mendapatkan pembaharuan setiap waktu anda memilih. Jika anda mengajukan formulir tanpa memilih pilihan, anda akan melihat pesan kesalahan.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Catatan</p>\n<p>Kode untuk tampilan <code class=\"docutils literal notranslate\">vote()</code> kami mempunyai masalah kecil. Dia pertama mendapatkan obyek <code class=\"docutils literal notranslate\">selected_choice</code> dari basistada, lalu menghitung nilai baru dari <code class=\"docutils literal notranslate\">votes</code>, dan lalu menyimpan kembali ke basisdata. Jika dua pengguna dari situs jaringan anda mencoba memilih <em>tepatnya waktu sama</em>, ini mungkin menjadi salah: nilai sama, mari kita katakan 42, akan ditarik untuk <code class=\"docutils literal notranslate\">votes</code>. Lalu, untuk kedua pengguna nilai baru dari 43 dihitung dan disimpan, tetapi 44 akan menjadi nilai diharapkan.</p>\n<p>Ini disebut <em>kondisi jarang</em>. Jika anda tertarik, anda dapat membaca <a class=\"reference internal\" href=\"/id/4.2/ref/models/expressions/#avoiding-race-conditions-using-f\"><span class=\"std std-ref\">Menghindari kondisi balapan menggunakan F()</span></a> untuk mempelajari bagaimana anda dapat mengatasi masalah ini.</p>\n</aside>\n</section>\n<section id=\"use-generic-views-less-code-is-better\">\n<h2>Gunakan tampilan umum: Sedikit kode lebih baik<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>Tampilan <code class=\"docutils literal notranslate\">detail()</code> (from <a class=\"reference internal\" href=\"/id/4.2/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>) dan <code class=\"docutils literal notranslate\">results()</code> sangat pendek -- dand seperti disebutkan diatas, berlebih-lebihan. Tampilan <code class=\"docutils literal notranslate\">index()</code>, yang menampilkan daftar dari jejak pendapat, adalah mirip.</p>\n<p>Tampilan ini mewakili kasus umum dari pengembangan dasar jaringan: mendapatkan data dari basisdata menurut sebuah parameter dilewatkan dalam URL, membuat sebuah cetakan dan mengembalikan cetakan yang dibangun. Karena ini sudah umum, Django menyediakan jalan pintas, disebut sistem &quot;generic views&quot;.</p>\n<p>Generic views abstract common patterns to the point where you don't even need to\nwrite Python code to write an app. For example, the\n<a class=\"reference internal\" href=\"/id/4.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\">ListView</code></a> and\n<a class=\"reference internal\" href=\"/id/4.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\">DetailView</code></a> generic views\nabstract the concepts of &quot;display a list of objects&quot; and\n&quot;display a detail page for a particular type of object&quot; respectively.</p>\n<p>Mari rubah aplikasi jejak pendapat kami menggunakan sistem tampilan umum, sehingga kami dapat menghapus sekelompok dari kode milik kami. Kami harus mengambil beberapa langkah untuk membuat perubahan. Kami akan:</p>\n<ol class=\"arabic simple\">\n<li><p>Rubah URLconf.</p></li>\n<li><p>Hapus beberapa lama, tampilan tidak dibutuhkan.</p></li>\n<li><p>Memperkenalkan tampilan baru berbasis pada tampilan umum Django.</p></li>\n</ol>\n<p>Membaca untuk rinci.</p>\n<aside class=\"admonition-why-the-code-shuffle admonition\" role=\"note\">\n<p class=\"admonition-title\">Kenapa kode dikocok?</p>\n<p>Umumnya, ketika menulis aplikasi Django, anda akan menilai apakah tampilan umum cocok untuk masalah anda, dan anda akan menggunakan mereka dari mulai, daripada mengurai kembali kode anda setengah jalan. Tetapi tutorial ini sengaja fokus pada penulisan tampilan &quot;cara sulit&quot; sampai sekarang, untuk fokus pada konsep inti.</p>\n<p>Anda harus mengetahui matematika dasar sebelum mulai menggunakan penghitung.</p>\n</aside>\n<section id=\"amend-urlconf\">\n<h3>Merubah 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>Pertama, buka URLconf <code class=\"docutils literal notranslate\">polls/urls.py</code> dan rubah nya seperti itu:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/urls.py</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=\"nn\">django.urls</span> <span class=\"kn\">import</span> path\n\n<span class=\"kn\">from</span> <span class=\"nn\">.</span> <span class=\"kn\">import</span> views\n\napp_name <span class=\"o\">=</span> <span class=\"s2\">&quot;polls&quot;</span>\nurlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;&quot;</span><span class=\"p\">,</span> views<span class=\"o\">.</span>IndexView<span class=\"o\">.</span>as_view<span class=\"p\">(),</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;index&quot;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;&lt;int:pk&gt;/&quot;</span><span class=\"p\">,</span> views<span class=\"o\">.</span>DetailView<span class=\"o\">.</span>as_view<span class=\"p\">(),</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;detail&quot;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;&lt;int:pk&gt;/results/&quot;</span><span class=\"p\">,</span> views<span class=\"o\">.</span>ResultsView<span class=\"o\">.</span>as_view<span class=\"p\">(),</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;results&quot;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;&lt;int:question_id&gt;/vote/&quot;</span><span class=\"p\">,</span> views<span class=\"o\">.</span>vote<span class=\"p\">,</span> name<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>Note that the name of the matched pattern in the path strings of the second and\nthird patterns has changed from <code class=\"docutils literal notranslate\">&lt;question_id&gt;</code> to <code class=\"docutils literal notranslate\">&lt;pk&gt;</code>. This is\nnecessary because we'll use the\n<a class=\"reference internal\" href=\"/id/4.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\">DetailView</code></a> generic view to replace our\n<code class=\"docutils literal notranslate\">detail()</code> and <code class=\"docutils literal notranslate\">results()</code> views, and it expects the primary key value\ncaptured from the URL to be called <code class=\"docutils literal notranslate\">&quot;pk&quot;</code>.</p>\n</section>\n<section id=\"amend-views\">\n<h3>Merubah tampilan<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>Selanjutnya, kami akan memindahkan tampilan <code class=\"docutils literal notranslate\">index</code>, <code class=\"docutils literal notranslate\">detail</code>, dan <code class=\"docutils literal notranslate\">results</code> lama dan menggunakan tampilan umum Django. Untuk melakukannya, buka berkas <code class=\"docutils literal notranslate\">polls/views.py</code> dan rubah seperti itu:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/views.py</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=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponseRedirect\n<span class=\"kn\">from</span> <span class=\"nn\">django.shortcuts</span> <span class=\"kn\">import</span> get_object_or_404<span class=\"p\">,</span> render\n<span class=\"kn\">from</span> <span class=\"nn\">django.urls</span> <span class=\"kn\">import</span> reverse\n<span class=\"kn\">from</span> <span class=\"nn\">django.views</span> <span class=\"kn\">import</span> generic\n\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> Choice<span class=\"p\">,</span> Question\n\n\n<span class=\"k\">class</span> <span class=\"nc\">IndexView</span><span class=\"p\">(</span>generic<span class=\"o\">.</span>ListView<span class=\"p\">):</span>\n    template_name <span class=\"o\">=</span> <span class=\"s2\">&quot;polls/index.html&quot;</span>\n    context_object_name <span class=\"o\">=</span> <span class=\"s2\">&quot;latest_question_list&quot;</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">get_queryset</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"sd\">&quot;&quot;&quot;Return the last five published questions.&quot;&quot;&quot;</span>\n        <span class=\"k\">return</span> Question<span class=\"o\">.</span>objects<span class=\"o\">.</span>order_by<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=\"nc\">DetailView</span><span class=\"p\">(</span>generic<span class=\"o\">.</span>DetailView<span class=\"p\">):</span>\n    model <span class=\"o\">=</span> Question\n    template_name <span class=\"o\">=</span> <span class=\"s2\">&quot;polls/detail.html&quot;</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">ResultsView</span><span class=\"p\">(</span>generic<span class=\"o\">.</span>DetailView<span class=\"p\">):</span>\n    model <span class=\"o\">=</span> Question\n    template_name <span class=\"o\">=</span> <span class=\"s2\">&quot;polls/results.html&quot;</span>\n\n\n<span class=\"k\">def</span> <span class=\"nf\">vote</span><span class=\"p\">(</span>request<span class=\"p\">,</span> question_id<span class=\"p\">):</span>\n    <span class=\"o\">...</span>  <span class=\"c1\"># same as above, no changes needed.</span>\n</code></pre></figure>\n<p>Each generic view needs to know what model it will be acting upon. This is\nprovided using either the <code class=\"docutils literal notranslate\">model</code> attribute (in this example, <code class=\"docutils literal notranslate\">model =\nQuestion</code> for  <code class=\"docutils literal notranslate\">DetailView</code> and <code class=\"docutils literal notranslate\">ResultsView</code>) or by defining the\n<a class=\"reference internal\" href=\"/id/4.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\">get_queryset()</code></a> method (as\nshown in <code class=\"docutils literal notranslate\">IndexView</code>).</p>\n<p>Secara awal, tampilan umum <a class=\"reference internal\" href=\"/id/4.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\">DetailView</code></a> menggunakan cetakan dipanggil <code class=\"docutils literal notranslate\">&lt;app name&gt;/&lt;model name&gt;_detail.html</code>. Di kasus kami, dia akan menggunakan cetakan <code class=\"docutils literal notranslate\">&quot;polls/question_detail.html&quot;</code>. Atribut <code class=\"docutils literal notranslate\">template_name</code> digunakan untuk memberitahu Django untuk menggunakan cetakan spesifik dibandingkan dari nama cetakan awal otomatis dibangkitkan. Kami juga menentukan <code class=\"docutils literal notranslate\">template_name</code> untuk tampilan daftar <code class=\"docutils literal notranslate\">results</code> -- ini memastikan bahwa tampilan hasil dan tampilan rinci mempunyai penampilan ebrbeda ketika dibentuk, bahkan mereka berdua <a class=\"reference internal\" href=\"/id/4.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\">DetailView</code></a> dibelakang layar.</p>\n<p>Demikian pula, tampilan umum <a class=\"reference internal\" href=\"/id/4.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\">ListView</code></a> menggunakan cetakan awal disebut <code class=\"docutils literal notranslate\">&lt;app name&gt;/&lt;model name&gt;_list.html</code>; kami menggunakan <code class=\"docutils literal notranslate\">template_name</code> untuk memberitahu <a class=\"reference internal\" href=\"/id/4.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\">ListView</code></a> untuk menggunakan cetakan <code class=\"docutils literal notranslate\">&quot;polls/index.html&quot;</code> kami yang ada.</p>\n<p>Dalam bagian sebelumnya dari tutorial, cetakan telah disediakan dengan sebuah konteks yang mengandung variabel konteks <code class=\"docutils literal notranslate\">question</code> dan <code class=\"docutils literal notranslate\">latest_question_list</code>. Untuk <code class=\"docutils literal notranslate\">DetailView</code> variabel <code class=\"docutils literal notranslate\">question</code> adalah disediakan otomatis -- sejak kami menggunakan model Django (<code class=\"docutils literal notranslate\">Question</code>), Django dapat menentukan sebuah nama sesuai untuk variabel konteks. Bagaimanapun untuk ListView, variabel konteks dibangkitkan otomatos adalah <code class=\"docutils literal notranslate\">question_list</code>. Untuk menimpa ini kami menyediakan atribut <code class=\"docutils literal notranslate\">context_object_name</code>, menentukan apa yang kita ingin gunakan <code class=\"docutils literal notranslate\">latest_question_list</code>. Sebagai sebuah pendekatan alternatif, anda dapat merubah cetakan anda untuk mencocokkan dengan variabel konteks awalan baru -- tetapi itu lebih mudah memberitahu Django untuk menggunakan varaibel anda inginkan.</p>\n<p>Jalankan peladen, dan gunakan aplikasi jejak pendapat baru anda berdasarkan tampilan umum.</p>\n<p>Untuk rincian penuh pada tampilan umum, lihat <a class=\"reference internal\" href=\"/id/4.2/topics/class-based-views/\"><span class=\"doc\">dokumentasi tampilan umum</span></a>.</p>\n<p>Ketika anda nyaman dengan formulir dan tampilan umum, baca <a class=\"reference internal\" href=\"/id/4.2/intro/tutorial05/\"><span class=\"doc\">bagian 5 dari tutorial ini</span></a> untuk mempelajari tentang aplikasi jejak pendapat kami.</p>\n</section>\n</section>","rootId":"writing-your-first-django-app-part-4","toc":[{"title":"Tulis sebuah formulir minimal","anchor":"write-a-minimal-form","children":[]},{"title":"Gunakan tampilan umum: Sedikit kode lebih baik","anchor":"use-generic-views-less-code-is-better","children":[{"title":"Merubah URLconf","anchor":"amend-urlconf","children":[]},{"title":"Merubah tampilan","anchor":"amend-views","children":[]}]}],"breadcrumbs":[{"docname":"intro/index","title":"Mulai","url":"/id/4.2/intro/"}],"prev":{"docname":"intro/tutorial03","title":"Menulis aplikasi Django pertama anda, bagian 3","url":"/id/4.2/intro/tutorial03/"},"next":{"docname":"intro/tutorial05","title":"Menulis aplikasi Django pertama anda, bagian 5","url":"/id/4.2/intro/tutorial05/"},"formats":{"html":"/id/4.2/intro/tutorial04/","markdown":"/id/4.2/intro/tutorial04.md","json":"/id/4.2/intro/tutorial04.json"},"source":"https://github.com/django/django/blob/stable/4.2.x/docs/intro/tutorial04.txt","official":"https://docs.djangoproject.com/id/4.2/intro/tutorial04/","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","1.9"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}