{"id":5841,"date":"2022-11-28T02:26:02","date_gmt":"2022-11-28T02:26:02","guid":{"rendered":"https:\/\/www.pythontutorial.net\/?page_id=5841"},"modified":"2023-08-17T09:11:16","modified_gmt":"2023-08-17T09:11:16","slug":"django-form","status":"publish","type":"page","link":"https:\/\/www.pythontutorial.net\/django-tutorial\/django-form\/","title":{"rendered":"Django Form"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you&#8217;ll learn how to create a Django Form to create, update, and delete Post models of the blog application.<\/p>\n\n\n\n<p class=\"note\">This tutorial begins where&nbsp;creating the <a href=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-admin-page\/\">Django admin page<\/a> tutorial left off.<\/p>\n\n\n\n<p>Django admin is good enough for admin to manage the contents based on the models. However, when you want the users of the website to manage their content, you need to create separate forms for them.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='introduction-to-the-django-form'>Introduction to the Django Form <a href=\"#introduction-to-the-django-form\" class=\"anchor\" id=\"introduction-to-the-django-form\" title=\"Anchor for Introduction to the Django Form\">#<\/a><\/h2>\n\n\n\n<p>Handling forms involves very complex logic:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Prepare an HTML form.<\/li>\n\n\n\n<li>Validate fields in the browser using JavaScript or built-in HTML5 validation.<\/li>\n\n\n\n<li>Receive the values in the server.<\/li>\n\n\n\n<li>Validate fields in the server.<\/li>\n\n\n\n<li>Processing form values like saving them into the database if the form is valid<\/li>\n\n\n\n<li>Rerender the form with old values and an error message if the form is invalid.<\/li>\n<\/ul>\n\n\n\n<p>Django forms simplify and automate almost all of the above steps. <\/p>\n\n\n\n<p class=\"note\">Note that you can write code to do all of the above steps manually if you want more customization of the forms.<\/p>\n\n\n\n<p>All forms in Django inherit from the <code>django.forms.Form<\/code> class. The <code>ModelForm<\/code> class allows you to create a form that associates with a <a href=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-models\/\">model<\/a> .<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='defining-a-form'>Defining a form <a href=\"#defining-a-form\" class=\"anchor\" id=\"defining-a-form\" title=\"Anchor for Defining a form\">#<\/a><\/h2>\n\n\n\n<p>First, create a new file <code>forms.py<\/code> in the <code>blog<\/code> application&#8217;s directory.<\/p>\n\n\n\n<p>Second, define a new form called <code>PostForm<\/code> that inherits from the <code>ModelForm<\/code> class:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> django.forms <span class=\"hljs-keyword\">import<\/span> ModelForm\n<span class=\"hljs-keyword\">from<\/span> .models <span class=\"hljs-keyword\">import<\/span> Post\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PostForm<\/span><span class=\"hljs-params\">(ModelForm)<\/span>:<\/span>\n    <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Meta<\/span>:<\/span>\n        model = Post\n        fields = &#91;<span class=\"hljs-string\">'title'<\/span>,<span class=\"hljs-string\">'content'<\/span>, <span class=\"hljs-string\">'author'<\/span>, <span class=\"hljs-string\">'author'<\/span>]       <\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Import <code>ModelForm<\/code> from the <code>django.forms<\/code>.<\/li>\n\n\n\n<li>Import <code>Post<\/code> from the <code>models.py<\/code> module.<\/li>\n\n\n\n<li>Define <code>PostForm<\/code> class that inherits from the <code>ModelForm<\/code> class. In the <code>PostForm<\/code> class, define the <code>Meta<\/code> class and specify the <code>model<\/code> and <code>fields<\/code> attributes.<\/li>\n<\/ul>\n\n\n\n<p>Third, define a route that displays the <code>PostForm<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> django.urls <span class=\"hljs-keyword\">import<\/span> path\n<span class=\"hljs-keyword\">from<\/span> . <span class=\"hljs-keyword\">import<\/span> views\n\nurlpatterns = &#91;\n    path(<span class=\"hljs-string\">''<\/span>, views.home, name=<span class=\"hljs-string\">'posts'<\/span>),\n    path(<span class=\"hljs-string\">'post\/create'<\/span>, views.create_post, name=<span class=\"hljs-string\">'post-create'<\/span>),\n    path(<span class=\"hljs-string\">'about\/'<\/span>, views.about, name=<span class=\"hljs-string\">'about'<\/span>),\n]\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Fourth, define <code>create_post()<\/code> function that displays the form:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> django.shortcuts <span class=\"hljs-keyword\">import<\/span> render\n<span class=\"hljs-keyword\">from<\/span> .models <span class=\"hljs-keyword\">import<\/span> Post\n<span class=\"hljs-keyword\">from<\/span> .forms <span class=\"hljs-keyword\">import<\/span> PostForm\n\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">create_post<\/span><span class=\"hljs-params\">(request)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">if<\/span> request.method == <span class=\"hljs-string\">'GET'<\/span>:\n        context = {<span class=\"hljs-string\">'form'<\/span>: PostForm()}\n        <span class=\"hljs-keyword\">return<\/span> render(request, <span class=\"hljs-string\">'blog\/post_form.html'<\/span>, context)\n\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">home<\/span><span class=\"hljs-params\">(request)<\/span>:<\/span>\n    posts = Post.objects.all()\n    context = {<span class=\"hljs-string\">'posts'<\/span>: posts}\n    <span class=\"hljs-keyword\">return<\/span> render(request, <span class=\"hljs-string\">'blog\/home.html'<\/span>, context)\n\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">about<\/span><span class=\"hljs-params\">(request)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">return<\/span> render(request, <span class=\"hljs-string\">'blog\/about.html'<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the <code>create_post()<\/code>, if the <code>HTTP<\/code> request is <code>GET<\/code>, then create a new instance of the <code>PostForm<\/code> class and pass it to the <code>render()<\/code> function.<\/p>\n\n\n\n<p>Fifth, create the <code>post_form.html<\/code> template:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">{% extends 'base.html' %}\n\t\n{% block content %}\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>New Post<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">method<\/span>=<span class=\"hljs-string\">\"post\"<\/span> <span class=\"hljs-attr\">novalidate<\/span>&gt;<\/span>\n\t{% csrf_token %}\n\t{{ form.as_p }}\n\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"Save\"<\/span> \/&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n\n{% endblock content %}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the <code>post_form.html<\/code>, add the <code>csrf_token<\/code> tag and render the form using the <code>form.as_p<\/code> property. It&#8217;ll output the following:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span> <span class=\"hljs-attr\">for<\/span>=<span class=\"hljs-string\">\"id_title\"<\/span>&gt;<\/span>Title:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\"<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"title\"<\/span> <span class=\"hljs-attr\">maxlength<\/span>=<span class=\"hljs-string\">\"120\"<\/span> <span class=\"hljs-attr\">required<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"id_title\"<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span> <span class=\"hljs-attr\">for<\/span>=<span class=\"hljs-string\">\"id_content\"<\/span>&gt;<\/span>Content:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">textarea<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"content\"<\/span> <span class=\"hljs-attr\">cols<\/span>=<span class=\"hljs-string\">\"40\"<\/span> <span class=\"hljs-attr\">rows<\/span>=<span class=\"hljs-string\">\"10\"<\/span> <span class=\"hljs-attr\">required<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"id_content\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">textarea<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If you open the URL <code>http:\/\/127.0.0.1:8000\/post\/create<\/code>, you&#8217;ll see the following form:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"501\" height=\"463\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-new-post-form.png\" alt=\"\" class=\"wp-image-5851\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-new-post-form.png 501w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-new-post-form-300x277.png 300w\" sizes=\"auto, (max-width: 501px) 100vw, 501px\" \/><\/figure>\n\n\n\n<p>If you click the Save button, you&#8217;ll see the error message:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"506\" height=\"458\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-form-HTML5-client-validation.png\" alt=\"\" class=\"wp-image-5849\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-form-HTML5-client-validation.png 506w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-form-HTML5-client-validation-300x272.png 300w\" sizes=\"auto, (max-width: 506px) 100vw, 506px\" \/><\/figure>\n\n\n\n<p>Because the title, content, and author fields of the Post model are <strong>required fields <\/strong>by default, the <code>PostForm<\/code> that uses the <code>Post<\/code> model also renders an HTML form that requires these fields.<\/p>\n\n\n\n<p>To test the server validation, you can disable the client validation by adding the <code>novalidate<\/code> property to the form like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">{% extends 'base.html' %}\n\t\n{% block content %}\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>New Post<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">method<\/span>=<span class=\"hljs-string\">\"post\"<\/span> <span class=\"hljs-attr\">novalidate<\/span>&gt;<\/span>\n\t{% csrf_token %}\n\t{{ form.as_p }}\n\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"Save\"<\/span> \/&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n\n{% endblock content %}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>To handle the HTTP POST method, you need to modify the <code>create_post<\/code> function in the <code>views.py<\/code> of the <code>blog<\/code> application:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> django.shortcuts <span class=\"hljs-keyword\">import<\/span> render, redirect\n<span class=\"hljs-keyword\">from<\/span> .models <span class=\"hljs-keyword\">import<\/span> Post\n<span class=\"hljs-keyword\">from<\/span> .forms <span class=\"hljs-keyword\">import<\/span> PostForm\n\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">create_post<\/span><span class=\"hljs-params\">(request)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">if<\/span> request.method == <span class=\"hljs-string\">'GET'<\/span>:\n        context = {<span class=\"hljs-string\">'form'<\/span>: PostForm()}\n        <span class=\"hljs-keyword\">return<\/span> render(request, <span class=\"hljs-string\">'blog\/post_form.html'<\/span>, context)\n    <span class=\"hljs-keyword\">elif<\/span> request.method == <span class=\"hljs-string\">'POST'<\/span>:\n        form = PostForm(request.POST)\n        <span class=\"hljs-keyword\">if<\/span> form.is_valid():\n            form.save()\n            <span class=\"hljs-keyword\">return<\/span> redirect(<span class=\"hljs-string\">'posts'<\/span>)\n        <span class=\"hljs-keyword\">else<\/span>:\n            <span class=\"hljs-keyword\">return<\/span> render(request, <span class=\"hljs-string\">'blog\/post_form.html'<\/span>, {<span class=\"hljs-string\">'form'<\/span>: form})\n\n<span class=\"hljs-comment\"># ...<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If the HTTP request is POST (<code>request.method=='POST'<\/code>): <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create a new instance of the <code>PostForm<\/code> class with the data from the POST.<\/li>\n\n\n\n<li>Check if the form is valid.<\/li>\n\n\n\n<li>If the form is valid, save the form values into the database and redirect the web browser to the <code>'posts'<\/code> path.<\/li>\n\n\n\n<li>Otherwise, rerender the form with old values and errors.<\/li>\n<\/ul>\n\n\n\n<p>If you submit the form without entering anything values, you&#8217;ll get the following error messages:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"501\" height=\"581\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-new-post-form-server-validation.png\" alt=\"\" class=\"wp-image-5852\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-new-post-form-server-validation.png 501w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-new-post-form-server-validation-259x300.png 259w\" sizes=\"auto, (max-width: 501px) 100vw, 501px\" \/><\/figure>\n\n\n\n<p>However, when you provide values for some required fields, Django renders the form with old values and displays error messages for only invalid fields.<\/p>\n\n\n\n<p>For example, the following form displays the error message for the <code>title<\/code> field while retaining the old values for the <code>content<\/code> and <code>author<\/code> fields:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"506\" height=\"498\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-server-validation-and-form-rerendering.png\" alt=\"\" class=\"wp-image-5853\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-server-validation-and-form-rerendering.png 506w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-server-validation-and-form-rerendering-300x295.png 300w\" sizes=\"auto, (max-width: 506px) 100vw, 506px\" \/><\/figure>\n\n\n\n<p>If you enter valid values for all the fields, Django saves the values into the database <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"498\" height=\"452\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-valid-values.png\" alt=\"\" class=\"wp-image-5854\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-valid-values.png 498w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-valid-values-300x272.png 300w\" sizes=\"auto, (max-width: 498px) 100vw, 498px\" \/><\/figure>\n\n\n\n<p>&#8230;and redirect to the post list:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"454\" height=\"633\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-new-post-on-post-list.png\" alt=\"\" class=\"wp-image-5856\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-new-post-on-post-list.png 454w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-form-new-post-on-post-list-215x300.png 215w\" sizes=\"auto, (max-width: 454px) 100vw, 454px\" \/><\/figure>\n\n\n\n<p class=\"note\"><a href=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2023\/01\/django_project_8.zip\" target=\"_blank\" rel=\"noreferrer noopener\">Download the Django Project source code<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='summary'>Summary <a href=\"#summary\" class=\"anchor\" id=\"summary\" title=\"Anchor for Summary\">#<\/a><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create a model form by subclassing the <code>ModelForm<\/code>.<\/li>\n\n\n\n<li>Add the <code>novalidate<\/code> property to the form to disable HTML5 validation temporarily for testing server validation.<\/li>\n\n\n\n<li>Use <code>form.is_valid()<\/code> to check if the form is valid. <\/li>\n\n\n\n<li>Use <code>form.save()<\/code> to save form values into the database.<\/li>\n\n\n\n<li>Use <code>redirect()<\/code> to redirect to a path.<\/li>\n<\/ul>\n<div class=\"helpful-block-content\" data-title=\"\">\n\t<header>\n\t\t<div class=\"wth-question\">Was this tutorial helpful ?<\/div>\n\t\t<div class=\"wth-thumbs\">\n\t\t\t<button\n\t\t\t\tdata-post=\"5841\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-form\/\"\n\t\t\t\tdata-post-title=\"Django Form\"\n\t\t\t\tdata-response=\"1\"\n\t\t\t\tclass=\"wth-btn-rounded wth-yes-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\tclass=\"feather feather-thumbs-up block w-full h-full\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> Yes <\/span>\n\t\t\t<\/button>\n\n\t\t\t<button\n\t\t\t\tdata-response=\"0\"\n\t\t\t\tdata-post=\"5841\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-form\/\"\n\t\t\t\tdata-post-title=\"Django Form\"\n\t\t\t\tclass=\"wth-btn-rounded wth-no-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> No <\/span>\n\t\t\t<\/button>\n\t\t<\/div>\n\t<\/header>\n\n\t<div class=\"wth-form hidden\">\n\t\t<div class=\"wth-form-wrapper\">\n\t\t\t<div class=\"wth-title\"><\/div>\n\t\t\t<textarea class=\"wth-message\"><\/textarea>\n\t\t\t<input type=\"button\" name=\"wth-submit\" class=\"wth-btn wth-btn-submit\" id=\"wth-submit\" \/>\n\t\t\t<input type=\"button\" class=\"wth-btn wth-btn-cancel\" value=\"Cancel\" \/>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you&#8217;ll learn how to create a Django Form to create a new post and save it into the database.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":5531,"menu_order":6,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-5841","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/5841","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/comments?post=5841"}],"version-history":[{"count":0,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/5841\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/5531"}],"wp:attachment":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/media?parent=5841"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}