{"id":5900,"date":"2022-11-28T09:24:13","date_gmt":"2022-11-28T09:24:13","guid":{"rendered":"https:\/\/www.pythontutorial.net\/?page_id=5900"},"modified":"2023-08-17T09:30:50","modified_gmt":"2023-08-17T09:30:50","slug":"django-login","status":"publish","type":"page","link":"https:\/\/www.pythontutorial.net\/django-tutorial\/django-login\/","title":{"rendered":"Django Login"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you&#8217;ll learn how to create a Django login form that allows users to log in using a username and password.<\/p>\n\n\n\n<p class=\"note\">This tutorial begins where&nbsp;the <a href=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-delete-form\/\">Django Delete Form tutorial<\/a>&nbsp;left off.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='create-a-new-application'>Create a new application <a href=\"#create-a-new-application\" class=\"anchor\" id=\"create-a-new-application\" title=\"Anchor for Create a new application\">#<\/a><\/h2>\n\n\n\n<p>First, <a href=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-create-app\/\">create a new application<\/a> called <code>users<\/code> by executing the <code>startapp<\/code> command:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">django-admin startapp users<\/code><\/span><\/pre>\n\n\n<p>The project directory will look like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">\u251c\u2500\u2500 blog\n\u251c\u2500\u2500 db.sqlite3\n\u251c\u2500\u2500 manage.py\n\u251c\u2500\u2500 mysite\n\u251c\u2500\u2500 static\n\u251c\u2500\u2500 templates\n\u2514\u2500\u2500 users<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, register the <code>users<\/code> application in the installed apps of the <code>settings.py<\/code> of the project:<\/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 shcb-code-table\"><span class='shcb-loc'><span>INSTALLED_APPS = &#91;\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-string\">'django.contrib.admin'<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-string\">'django.contrib.auth'<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-string\">'django.contrib.contenttypes'<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-string\">'django.contrib.sessions'<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-string\">'django.contrib.messages'<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-string\">'django.contrib.staticfiles'<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-comment\"># local<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-string\">'blog.apps.BlogConfig'<\/span>,\n<\/span><\/span><mark class='shcb-loc'><span>    <span class=\"hljs-string\">'users.apps.UsersConfig'<\/span>\n<\/span><\/mark><span class='shcb-loc'><span>]\n<\/span><\/span><\/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>Third, create a new <code>urls.py<\/code> file inside the <code>users<\/code> app with the following code:<\/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.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;]<\/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>Finally, include the <code>urls.py<\/code> of the <code>users<\/code> application in the <code>urls.py<\/code> of the project by using the <code>include()<\/code> function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-code-table\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> django.contrib <span class=\"hljs-keyword\">import<\/span> admin\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> django.urls <span class=\"hljs-keyword\">import<\/span> path, include\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>urlpatterns = &#91;\n<\/span><\/span><span class='shcb-loc'><span>    path(<span class=\"hljs-string\">'admin\/'<\/span>, admin.site.urls),\n<\/span><\/span><span class='shcb-loc'><span>    path(<span class=\"hljs-string\">''<\/span>,include(<span class=\"hljs-string\">'blog.urls'<\/span>)),\n<\/span><\/span><mark class='shcb-loc'><span>    path(<span class=\"hljs-string\">''<\/span>,include(<span class=\"hljs-string\">'users.urls'<\/span>))\n<\/span><\/mark><span class='shcb-loc'><span>]\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><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<h2 class=\"wp-block-heading\" id='create-a-login-form'>Create a login form <a href=\"#create-a-login-form\" class=\"anchor\" id=\"create-a-login-form\" title=\"Anchor for Create a login form\">#<\/a><\/h2>\n\n\n\n<p>First, create a login URL in the <code>urls.py<\/code> of the <code>users<\/code> application:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" 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\">'login\/'<\/span>, views.sign_in, name=<span class=\"hljs-string\">'login'<\/span>),\n]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><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>Second, create a <code>forms.py<\/code> file in the <code>users<\/code> application and define the <code>LoginForm<\/code> that inherits from the <code>Form<\/code> class:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> django <span class=\"hljs-keyword\">import<\/span> forms\n\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">LoginForm<\/span><span class=\"hljs-params\">(forms.Form)<\/span>:<\/span>\n    username = forms.CharField(max_length=<span class=\"hljs-number\">65<\/span>)\n    password = forms.CharField(max_length=<span class=\"hljs-number\">65<\/span>, widget=forms.PasswordInput)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><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>The <code>LoginForm<\/code> has two fields username and password. <\/p>\n\n\n\n<p>Third, create the <code>sign_in()<\/code> function in the <code>views.py<\/code> file of the <code>users<\/code> application to render the <code>login.html<\/code> template:<\/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\n<span class=\"hljs-keyword\">from<\/span> .forms <span class=\"hljs-keyword\">import<\/span> LoginForm\n\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">sign_in<\/span><span class=\"hljs-params\">(request)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">if<\/span> request.method == <span class=\"hljs-string\">'GET'<\/span>:\n        form = LoginForm()\n        <span class=\"hljs-keyword\">return<\/span> render(request, <span class=\"hljs-string\">'users\/login.html'<\/span>, {<span class=\"hljs-string\">'form'<\/span>: form})\n<\/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>Fourth, create the <code>templates\/users<\/code> directory inside the <code>users<\/code> application:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">mkdir templates\ncd templates\nmkdir users<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Fifth, create the <code>login.html<\/code> template inside the <code>templates\/users<\/code> directory that extends the <code>base.html<\/code> template:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">{% extends 'base.html' %}\n\n{% block content %}\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<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>Login<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\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\">\"Login\"<\/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-9\"><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>Sixth, open the login URL, and you&#8217;ll see the login form:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">http:&#47;&#47;127.0.0.1:8000\/login<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<figure class=\"wp-block-image size-full border\"><img loading=\"lazy\" decoding=\"async\" width=\"504\" height=\"227\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form.png\" alt=\"\" class=\"wp-image-5902\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form.png 504w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-300x135.png 300w\" sizes=\"auto, (max-width: 504px) 100vw, 504px\" \/><\/figure>\n\n\n\n<p>If you enter a username\/password and click the Login button, you&#8217;ll get an error because we haven&#8217;t added the code that handles the HTTP POST request yet.<\/p>\n\n\n\n<p>Seventh, modify the <code>sign_in()<\/code> function to handle the login process:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-code-table\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> django.shortcuts <span class=\"hljs-keyword\">import<\/span> render, redirect\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> django.contrib <span class=\"hljs-keyword\">import<\/span> messages\n<\/span><\/span><mark class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> django.contrib.auth <span class=\"hljs-keyword\">import<\/span> login, authenticate\n<\/span><\/mark><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> .forms <span class=\"hljs-keyword\">import<\/span> LoginForm\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">sign_in<\/span><span class=\"hljs-params\">(request)<\/span>:<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">if<\/span> request.method == <span class=\"hljs-string\">'GET'<\/span>:\n<\/span><\/span><span class='shcb-loc'><span>        form = LoginForm()\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> render(request,<span class=\"hljs-string\">'users\/login.html'<\/span>, {<span class=\"hljs-string\">'form'<\/span>: form})\n<\/span><\/span><span class='shcb-loc'><span>    \n<\/span><\/span><mark class='shcb-loc'><span>    <span class=\"hljs-keyword\">elif<\/span> request.method == <span class=\"hljs-string\">'POST'<\/span>:\n<\/span><\/mark><mark class='shcb-loc'><span>        form = LoginForm(request.POST)\n<\/span><\/mark><mark class='shcb-loc'><span>        \n<\/span><\/mark><mark class='shcb-loc'><span>        <span class=\"hljs-keyword\">if<\/span> form.is_valid():\n<\/span><\/mark><mark class='shcb-loc'><span>            username = form.cleaned_data&#91;<span class=\"hljs-string\">'username'<\/span>]\n<\/span><\/mark><mark class='shcb-loc'><span>            password = form.cleaned_data&#91;<span class=\"hljs-string\">'password'<\/span>]\n<\/span><\/mark><mark class='shcb-loc'><span>            user = authenticate(request,username=username,password=password)\n<\/span><\/mark><mark class='shcb-loc'><span>            <span class=\"hljs-keyword\">if<\/span> user:\n<\/span><\/mark><mark class='shcb-loc'><span>                login(request, user)\n<\/span><\/mark><mark class='shcb-loc'><span>                messages.success(request,<span class=\"hljs-string\">f'Hi <span class=\"hljs-subst\">{username.title()}<\/span>, welcome back!'<\/span>)\n<\/span><\/mark><mark class='shcb-loc'><span>                <span class=\"hljs-keyword\">return<\/span> redirect(<span class=\"hljs-string\">'posts'<\/span>)\n<\/span><\/mark><mark class='shcb-loc'><span>        \n<\/span><\/mark><mark class='shcb-loc'><span>        <span class=\"hljs-comment\"># form is not valid or user is not authenticated<\/span>\n<\/span><\/mark><mark class='shcb-loc'><span>        messages.error(request,<span class=\"hljs-string\">f'Invalid username or password'<\/span>)\n<\/span><\/mark><mark class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> render(request,<span class=\"hljs-string\">'users\/login.html'<\/span>,{<span class=\"hljs-string\">'form'<\/span>: form})\n<\/span><\/mark><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><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<p>First, import the <code>authenticate<\/code> and <code>login<\/code> function from the <code>django.contrib.auth<\/code> module:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> django.contrib.auth <span class=\"hljs-keyword\">import<\/span> login, authenticate<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><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>The <code>authenticate()<\/code> function verifies a username and password. If the username and password are valid, it returns an instance of <code>User<\/code> class or <code>None<\/code> otherwise.<\/p>\n\n\n\n<p>The <code>login()<\/code> function logs a user in. Technically, it creates a session id on the server and sends it back to the web browser in the form of a cookie. <\/p>\n\n\n\n<p>In the subsequent request, the web browser sends the session id back to the web server, Django matches the cookie value with the session id and creates the <code>User<\/code> object.<\/p>\n\n\n\n<p>Second, verify the username and password using the <code>authenticate()<\/code> function if the form is valid:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">user = authenticate(request, username=username, password=password)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><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>Third, log the user in, <a href=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-flash-messages\/\">create a flash message<\/a>, and redirect the user to the <code>posts<\/code> URL if the username and password are valid:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">if<\/span> user:\n   login(request, user)\n   messages.success(request,<span class=\"hljs-string\">f'Hi <span class=\"hljs-subst\">{user.username.title()}<\/span>, welcome back!'<\/span>)\n   <span class=\"hljs-keyword\">return<\/span> redirect(<span class=\"hljs-string\">'posts'<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><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>Otherwise, create a flash error message and redirect the user back to the login page:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">messages.error(request,<span class=\"hljs-string\">f'Invalid username or password'<\/span>)\n<span class=\"hljs-keyword\">return<\/span> render(request,<span class=\"hljs-string\">'users\/login.html'<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><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 you enter a username without a password and click the Login button, you&#8217;ll get the following error message:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full border\"><img loading=\"lazy\" decoding=\"async\" width=\"506\" height=\"330\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-invalid-username-and-password.png\" alt=\"\" class=\"wp-image-5904\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-invalid-username-and-password.png 506w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-invalid-username-and-password-300x196.png 300w\" sizes=\"auto, (max-width: 506px) 100vw, 506px\" \/><\/figure>\n\n\n\n<p>However, if you enter the correct username\/password, you&#8217;ll be redirected to the post list page with a welcome message:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full border\"><img loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"498\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-valid-username-and-password.png\" alt=\"\" class=\"wp-image-5905\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-valid-username-and-password.png 474w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-valid-username-and-password-286x300.png 286w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id='add-a-logout-form'>Add a Logout form <a href=\"#add-a-logout-form\" class=\"anchor\" id=\"add-a-logout-form\" title=\"Anchor for Add a Logout form\">#<\/a><\/h2>\n\n\n\n<p>First, define a route for logging a user out:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">from<\/span> django.urls <span class=\"hljs-keyword\">import<\/span> path\n<span class=\"hljs-keyword\">from<\/span> . import views\n\nurlpatterns = &#91;\n    path(<span class=\"hljs-string\">'login\/'<\/span>, views.sign_in, name=<span class=\"hljs-string\">'login'<\/span>),\n    path(<span class=\"hljs-string\">'logout\/'<\/span>, views.sign_out, name=<span class=\"hljs-string\">'logout'<\/span>),\n]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, define the <code>sign_out()<\/code> function in the <code>views.py<\/code> file that handles the logout route:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-code-table\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> django.shortcuts <span class=\"hljs-keyword\">import<\/span> render, redirect\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> django.contrib <span class=\"hljs-keyword\">import<\/span> messages\n<\/span><\/span><mark class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> django.contrib.auth <span class=\"hljs-keyword\">import<\/span> login, authenticate, logout\n<\/span><\/mark><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> .forms <span class=\"hljs-keyword\">import<\/span> LoginForm\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">sign_in<\/span><span class=\"hljs-params\">(request)<\/span>:<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">if<\/span> request.method == <span class=\"hljs-string\">'GET'<\/span>:\n<\/span><\/span><span class='shcb-loc'><span>        form = LoginForm()\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> render(request,<span class=\"hljs-string\">'users\/login.html'<\/span>, {<span class=\"hljs-string\">'form'<\/span>: form})\n<\/span><\/span><span class='shcb-loc'><span>    \n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">elif<\/span> request.method == <span class=\"hljs-string\">'POST'<\/span>:\n<\/span><\/span><span class='shcb-loc'><span>        form = LoginForm(request.POST)\n<\/span><\/span><span class='shcb-loc'><span>        \n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">if<\/span> form.is_valid():\n<\/span><\/span><span class='shcb-loc'><span>            username = form.cleaned_data&#91;<span class=\"hljs-string\">'username'<\/span>]\n<\/span><\/span><span class='shcb-loc'><span>            password=form.cleaned_data&#91;<span class=\"hljs-string\">'password'<\/span>]\n<\/span><\/span><span class='shcb-loc'><span>            user = authenticate(request,username=username,password=password)\n<\/span><\/span><span class='shcb-loc'><span>            <span class=\"hljs-keyword\">if<\/span> user:\n<\/span><\/span><span class='shcb-loc'><span>                login(request, user)\n<\/span><\/span><span class='shcb-loc'><span>                messages.success(request,<span class=\"hljs-string\">f'Hi <span class=\"hljs-subst\">{username.title()}<\/span>, welcome back!'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>                <span class=\"hljs-keyword\">return<\/span> redirect(<span class=\"hljs-string\">'posts'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>        \n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-comment\"># either form not valid or user is not authenticated<\/span>\n<\/span><\/span><span class='shcb-loc'><span>        messages.error(request,<span class=\"hljs-string\">f'Invalid username or password'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> render(request,<span class=\"hljs-string\">'users\/login.html'<\/span>,{<span class=\"hljs-string\">'form'<\/span>: form})\n<\/span><\/span><span class='shcb-loc'><span>    \n<\/span><\/span><span class='shcb-loc'><span>    \n<\/span><\/span><span class='shcb-loc'><span>        \n<\/span><\/span><mark class='shcb-loc'><span><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">sign_out<\/span><span class=\"hljs-params\">(request)<\/span>:<\/span>\n<\/span><\/mark><mark class='shcb-loc'><span>    logout(request)\n<\/span><\/mark><mark class='shcb-loc'><span>    messages.success(request,<span class=\"hljs-string\">f'You have been logged out.'<\/span>)\n<\/span><\/mark><mark class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> redirect(<span class=\"hljs-string\">'login'<\/span>)        \n<\/span><\/mark><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><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 you log in and access the login page, you&#8217;ll still see the login form. Therefore, it&#8217;s better to redirect the logged user to the post list instead if the user accesses the login page.<\/p>\n\n\n\n<p>Third, modify the <code>sign_in()<\/code> function in the <code>views.py<\/code> of the <code>users<\/code> application:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-code-table\"><span class='shcb-loc'><span>def sign_in(request):\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">if<\/span> request.method == <span class=\"hljs-string\">'GET'<\/span>:\n<\/span><\/span><mark class='shcb-loc'><span>        <span class=\"hljs-keyword\">if<\/span> request.user.is_authenticated:\n<\/span><\/mark><mark class='shcb-loc'><span>            <span class=\"hljs-keyword\">return<\/span> redirect(<span class=\"hljs-string\">'posts'<\/span>)\n<\/span><\/mark><span class='shcb-loc'><span>        \n<\/span><\/span><span class='shcb-loc'><span>        form = LoginForm()\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> render(request,<span class=\"hljs-string\">'users\/login.html'<\/span>, {<span class=\"hljs-string\">'form'<\/span>: form})\n<\/span><\/span><span class='shcb-loc'><span>    \n<\/span><\/span><span class='shcb-loc'><span>    elif request.method == <span class=\"hljs-string\">'POST'<\/span>:\n<\/span><\/span><span class='shcb-loc'><span>        form = LoginForm(request.POST)\n<\/span><\/span><span class='shcb-loc'><span>        \n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">if<\/span> form.is_valid():\n<\/span><\/span><span class='shcb-loc'><span>            username = form.cleaned_data&#91;<span class=\"hljs-string\">'username'<\/span>]\n<\/span><\/span><span class='shcb-loc'><span>            password=form.cleaned_data&#91;<span class=\"hljs-string\">'password'<\/span>]\n<\/span><\/span><span class='shcb-loc'><span>            user = authenticate(request,username=username,password=password)\n<\/span><\/span><span class='shcb-loc'><span>            <span class=\"hljs-keyword\">if<\/span> user:\n<\/span><\/span><span class='shcb-loc'><span>                login(request, user)\n<\/span><\/span><span class='shcb-loc'><span>                messages.success(request,f<span class=\"hljs-string\">'Hi {username.title()}, welcome back!'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>                <span class=\"hljs-keyword\">return<\/span> redirect(<span class=\"hljs-string\">'posts'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>        \n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-comment\"># either form not valid or user is not authenticated<\/span>\n<\/span><\/span><span class='shcb-loc'><span>        messages.error(request,f<span class=\"hljs-string\">'Invalid username or password'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> render(request,<span class=\"hljs-string\">'users\/login.html'<\/span>,{<span class=\"hljs-string\">'form'<\/span>: form})\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The the <code>request.user.is_authenticated<\/code> returns <code>True<\/code> if a user is logged in or <code>False<\/code> otherwise.<\/p>\n\n\n\n<p>Fourth, modify the <code>base.html<\/code> template to include the logout link if the user is authenticated and the login link otherwise:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">{%load static %}\n<span class=\"hljs-meta\">&lt;!DOCTYPE <span class=\"hljs-meta-keyword\">html<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"en\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">charset<\/span>=<span class=\"hljs-string\">\"UTF-8\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"viewport\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"width=device-width, initial-scale=1.0\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"stylesheet\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"{% static 'css\/style.css' %}\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"{% static 'js\/app.js' %}\"<\/span> <span class=\"hljs-attr\">defer<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>My Site<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n  \t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">header<\/span>&gt;<\/span>\n  \t\t{%if request.user.is_authenticated %}\n  \t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>Hi {{ request.user.username | title }}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n  \t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"{% url 'logout' %}\"<\/span>&gt;<\/span>Logout<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n  \t\t{%else%}\n  \t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"{% url 'login' %}\"<\/span>&gt;<\/span>Login<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n  \t\t{%endif%}\n  \t<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">header<\/span>&gt;<\/span>\n  \t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n\t  \t{% if messages %}\n\t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"messages\"<\/span>&gt;<\/span>\n\t\t\t{% for message in messages %}\n\t\t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"alert {% if message.tags %}alert-{{ message.tags }}\"<\/span>{% <span class=\"hljs-attr\">endif<\/span> %}&gt;<\/span>\n\t\t\t\t\t{{ message }}\n\t\t\t\t<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\t\t\t{% endfor %}\n\t\t\t<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\t\t{% endif %}\n\t\t    \n\t    {%block content%} \n\t    {%endblock content%}\n  \t<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n\t\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">html<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><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 access the site, you&#8217;ll see the login link:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full border\"><img loading=\"lazy\" decoding=\"async\" width=\"460\" height=\"353\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-not-authenticated.png\" alt=\"\" class=\"wp-image-5906\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-not-authenticated.png 460w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-not-authenticated-300x230.png 300w\" sizes=\"auto, (max-width: 460px) 100vw, 460px\" \/><\/figure>\n\n\n\n<p>When you click the login link, it&#8217;ll open the login page:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full border\"><img loading=\"lazy\" decoding=\"async\" width=\"517\" height=\"275\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-not-authenticated-and-login.png\" alt=\"\" class=\"wp-image-5907\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-not-authenticated-and-login.png 517w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-not-authenticated-and-login-300x160.png 300w\" sizes=\"auto, (max-width: 517px) 100vw, 517px\" \/><\/figure>\n\n\n\n<p>If you enter the valid username and password and log in, you&#8217;ll see a welcome message as well as the logout link:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full border\"><img loading=\"lazy\" decoding=\"async\" width=\"452\" height=\"353\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-logout-link.png\" alt=\"\" class=\"wp-image-5909\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-logout-link.png 452w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-logout-link-300x234.png 300w\" sizes=\"auto, (max-width: 452px) 100vw, 452px\" \/><\/figure>\n\n\n\n<p>If you click the logout link, it redirects to the login page:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full border\"><img loading=\"lazy\" decoding=\"async\" width=\"624\" height=\"348\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-back-to-login-page.png\" alt=\"\" class=\"wp-image-5910\" srcset=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-back-to-login-page.png 624w, https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/11\/django-login-form-back-to-login-page-300x167.png 300w\" sizes=\"auto, (max-width: 624px) 100vw, 624px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id='hiding-the-edit-and-delete-links-on-the-post-list'>Hiding the edit and delete links on the post list <a href=\"#hiding-the-edit-and-delete-links-on-the-post-list\" class=\"anchor\" id=\"hiding-the-edit-and-delete-links-on-the-post-list\" title=\"Anchor for Hiding the edit and delete links on the post list\">#<\/a><\/h2>\n\n\n\n<p>If a user is logged in, the <code>request.user.is_authenticated<\/code> is <code>True<\/code>. Therefore, you can use this object to show and hide elements of the page whether the user is logged in or not.<\/p>\n\n\n\n<p>For example, the following hides the editing and deleting links on the <code>blog\/home.html<\/code> template if the user is authenticated:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-code-table\"><span class='shcb-loc'><span>{% extends 'base.html' %}\n<\/span><\/span><span class='shcb-loc'><span>\t\n<\/span><\/span><span class='shcb-loc'><span>{% block content %}\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>My Posts<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t{% for post in posts %}\n<\/span><\/span><span class='shcb-loc'><span>\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>{{ post.title }}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">small<\/span>&gt;<\/span>Published on {{ post.published_at | date:\"M d, Y\" }} by {{ post.author | title}}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">small<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>{{ post.content }}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t\n<\/span><\/span><mark class='shcb-loc'><span>\t\t{% if request.user.is_authenticated %}\n<\/span><\/mark><span class='shcb-loc'><span>\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"{% url 'post-edit' post.id %}\"<\/span>&gt;<\/span>Edit<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span> \n<\/span><\/span><span class='shcb-loc'><span>\t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"{% url 'post-delete' post.id%}\"<\/span>&gt;<\/span>Delete<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\t\t<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n<\/span><\/span><mark class='shcb-loc'><span>\t\t{% endif %}\n<\/span><\/mark><span class='shcb-loc'><span>\t\t\n<\/span><\/span><span class='shcb-loc'><span>\t{% endfor %}\n<\/span><\/span><span class='shcb-loc'><span>{% endblock content %}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><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<h2 class=\"wp-block-heading\" id='protecting-the-protected-pages'>Protecting the protected pages <a href=\"#protecting-the-protected-pages\" class=\"anchor\" id=\"protecting-the-protected-pages\" title=\"Anchor for Protecting the protected pages\">#<\/a><\/h2>\n\n\n\n<p>Typically, you should allow authenticated users to access the creating, updating, and deleting post pages. To do that you can use Django&#8217;s <code>login_required<\/code> decorator.<\/p>\n\n\n\n<p>If a view function has the <code>login_required<\/code> decorator and an unauthenticated user attempts to run it, Django will redirect the user to the login page.<\/p>\n\n\n\n<p>We&#8217;ll protect the create, update, and delete post functions using the <code>login_required<\/code> decorator.<\/p>\n\n\n\n<p>First, set the login URL in the <code>settings.py<\/code> of to the login URL:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">LOGIN_URL = <span class=\"hljs-string\">'login'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If you don&#8217;t do this, Django will redirect to the default login URL which is <code>accounts\/login\/<\/code> not <code>users\/login<\/code> as we defined in this project.<\/p>\n\n\n\n<p>Second, modify the <code>views.py<\/code> of the <code>blog<\/code> application by adding the <code>@login_required<\/code> decorator to the <code>create_post<\/code>, <code>edit_post<\/code>, and <code>delete_post<\/code> functions:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> django.shortcuts <span class=\"hljs-keyword\">import<\/span> render, redirect, get_object_or_404\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> django.contrib <span class=\"hljs-keyword\">import<\/span> messages\n<\/span><\/span><mark class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> django.contrib.auth.decorators <span class=\"hljs-keyword\">import<\/span> login_required\n<\/span><\/mark><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> .models <span class=\"hljs-keyword\">import<\/span> Post\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">from<\/span> .forms <span class=\"hljs-keyword\">import<\/span> PostForm\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><mark class='shcb-loc'><span>@login_required\n<\/span><\/mark><span class='shcb-loc'><span>def delete_post(request, id):\n<\/span><\/span><span class='shcb-loc'><span>    post = get_object_or_404(Post, pk=id)\n<\/span><\/span><span class='shcb-loc'><span>    context = {<span class=\"hljs-string\">'post'<\/span>: post}\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">if<\/span> request.method == <span class=\"hljs-string\">'GET'<\/span>:\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> render(request, <span class=\"hljs-string\">'blog\/post_confirm_delete.html'<\/span>, context)\n<\/span><\/span><span class='shcb-loc'><span>    elif request.method == <span class=\"hljs-string\">'POST'<\/span>:\n<\/span><\/span><span class='shcb-loc'><span>        post.delete()\n<\/span><\/span><span class='shcb-loc'><span>        messages.success(request,  <span class=\"hljs-string\">'The post has been deleted successfully.'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> redirect(<span class=\"hljs-string\">'posts'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><mark class='shcb-loc'><span>@login_required\n<\/span><\/mark><span class='shcb-loc'><span>def edit_post(request, id):\n<\/span><\/span><span class='shcb-loc'><span>    post = get_object_or_404(Post, id=id)\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">if<\/span> request.method == <span class=\"hljs-string\">'GET'<\/span>:\n<\/span><\/span><span class='shcb-loc'><span>        context = {<span class=\"hljs-string\">'form'<\/span>: PostForm(instance=post), <span class=\"hljs-string\">'id'<\/span>: id}\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> render(request, <span class=\"hljs-string\">'blog\/post_form.html'<\/span>, context)\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    elif request.method == <span class=\"hljs-string\">'POST'<\/span>:\n<\/span><\/span><span class='shcb-loc'><span>        form = PostForm(request.POST, instance=post)\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">if<\/span> form.is_valid():\n<\/span><\/span><span class='shcb-loc'><span>            form.save()\n<\/span><\/span><span class='shcb-loc'><span>            messages.success(\n<\/span><\/span><span class='shcb-loc'><span>                request, <span class=\"hljs-string\">'The post has been updated successfully.'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>            <span class=\"hljs-keyword\">return<\/span> redirect(<span class=\"hljs-string\">'posts'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-attr\">else<\/span>:\n<\/span><\/span><span class='shcb-loc'><span>            messages.error(request, <span class=\"hljs-string\">'Please correct the following errors:'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>            <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<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><mark class='shcb-loc'><span>@login_required\n<\/span><\/mark><span class='shcb-loc'><span>def create_post(request):\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">if<\/span> request.method == <span class=\"hljs-string\">'GET'<\/span>:\n<\/span><\/span><span class='shcb-loc'><span>        context = {<span class=\"hljs-string\">'form'<\/span>: PostForm()}\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">return<\/span> render(request, <span class=\"hljs-string\">'blog\/post_form.html'<\/span>, context)\n<\/span><\/span><span class='shcb-loc'><span>    elif request.method == <span class=\"hljs-string\">'POST'<\/span>:\n<\/span><\/span><span class='shcb-loc'><span>        form = PostForm(request.POST)\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">if<\/span> form.is_valid():\n<\/span><\/span><span class='shcb-loc'><span>            form.save()\n<\/span><\/span><span class='shcb-loc'><span>            messages.success(\n<\/span><\/span><span class='shcb-loc'><span>                request, <span class=\"hljs-string\">'The post has been created successfully.'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>            <span class=\"hljs-keyword\">return<\/span> redirect(<span class=\"hljs-string\">'posts'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-attr\">else<\/span>:\n<\/span><\/span><span class='shcb-loc'><span>            messages.error(request, <span class=\"hljs-string\">'Please correct the following errors:'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>            <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<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>def home(request):\n<\/span><\/span><span class='shcb-loc'><span>    posts = Post.objects.all()\n<\/span><\/span><span class='shcb-loc'><span>    context = {<span class=\"hljs-string\">'posts'<\/span>: posts}\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> render(request, <span class=\"hljs-string\">'blog\/home.html'<\/span>, context)\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>def about(request):\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> render(request, <span class=\"hljs-string\">'blog\/about.html'<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If you open the create, update, or delete URL, for example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">http:<span class=\"hljs-comment\">\/\/127.0.0.1\/post\/create<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>It&#8217;ll be redirected to the login page.<\/p>\n\n\n\n<p class=\"note\"><a href=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2023\/01\/django_project_11.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>Use <code>authenticate()<\/code> function to verify a user by username and password.<\/li>\n\n\n\n<li>Use <code>login()<\/code> function to log a user in.<\/li>\n\n\n\n<li>Use <code>logout()<\/code> function to log a user out.<\/li>\n\n\n\n<li>Use <code>request.user.is_authenticated<\/code> to check if the current user is authenticated.<\/li>\n\n\n\n<li>User <code>@login_required<\/code> decorator to protect pages from unauthenticated users.<\/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=\"5900\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-login\/\"\n\t\t\t\tdata-post-title=\"Django Login\"\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=\"5900\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/django-tutorial\/django-login\/\"\n\t\t\t\tdata-post-title=\"Django Login\"\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 login form that allows users to log in using a username and password.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":5531,"menu_order":10,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-5900","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/5900","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=5900"}],"version-history":[{"count":0,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/5900\/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=5900"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}