{"id":116603,"date":"2024-09-27T07:53:11","date_gmt":"2024-09-27T07:53:11","guid":{"rendered":"\/tutorials\/?p=116603"},"modified":"2025-12-22T14:10:22","modified_gmt":"2025-12-22T14:10:22","slug":"django-tutorial","status":"publish","type":"post","link":"\/tutorials\/django-tutorial","title":{"rendered":"Django tutorial: Understanding the Django framework fundamentals"},"content":{"rendered":"<p>Django is a high-level Python web framework used for rapid development and clean, pragmatic design. It simplifies many web development tasks, letting you focus on writing your app without having to reinvent the wheel.<\/p><p>This makes it one of the most popular and widely used web frameworks for building dynamic, data-driven websites and applications.<\/p><p>In this tutorial, we will walk you through the core fundamentals of Django and provide a solid foundation to build your first web application. We will cover everything from setting up a VPS and installing Python to deploying your Django project.<\/p><p>By the end of this tutorial, you&rsquo;ll have a fully functional web application and a solid understanding of how to continue developing your own projects using Django. Whether you&rsquo;re new to web development or looking to expand your skills, this Django tutorial will help you master the essentials.<\/p><p>\n\n\n\n\n\n\n<\/p><h2 class=\"wp-block-heading\" id=\"h-installing-django-framework\">Installing Django framework<\/h2><p>Before we dive into building your Django application, you&rsquo;ll need to set up your development environment. This process includes setting up a VPS, installing Python, creating a virtual environment, and installing Django.<\/p><h3 class=\"wp-block-heading\" id=\"h-prerequisites\">Prerequisites<\/h3><p>Before you begin working with Django, it&rsquo;s important to have a basic understanding of certain concepts. Here&rsquo;s what you should be familiar with:<\/p><ul class=\"wp-block-list\">\n<li><strong>Basic Python knowledge<\/strong>: Solid understanding of Python fundamentals &ndash; data types, control flow, functions, classes, modules.<\/li>\n\n\n\n<li><strong>HTML, CSS, and JavaScript basics<\/strong>: Basic knowledge of HTML, CSS, and JavaScript.<\/li>\n\n\n\n<li><strong>Understanding of databases<\/strong>: Database concepts &ndash; tables, records, primary keys, foreign keys. SQL knowledge is a plus.<\/li>\n\n\n\n<li><strong>Command-Line Interface (CLI) familiarity<\/strong>: Basic knowledge of <a href=\"\/tutorials\/linux-commands\">essential Linux commands<\/a>.<\/li>\n<\/ul><p>With these prerequisites in place, you&rsquo;ll be well-prepared to understand and follow the steps required to install Django and start building your web applications.<\/p><h3 class=\"wp-block-heading\" id=\"h-get-a-django-vps\">Get a Django VPS<\/h3><p>Choosing the right hosting environment is crucial for running your Django application smoothly. A Virtual Private Server (VPS) offers more control, scalability, and resources than shared hosting, making it ideal for Django projects. <a href=\"\/vps\/django-hosting\">Hostinger&rsquo;s<strong> <\/strong>Django VPS hosting<\/a> is an excellent choice, providing affordable plans as well as servers that are easy to set up and manage.<\/p><p>When selecting a VPS plan from Hostinger, consider the needs of your project:<\/p><ul class=\"wp-block-list\">\n<li><strong>CPU and RAM<\/strong>: A faster CPU and more RAM provide better performance, especially for more complex applications or higher traffic volumes.<\/li>\n\n\n\n<li><strong>Storage<\/strong>: Django applications often work with databases and static files. Ensure your VPS has sufficient SSD storage for your needs.<\/li>\n\n\n\n<li><strong>Bandwidth<\/strong>: Depending on your expected traffic, choose a plan with enough bandwidth to support your visitors without slowdowns.<\/li>\n<\/ul><p>For a basic Django project, a lower-tier VPS plan like <strong>KVM 1<\/strong> or <strong>KVM 2<\/strong> should be sufficient, but as your project grows, you can easily upgrade to higher-tier options for more resources.<\/p><figure class=\"wp-block-image size-large\"><a class=\"hgr-tutorials-cta hgr-tutorials-cta-vps-hosting\" href=\"\/vps-hosting\" target=\"_blank\" rel=\"noreferrer noopener\"><img decoding=\"async\" width=\"1024\" height=\"300\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2023\/02\/VPS-hosting-banner.png\/public\" alt=\"\" class=\"wp-image-77934\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2023\/02\/VPS-hosting-banner.png\/w=1024,fit=scale-down 1024w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2023\/02\/VPS-hosting-banner.png\/w=300,fit=scale-down 300w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2023\/02\/VPS-hosting-banner.png\/w=150,fit=scale-down 150w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2023\/02\/VPS-hosting-banner.png\/w=768,fit=scale-down 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure><p>Once you&rsquo;ve chosen a VPS plan and completed the purchase, follow these steps to set up the server:<\/p><ol class=\"wp-block-list\">\n<li><strong>Start VPS setup<\/strong>: Log in to <a href=\"https:\/\/hpanel.hostinger.com\/\" target=\"_blank\" rel=\"noopener\">hPanel<\/a> &ndash; on the <strong>Home <\/strong>page, you&rsquo;ll see a pending VPS setup, similar to this:<\/li>\n<\/ol><div class=\"wp-block-image\">\n<figure data-wp-context='{\"imageId\":\"69e20b3c3a398\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-large wp-lightbox-container\"><img decoding=\"async\" width=\"1121\" height=\"138\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/get_a_django_vps_2.png\/public\" alt=\"Screenshot displaying pending setup for KVM2 plan and a setup button on the far right corner.\" class=\"wp-image-116645\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/get_a_django_vps_2.png\/w=1121,fit=scale-down 1121w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/get_a_django_vps_2.png\/w=300,fit=scale-down 300w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/get_a_django_vps_2.png\/w=1024,fit=scale-down 1024w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/get_a_django_vps_2.png\/w=150,fit=scale-down 150w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/get_a_django_vps_2.png\/w=768,fit=scale-down 768w\" sizes=\"(max-width: 1121px) 100vw, 1121px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Press <strong>Setup <\/strong>and <strong>Start Now<\/strong> in the next window.<\/p><ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Select a location for your VPS<\/strong>: Consider which region you&rsquo;re expecting traffic from. The lowest latency region will not necessarily be the best for your application if expected traffic comes from Australia while you&rsquo;re located in Europe.<\/li>\n<\/ol><div class=\"wp-block-image\">\n<figure data-wp-context='{\"imageId\":\"69e20b3c3bebe\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"515\" height=\"311\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/get_a_django_vps_3.png\/public\" alt=\"Screenshot of Hostinger VPS location selector and continue button at the bottom\" class=\"wp-image-116653\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/get_a_django_vps_3.png\/w=515,fit=scale-down 515w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/get_a_django_vps_3.png\/w=300,fit=scale-down 300w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/get_a_django_vps_3.png\/w=150,fit=scale-down 150w\" sizes=\"(max-width: 515px) 100vw, 515px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><ol start=\"3\" class=\"wp-block-list\">\n<li><strong>Select OS template<\/strong>: For this guide, you should select Plain OS Ubuntu; however, Hostinger also offers an OS with Panel options and an OS with Application stack (pre-installed software dependencies).<\/li>\n\n\n\n<li><strong>Set up your VPS credentials<\/strong>: Enter the <strong>root <\/strong>password and add an SSH key if you&rsquo;d like. Finish the setup.<\/li>\n\n\n\n<li><strong>Connect via SSH<\/strong>: Use an SSH client (e.g., PuTTY for Windows or the terminal for macOS\/Linux) to connect to the server. In your terminal, enter:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ssh root@your_vps_ip<\/pre><p>Replace <strong>your_vps_ip<\/strong> with the VPS IP address from Hostinger. You&rsquo;ll be prompted to enter your root password.<\/p><ol start=\"6\" class=\"wp-block-list\">\n<li><strong>Update the server<\/strong>: It&rsquo;s important to ensure your server is up-to-date. Run the following command to update the system packages:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">apt update &amp;&amp; apt upgrade -y<\/pre><p>With the VPS ready, you can now install Python and other dependencies for Django development.<\/p><h3 class=\"wp-block-heading\" id=\"h-install-python\">Install Python<\/h3><p>To run Django, you&rsquo;ll need to <a href=\"\/tutorials\/install-pip-in-ubuntu\/\">install Python and pip on your VPS<\/a>. Most modern Linux distributions, like Ubuntu, come with Python pre-installed.<\/p><p>If you don&rsquo;t have it installed or need to update it, you can do so easily. Use the following commands to check the current Python version and install the latest version of Python 3:<\/p><ol class=\"wp-block-list\">\n<li>Check if Python is installed:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">python3 --version<\/pre><div class=\"wp-block-image\">\n<figure data-wp-context='{\"imageId\":\"69e20b3c3e1a8\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"207\" height=\"42\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/install_python.png\/public\" alt=\"Screenshot of terminal window, displaying command &quot;python --version&quot; and it's result &quot;Python 3.12.6&quot;\" class=\"wp-image-116654\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/install_python.png\/w=207,fit=scale-down 207w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/install_python.png\/w=150,fit=scale-down 150w\" sizes=\"(max-width: 207px) 100vw, 207px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><ol start=\"2\" class=\"wp-block-list\">\n<li>If your command-line interface returns the Python version number, the programming language is already installed. In that case, you simply need to install pip:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">apt install python3-pip<\/pre><ol start=\"3\" class=\"wp-block-list\">\n<li>Install Python and pip (if necessary):<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">apt install python3 python3-pip -y<\/pre><p>Once Python is installed, you&rsquo;re ready to set up a virtual environment.<\/p><h3 class=\"wp-block-heading\" id=\"h-set-up-a-virtual-environment\">Set up a virtual environment<\/h3><p>A virtual environment is an isolated space where you can install Python packages and dependencies for a specific project. This method does not affect the system-wide Python environment or other projects.<\/p><p>This is crucial when working with Django because different projects might require different versions of packages. A virtual environment ensures that each project&rsquo;s dependencies are neatly contained and do not conflict with others.<\/p><p>Why use a Virtual Environment:<\/p><ul class=\"wp-block-list\">\n<li><strong>Isolation<\/strong>: Keeps your project&rsquo;s dependencies separate from other Python projects.<\/li>\n\n\n\n<li><strong>Version Control<\/strong>: You can install different versions of packages in each virtual workspace, avoiding conflicts between projects.<\/li>\n\n\n\n<li><strong>Cleaner Environment<\/strong>: It allows you to experiment with packages without affecting the global Python environment on your server.<\/li>\n<\/ul><p>Follow these steps to set up a <a href=\"\/tutorials\/how-to-create-a-python-virtual-environment\">virtual environment on your VPS<\/a>:<\/p><ol class=\"wp-block-list\">\n<li>Install the <strong>venv <\/strong>package (if it&rsquo;s not already installed):<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">apt install python3-venv -y<\/pre><ol start=\"2\" class=\"wp-block-list\">\n<li>Create and navigate to the directory where you want to store your Django project and create a virtual environment:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">mkdir myprojectcd myproject<\/pre><p>Replace <strong>myproject <\/strong>with whatever you want to name your project folder.<\/p><ol start=\"3\" class=\"wp-block-list\">\n<li>Create a virtual environment using <strong>venv <\/strong>:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">python3 -m venv env_name<\/pre><ol start=\"4\" class=\"wp-block-list\">\n<li>Activate the virtual environment:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">source env_name\/bin\/activate<\/pre><p>Once activated, the shell prompt will change to reflect the environment (e.g.,<strong>(env_name)<\/strong>), indicating that you&rsquo;re working within your virtual environment.<\/p><p>This setup ensures that all Django-related dependencies are isolated within the virtual environment, keeping your server clean and organized.<\/p><h3 class=\"wp-block-heading\" id=\"h-install-django\">Install Django<\/h3><p>With your virtual environment set up, the next step is to install the Django framework itself, which you can do using Python&rsquo;s package manager, <strong>pip<\/strong>. Installing Django in your virtual environment ensures that it&rsquo;s isolated from other projects and can be managed independently.<\/p><p>To <a href=\"\/tutorials\/how-to-install-django\">install Django<\/a>, follow these steps:<\/p><ol class=\"wp-block-list\">\n<li>With your virtual environment activated, use pip to install the latest version of Django:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">pip install django<\/pre><p>This will download and install all the dependencies and Django web framework within the virtual environment.<\/p><ol start=\"2\" class=\"wp-block-list\">\n<li>Use the following command to confirm that Django is installed and to check the version:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">django-admin --version<\/pre><div class=\"wp-block-image\">\n<figure data-wp-context='{\"imageId\":\"69e20b3c4100b\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"257\" height=\"39\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/install_django_1.png\/public\" alt=\"Screenshot of terminal window, displaying command &quot;django-admin --version&quot; and it's result &quot;5.1.1&quot;\" class=\"wp-image-116655\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/install_django_1.png\/w=257,fit=scale-down 257w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/install_django_1.png\/w=150,fit=scale-down 150w\" sizes=\"(max-width: 257px) 100vw, 257px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>This will output the current Django version installed in your environment, further confirming that the installation was successful.<\/p><p>With your VPS prepared for Django hosting, you can start building your application.<\/p><h2 class=\"wp-block-heading\" id=\"h-creating-a-new-django-project\">Creating a new Django project<\/h2><p>It&rsquo;s time to create your first Django app. In this section, you will establish the codebase foundation needed to begin developing your website.<\/p><p>Let&rsquo;s <a href=\"\/tutorials\/how-to-create-a-django-project\">create a new Django project<\/a>:<\/p><ol class=\"wp-block-list\">\n<li><strong>Navigate to your project directory<\/strong>: If you&rsquo;re not already in the directory where you want to create the project, use the <strong>cd <\/strong>command to navigate there.<\/li>\n\n\n\n<li><strong>Run the startproject command<\/strong>: Use Django&rsquo;s <strong>startproject <\/strong>command to create a new project. Replace <strong>myproject<\/strong> with the name of your project:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">django-admin startproject myproject<\/pre><p>This will create a new directory named <strong>myproject <\/strong>containing the default project structure.<\/p><ol start=\"3\" class=\"wp-block-list\">\n<li>Then, navigate to your project&rsquo;s inner folder:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">cd myproject\/myproject<\/pre><ol start=\"4\" class=\"wp-block-list\">\n<li><strong>Add your servers IP to ALLOWED_HOSTS<\/strong>: Use one of the default Ubuntu text editors (<strong>nano<\/strong> or <strong>vim<\/strong>) and open the <strong>settings.py<\/strong> file:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">vim settings.py<\/pre><p>Locate the <strong>ALLOWED_HOSTS<\/strong> setting and edit it to add your VPS IP as follows:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ALLOWED_HOSTS = ['your_vps_ip']<\/pre><p>Replace <strong>your_vps_ip<\/strong> with your actual VPS IP from the Hostinger console.<\/p><ol start=\"5\" class=\"wp-block-list\">\n<li><strong>Start the development server<\/strong>: To verify that everything is set up correctly, you can start the Django development server. Return to the parent project category and run <strong>runserver<\/strong>:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">python manage.py runserver 0.0.0.0:8000<\/pre><p>Now, open your browser and go to <a href=\"http:\/\/your_vps_ip:8000\/\"><strong>http:\/\/your_vps_ip:8000\/<\/strong><\/a><strong> <\/strong>&ndash; replace <strong>your_vps_ip<\/strong> with your actual VPS IP. If everything was done correctly, you should see the Django welcome page:<\/p><div class=\"wp-block-image\">\n<figure data-wp-context='{\"imageId\":\"69e20b3c4339c\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"521\" height=\"355\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/install_django_2.png\/public\" alt='Screenshot displaying default Django web page, containing text \"The install worked successfully! Congratulations!\" as well as a rocket launching above the text and version information below.' class=\"wp-image-116657\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/install_django_2.png\/w=521,fit=scale-down 521w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/install_django_2.png\/w=300,fit=scale-down 300w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/install_django_2.png\/w=150,fit=scale-down 150w\" sizes=\"(max-width: 521px) 100vw, 521px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>If you followed through with these steps, you successfully built and executed a default Django project on your VPS. The rest of this Django tutorial goes deeper into developing the application and understanding Django in general.<\/p><h3 class=\"wp-block-heading\" id=\"h-understanding-the-django-project-structure\">Understanding the Django project structure<\/h3><p>Running the <strong>startproject <\/strong>command creates a basic Django project structure that includes several key files and directories. Here&rsquo;s a breakdown of the structure and the purpose of each component:<\/p><div class=\"wp-block-image\">\n<figure data-wp-context='{\"imageId\":\"69e20b3c44e5d\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"257\" height=\"219\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_1.png\/public\" alt=\"Screenshot displaying default Django project structure: db.sqlite3 and manage.py files in the main myproject directory and init.py, asgi.py, settings.py, urls.py, wsgi.py files and pycache category inside the inner myproject directory\" class=\"wp-image-116659\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_1.png\/w=257,fit=scale-down 257w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_1.png\/w=150,fit=scale-down 150w\" sizes=\"(max-width: 257px) 100vw, 257px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Each of these files and directories plays a specific role in your Django project:<\/p><ol class=\"wp-block-list\">\n<li><strong>manage.py<\/strong>:<\/li>\n<\/ol><p>This is a command-line utility that helps you interact with your Django project. You use it for tasks such as running the development server, migrating databases, and managing your application.Here&rsquo;s what it looks like:<\/p><div class=\"wp-block-image\">\n<figure data-wp-context='{\"imageId\":\"69e20b3c46bbd\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"678\" height=\"442\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_2.png\/public\" alt=\"Screenshot of the default manage.py file opened in VS code editor\" class=\"wp-image-116662\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_2.png\/w=678,fit=scale-down 678w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_2.png\/w=300,fit=scale-down 300w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_2.png\/w=150,fit=scale-down 150w\" sizes=\"(max-width: 678px) 100vw, 678px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>These are its key functions:<\/p><div class=\"wp-block-image\">\n<figure data-wp-context='{\"imageId\":\"69e20b3c48659\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"590\" height=\"22\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_3.png\/public\" alt=\"Screenshot of text &quot;os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')&quot;\" class=\"wp-image-116665\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_3.png\/w=590,fit=scale-down 590w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_3.png\/w=300,fit=scale-down 300w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_3.png\/w=150,fit=scale-down 150w\" sizes=\"(max-width: 590px) 100vw, 590px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Sets the environment variable to tell Django which settings file to use.<\/p><div class=\"wp-block-image\">\n<figure data-wp-context='{\"imageId\":\"69e20b3c49fef\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"301\" height=\"18\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_4.png\/public\" alt=\"Screenshot of text &quot;os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')&quot;\" class=\"wp-image-116666\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_4.png\/w=301,fit=scale-down 301w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_4.png\/w=150,fit=scale-down 150w\" sizes=\"(max-width: 301px) 100vw, 301px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Runs various Django commands such as <strong>runserver<\/strong>, <strong>migrate<\/strong>, and others.<\/p><ol start=\"2\" class=\"wp-block-list\">\n<li><strong>myproject\/:<\/strong><\/li>\n<\/ol><p>The inner project directory that holds the core settings, configurations, and other default files for a Django project.<\/p><ol start=\"3\" class=\"wp-block-list\">\n<li><strong>__init__.py:<\/strong><\/li>\n<\/ol><p>This file marks the directory as a Python package, allowing the code to be imported as a module in Python. It&rsquo;s empty by default.<\/p><ol start=\"4\" class=\"wp-block-list\">\n<li><strong>settings.py:<\/strong><\/li>\n<\/ol><p>This is one of the most crucial files in Django. It contains all the configuration settings for your project, including database configurations, installed apps, middleware, and static file settings.<\/p><ol start=\"5\" class=\"wp-block-list\">\n<li><strong>urls.py:<\/strong><\/li>\n<\/ol><p>This file defines the URL routes for your application. It maps URLs to views that process requests and return responses.<\/p><div class=\"wp-block-image\">\n<figure data-wp-context='{\"imageId\":\"69e20b3c4bd89\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"365\" height=\"135\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_5.png\/public\" alt=\"Screenshot of a default url.py file structure\" class=\"wp-image-116667\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_5.png\/w=365,fit=scale-down 365w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_5.png\/w=300,fit=scale-down 300w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_5.png\/w=150,fit=scale-down 150w\" sizes=\"(max-width: 365px) 100vw, 365px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>As you add more functionality to your application, you&rsquo;ll extend <strong>urlpatterns<\/strong> to include the routes for your own views.<\/p><ol start=\"6\" class=\"wp-block-list\">\n<li><strong>asgi.py:<\/strong><\/li>\n<\/ol><p>This file provides an entry point for ASGI-compatible web servers to serve your project. ASGI (Asynchronous Server Gateway Interface) is the standard for asynchronous Django applications.<\/p><div class=\"wp-block-image\">\n<figure data-wp-context='{\"imageId\":\"69e20b3c4dc33\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"645\" height=\"154\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_6.png\/public\" alt=\"Screenshot of a default asgi.py file structure\" class=\"wp-image-116669\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_6.png\/w=645,fit=scale-down 645w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_6.png\/w=300,fit=scale-down 300w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_6.png\/w=150,fit=scale-down 150w\" sizes=\"(max-width: 645px) 100vw, 645px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><ol start=\"6\" class=\"wp-block-list\">\n<li><strong>wsgi.py:<\/strong><\/li>\n<\/ol><p>This file is the entry point for WSGI-compatible web servers such as Gunicorn or uWSGI to serve your project in a production environment.<\/p><div class=\"wp-block-image\">\n<figure data-wp-context='{\"imageId\":\"69e20b3c4f650\"}' data-wp-interactive=\"core\/image\" class=\"aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"647\" height=\"152\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_7.png\/public\" alt=\"The default wsgi.py file structure\" class=\"wp-image-116670\" srcset=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_7.png\/w=647,fit=scale-down 647w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_7.png\/w=300,fit=scale-down 300w, https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2024\/09\/understanding_the_project_structure_7.png\/w=150,fit=scale-down 150w\" sizes=\"(max-width: 647px) 100vw, 647px\" \/><button class=\"lightbox-trigger\" type=\"button\" aria-haspopup=\"dialog\" aria-label=\"Enlarge\" data-wp-init=\"callbacks.initTriggerButton\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-style--right=\"state.imageButtonRight\" data-wp-style--top=\"state.imageButtonTop\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\"><\/path>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure><\/div><p>Understanding the role of each file and directory will equip you to modify settings, add URLs, and manage your project&rsquo;s structure.<\/p><h2 class=\"wp-block-heading\" id=\"h-understanding-django-models-and-databases\">Understanding Django models and databases<\/h2><p>With your Django project set up and running, the next step is to dive into one of the core components of any web application: managing data. Let&rsquo;s explore <a href=\"\/tutorials\/django-user-model\">how Django handles models and databases<\/a> to power dynamic, data-driven applications.<\/p><h3 class=\"wp-block-heading\" id=\"h-creating-and-migrating-models\">Creating and migrating models<\/h3><p>In Django, <strong>models<\/strong> define the structure of your database tables. They are Python classes that map directly to database tables, allowing you to interact with your data in a convenient way. Each model class represents a table, and each model attribute represents a field in the table.<\/p><p>Django abstracts away the SQL code, making it easier to create, update, and manage databases without writing raw SQL queries.<\/p><p><strong>Creating a Model<\/strong><\/p><p>To create a model, you&rsquo;ll define a Python class inside the <strong>models.py<\/strong> file of one of your apps. Each attribute in the class corresponds to a database field, and Django will automatically handle the underlying database structure.<\/p><p>Here&rsquo;s an example of a simple model in Django:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># In your app's models.py file\nfrom django.db import models\n\nclass Book(models.Model):\n    title = models.CharField(max_length=200)\n    author = models.CharField(max_length=100)\n    published_date = models.DateField()\n    isbn = models.CharField(max_length=13, unique=True)\n\n    def __str__(self):\n        return self.title<\/pre><ul class=\"wp-block-list\">\n<li><strong>title <\/strong>and <strong>author<\/strong>: These are character fields (<strong>CharField<\/strong>) with a maximum length.<\/li>\n\n\n\n<li><strong>published_date<\/strong>: This is a date field (<strong>DateField<\/strong>).<\/li>\n\n\n\n<li><strong>isbn<\/strong>: A character field with a unique constraint.<\/li>\n<\/ul><p>The <strong>__str__()<\/strong> method ensures that when you query for a book, it will return the book&rsquo;s title as a string representation.<\/p><p><strong>Adding the model to the database<\/strong><\/p><p>Once you&rsquo;ve created your model, Django needs to translate it into a database table. This is done through <strong>migrations<\/strong>, which are files that Django uses to keep track of changes in your models.<\/p><ol class=\"wp-block-list\">\n<li><strong>Create a migration<\/strong>: To create the migration file for your new model, run the following:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">python manage.py makemigrations<\/pre><p>Django will analyze the changes in your <strong>models.py<\/strong> file and generate a migration file that describes those changes in SQL-like statements.<\/p><p>You&rsquo;ll see output similar to this:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Migrations for 'myapp':\n  myapp\/migrations\/0001_initial.py\n    - Create model Book<\/pre><ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Apply the migration<\/strong>: After generating the migration, apply it to the database with the migrate command:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">python manage.py migrate<\/pre><p>This will create the necessary tables in your database. Now, the <strong>Book <\/strong>model is represented by a corresponding <strong>Book <\/strong>table in your database, and you can start adding, querying, and managing data.<\/p><h3 class=\"wp-block-heading\" id=\"h-setting-up-the-database\">Setting up the database<\/h3><p>Django supports multiple databases, allowing you to choose the best one for your project. The default database in Django is <strong>SQLite<\/strong>, which is lightweight and easy to set up, making it ideal for development and small projects.<\/p><p>However, for production environments, more robust databases like <strong>PostgreSQL<\/strong>, <strong>MySQL<\/strong>, or <strong>MariaDB<\/strong> are recommended due to their scalability and performance.<\/p><p>Django provides built-in support for all these databases. Let&rsquo;s start by setting up the default <strong>SQLite<\/strong> database.<\/p><p><strong>Setting up the default SQLite database<\/strong><\/p><p>By default, Django is configured to use SQLite, which comes pre-installed with Python, so no additional setup is needed. Here&rsquo;s how to ensure your project is ready to use SQLite:<\/p><ol class=\"wp-block-list\">\n<li>Navigate to your project&rsquo;s<strong> settings.py<\/strong> file, which is located in the project folder (<strong>myproject&rarr;myproject&rarr;settings.py<\/strong>).<\/li>\n\n\n\n<li>Go to the <strong>DATABASES<\/strong> section of <strong>settings.py<\/strong>, where Django will have already configured SQLite as the default database. Here&rsquo;s what it looks like:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">DATABASES = {\n    'default': {\n        'ENGINE': 'django.db.backends.sqlite3',\n        'NAME': BASE_DIR \/ 'db.sqlite3',\n    }\n}<\/pre><ul class=\"wp-block-list\">\n<li><strong>ENGINE<\/strong>: Specifies the database back-end (in this case, SQLite).<\/li>\n\n\n\n<li><strong>NAME<\/strong>: The path to the SQLite database file (<strong>db.sqlite3<\/strong>). Django automatically creates this file when you run the initial migration.<\/li>\n<\/ul><ol start=\"3\" class=\"wp-block-list\">\n<li>After confirming the database settings, you need to apply the initial migrations to set up the default tables (like users and sessions). Run the following command:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">python manage.py migrate<\/pre><p>This command will create the <strong>db.sqlite3<\/strong> file in the root of your project directory and set up all the necessary tables for your application to run.<\/p><ol start=\"4\" class=\"wp-block-list\">\n<li>Once the migrations are complete, check that the<strong> db.sqlite3<\/strong> file was created in your project folder. This file stores your database locally and will grow as you add more data.<\/li>\n<\/ol><h3 class=\"wp-block-heading\" id=\"h-database-integration\">Database integration<\/h3><p>Once you&rsquo;ve set up the default SQLite database for development, you may need to integrate a more robust database management system (DBMS) as your project grows. Django supports multiple DBMSes, including <strong>PostgreSQL<\/strong>, <strong>MySQL<\/strong>, <strong>MariaDB<\/strong>, and <strong>Oracle<\/strong>, each with its own strengths and integration process.<\/p><p>Let&rsquo;s overview each of the options:<\/p><ul class=\"wp-block-list\">\n<li><strong>SQLite<\/strong>: This is the default database in Django and is ideal for <strong>development<\/strong> and small projects. It is lightweight, file-based, and requires no setup beyond what Django provides out of the box. However, it&rsquo;s not suitable for production environments because it lacks advanced features like concurrent writes, scalability, and robustness under heavy traffic.<br><br><strong>Setup<\/strong>: SQLite requires no additional setup in Django; it is ready to use out of the box.<br><br><strong>Configuration<\/strong>: Django is preconfigured to use SQLite with the following settings in settings.py:<\/li>\n<\/ul><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">DATABASES = {\n    'default': {\n        'ENGINE': 'django.db.backends.sqlite3',\n        'NAME': BASE_DIR \/ 'db.sqlite3',\n    }\n}<\/pre><p>Notice that SQlite only requires 2 parameters &ndash; <strong>ENGINE <\/strong>and <strong> NAME<\/strong>.<\/p><ul class=\"wp-block-list\">\n<li><strong>PostgreSQL<\/strong>: A powerful, open-source database with advanced features such as support for complex queries, data types like JSON, and full-text search. It&rsquo;s highly recommended for <strong>production<\/strong> Django applications due to its scalability and feature set. PostgreSQL is known for adhering strictly to SQL standards and being reliable for complex and large-scale applications.<br><br><strong>Setup<\/strong>: PostgreSQL requires installing the <strong>psycopg2 <\/strong>package, which acts as the adapter between Django and the PostgreSQL database.<br><br><strong>Configuration<\/strong>: Besides default <strong>ENGINE<\/strong> and <strong>NAME<\/strong> parameters for SQLite, PostgreSQL also requires <strong>USER<\/strong>, <strong>PASSWORD<\/strong>, <strong>HOST, <\/strong>and <strong>PORT<\/strong>. All are configured in the <strong>settings.py<\/strong> file, in the <strong>DATABASES<\/strong> section:<\/li>\n<\/ul><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">DATABASES = {\n    'default': {\n        'ENGINE': 'django.db.backends.postgresql',\n        'NAME': 'mydatabase',\n        'USER': 'mydatabaseuser',\n        'PASSWORD': 'mypassword',\n        'HOST': 'localhost',\n        'PORT': '5432',\n    }\n}<\/pre><p><strong>Differences<\/strong>: Unlike SQLite, PostgreSQL is a fully-featured database that supports multiple concurrent users, advanced querying, and transactions. You&rsquo;ll need to <a href=\"\/tutorials\/how-to-install-postgresql-on-ubuntu\">install PostgreSQL on your server<\/a>, create a database and user, and handle more complex configurations.<\/p><ul class=\"wp-block-list\">\n<li><strong>MySQL \/ MariaDB<\/strong>: Both are fast and reliable relational databases that are widely used in web development. MySQL is known for its speed, while MariaDB, a fork of MySQL, focuses more on community-driven development and is fully compatible with MySQL. These databases are excellent for <strong>high-traffic web applications<\/strong> and are often favored for their performance.<br><br><strong>Setup<\/strong>: MySQL and MariaDB both use the <strong>mysqlclient <\/strong>package to interface with Django.<br><br><strong>Configuration:<\/strong> Both use the same parameters as PostgreSQL, configured in the <strong>settings.py<\/strong> file, in the <strong>DATABASES<\/strong> section:<\/li>\n<\/ul><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">DATABASES = {\n    'default': {\n        'ENGINE': 'django.db.backends.mysql',  # or 'django.db.backends.mariadb' for MariaDB\n        'NAME': 'mydatabase',\n        'USER': 'mydatabaseuser',\n        'PASSWORD': 'mypassword',\n        'HOST': 'localhost',\n        'PORT': '3306',\n    }\n}<\/pre><p><strong>Differences: <\/strong>MySQL and MariaDB are known for their performance with large datasets and high-traffic web applications. They support multiple storage engines, fast reads, and can handle millions of queries quickly.<\/p><ul class=\"wp-block-list\">\n<li><strong>Oracle \/ Microsoft SQL Server<\/strong>: These enterprise-grade databases offer significant power, especially in large web applications. However, their setup can be more complex, and they are generally only used in specific <strong>enterprise environments<\/strong> where the business already uses Oracle or SQL Server for other software.<br><br><strong>Setup<\/strong>: Both require additional drivers for integration with Django, such as <strong>cx_Oracle<\/strong> for Oracle or <strong>pyodbc <\/strong>for SQL Server. These databases are typically used in enterprise environments where other business software relies on these systems.<br><br><strong>Configuration<\/strong>: Each of these systems requires more complex setup processes, including server installation, setting up drivers, and configuring database credentials in the <strong>settings.py<\/strong>, much like the previous options.<br><br><strong>Differences<\/strong>: Oracle and SQL Server offer enterprise-grade features like advanced transaction handling, optimized performance, and integration with large-scale systems. Their setup is more complex and is often handled by specialized database administrators.<\/li>\n<\/ul><p>So, which one should you choose? Let&rsquo;s make it simple and straightforward:<\/p><ul class=\"wp-block-list\">\n<li><strong>Development and Testing<\/strong>: Stick with SQLite. It&rsquo;s simple, needs no setup, and is ideal for local testing.<\/li>\n\n\n\n<li><strong>Small-Scale Production<\/strong>: For smaller, low-traffic web applications, you might choose MySQL or MariaDB, as they provide better performance than SQLite and have an easier learning curve than PostgreSQL.<\/li>\n\n\n\n<li><strong>Large-Scale Production<\/strong>: PostgreSQL is the most recommended for Django projects that require scalability, security, and advanced features.<\/li>\n\n\n\n<li><strong>Enterprise Environments<\/strong>: If you work in an enterprise setting that uses Oracle or SQL Server for other applications, these databases may be the best choice due to integration requirements.<\/li>\n<\/ul><p><strong>Setting Up PostgreSQL with Django<\/strong><\/p><p>In this section, we will walk through the process of integrating <strong>PostgreSQL<\/strong> with Django, as it is one of the most commonly used databases for production applications.<\/p><ol class=\"wp-block-list\">\n<li><strong>Install PostgreSQL: <\/strong>To integrate PostgreSQL with Django, you first need to install PostgreSQL on your system:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo apt update<\/pre><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo apt install postgresql postgresql-contrib<\/pre><ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Install PostgreSQL adapter for Django: <\/strong>Django uses the <strong>psycopg2 <\/strong>package to interact with PostgreSQL. Install it using <strong>pip<\/strong>:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">pip install psycopg2<\/pre><ol start=\"3\" class=\"wp-block-list\">\n<li>Switch to the PostgreSQL user:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo -u postgres psql<\/pre><ol start=\"4\" class=\"wp-block-list\">\n<li>Create a new database:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">CREATE DATABASE mydatabase;<\/pre><ol start=\"5\" class=\"wp-block-list\">\n<li>Create a user with a password:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">CREATE USER mydatabaseuser WITH PASSWORD 'mypassword';<\/pre><ol start=\"6\" class=\"wp-block-list\">\n<li>Grant <strong>mydatabaseuser <\/strong>all privileges on the database:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">GRANT ALL PRIVILEGES ON DATABASE mydatabase TO mydatabaseuser;<\/pre><ol start=\"7\" class=\"wp-block-list\">\n<li>Exit the PostgreSQL shell:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\\q<\/pre><ol start=\"8\" class=\"wp-block-list\">\n<li><strong>Configure Django to use PostgreSQL:<\/strong> Open your <strong>settings.py<\/strong> file and locate the <strong>DATABASES<\/strong> section. Modify it for PostgreSQL as follows:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">DATABASES = {\n    'default': {\n        'ENGINE': 'django.db.backends.postgresql',\n        'NAME': 'mydatabase',\n        'USER': 'mydatabaseuser',\n        'PASSWORD': 'mypassword',\n        'HOST': 'localhost',  # Use '127.0.0.1' if 'localhost' doesn't work\n        'PORT': '5432',       # Default PostgreSQL port\n    }\n}<\/pre><p>The actual <strong>PASSWORD<\/strong> and <strong>USER<\/strong> values should match the ones you set in <strong>Step 5<\/strong>.<\/p><ol start=\"9\" class=\"wp-block-list\">\n<li><strong>Apply migrations:<\/strong> Now that your database is configured, you need to apply your project&rsquo;s migrations to set up the necessary tables in PostgreSQL:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">python manage.py migrate<\/pre><p>This command will create the required tables in your PostgreSQL database.<\/p><ol start=\"10\" class=\"wp-block-list\">\n<li><strong>Test the connection:<\/strong> Finally, run the Django development server using the <strong>runserver <\/strong>command, to verify that the PostgreSQL integration is successful:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">python manage.py runserver<\/pre><p>Open <strong>http:\/\/127.0.0.1:8000\/<\/strong> in your browser. If the Django welcome page appears without errors, your database connection is working correctly.<\/p><p>With your PostgreSQL database fully integrated, Django is now ready to handle larger, more complex datasets, making your project scalable and production-ready.<\/p><h2 class=\"wp-block-heading\" id=\"h-building-views-and-templates\">Building views and templates<\/h2><p>With the database and models set up to manage your application&rsquo;s data, the next step is to display this information to users and create interactive interfaces.<\/p><p>This is where <strong>views <\/strong>and <strong>templates<\/strong> come into play, allowing you to define the logic and structure behind the web pages users will interact with.<\/p><h3 class=\"wp-block-heading\" id=\"h-understanding-views\">Understanding views<\/h3><p><a href=\"\/tutorials\/building-django-views\">Django views<\/a><strong> <\/strong>are an essential component that defines the logic behind what a user sees when they interact with your application.<\/p><p>Simply put, a view takes a web request, processes it, and returns a response, typically in the form of a rendered HTML page. Views bridge your database and the user interface with the use of models and templates.<\/p><p>There are two primary types of views in Django: <strong>Function-Based Views (FBVs)<\/strong> and <strong>Class-Based Views (CBVs)<\/strong>. Both serve the same purpose but offer different ways of organizing code.<\/p><p><strong>Function-Based Views (FBVs)<\/strong><\/p><p>Function-Based Views are straightforward Python functions that accept a request object and return a response. They&rsquo;re often used for simpler use cases or where you need more control over the flow of the logic.<\/p><p>Here&rsquo;s an example of a simple FBV that renders an HTML template:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.shortcuts import render\n\n# Function-based view\ndef homepage(request):\n    return render(request, 'homepage.html')<\/pre><p>In this example:<\/p><ul class=\"wp-block-list\">\n<li><strong>request<\/strong>: The HTTP request object sent by the user&rsquo;s browser.<\/li>\n\n\n\n<li><strong>render<\/strong>: Combines the template <strong>homepage.html<\/strong> with any provided context data and returns an HTTP response.<\/li>\n<\/ul><p>FBVs are easy to understand and implement, but as views become more complex, such as involving forms or authentication, they can become harder to maintain.<\/p><p><strong>Class-Based Views (CBVs)<\/strong><\/p><p>Class-Based Views, on the other hand, allow you to structure views more efficiently by using object-oriented programming principles. CBVs are more flexible and reusable since they are based on Python classes.<\/p><p>Django provides built-in generic views, like <strong>ListView<\/strong> and <strong>DetailView<\/strong>, that handle common use cases. These views allow you to focus more on customizing them rather than rewriting repetitive logic.<\/p><p>Here&rsquo;s an example of a CBV that performs the same function as the previous FBV:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.views.generic import TemplateView\n\n# Class-based view\nclass HomePageView(TemplateView):\n    template_name = 'homepage.html'<\/pre><p>In this example:<\/p><ul class=\"wp-block-list\">\n<li><strong>TemplateView<\/strong>: A built-in generic view that renders a template.<\/li>\n\n\n\n<li><strong>template_name<\/strong>: Specifies the template file to render, just like in the FBV example.<\/li>\n<\/ul><p>To use this CBV in the URL configuration, you&rsquo;ll need to include the <strong>.as_view()<\/strong> method when adding it to <strong>urls.py<\/strong>:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.urls import path\nfrom .views import HomePageView\n\nurlpatterns = [\n    path('', HomePageView.as_view(), name='home'),\n]<\/pre><p><strong>When to Use FBVs vs. CBVs<\/strong><\/p><ul class=\"wp-block-list\">\n<li><strong>Use FBVs<\/strong> when you need simplicity and full control over your view logic. They are often more intuitive for small views or custom logic that doesn&rsquo;t fit into Django&rsquo;s predefined view patterns.<\/li>\n\n\n\n<li><strong>Use CBVs<\/strong> when you want to follow <strong>DRY (Don&rsquo;t Repeat Yourself)<\/strong> principles and reuse existing logic. CBVs are ideal when your views grow in complexity, such as when handling forms, paginated data, or standard CRUD operations.<\/li>\n<\/ul><p>Both FBVs and CBVs are integral to Django, and choosing between them depends on your project&rsquo;s requirements and your personal preference.<\/p><h3 class=\"wp-block-heading\" id=\"h-working-with-templates\">Working with templates<\/h3><p>The <a href=\"\/working-with-django-templates\">template<strong> <\/strong>system in Django<\/a> is designed to separate the presentation of data from the underlying logic. Templates are essentially HTML files that contain dynamic content, allowing you to display data passed from your views. The Django Template Language (DTL) provides placeholders and logic, like loops and conditionals, to insert dynamic data into HTML.<\/p><p>Templates play a crucial role in defining the look and feel of your web pages while maintaining a clean separation of concerns between the logic, which is handled by views, and the user interface.<\/p><p><strong>Creating a Template<\/strong><\/p><p>To create a template in Django, you need to create an HTML file inside a <strong>templates <\/strong>directory. The directory structure might look like this:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">myproject\/\n&#9474;\n&#9500;&#9472;&#9472; myapp\/\n&#9474;   &#9500;&#9472;&#9472; templates\/\n&#9474;   &#9474;   &#9492;&#9472;&#9472; myapp\/\n&#9474;   &#9474;       &#9492;&#9472;&#9472; homepage.html\n&#9474;   &#9492;&#9472;&#9472; views.py\n&#9474;\n&#9492;&#9472;&#9472; manage.py\n<\/pre><p>In this structure, Django automatically looks for templates in the <strong>templates <\/strong>directory of your app. You can further organize templates inside app-specific folders (like <strong>myapp\/homepage.html<\/strong>), ensuring that each app has its own templates.<\/p><p>Here&rsquo;s an example of a simple template (<strong>homepage.html<\/strong>):<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n    &lt;title&gt;Home&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h1&gt;Welcome to {{ site_name }}&lt;\/h1&gt;\n    &lt;p&gt;{{ message }}&lt;\/p&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/pre><p>In this template, <strong>{{ site_name }}<\/strong> and <strong>{{ message }}<\/strong> are placeholders that will be filled with dynamic data passed from the view.<\/p><p><strong>Rendering a template in a view<\/strong><\/p><p>To render a template, you need to pass it to the view using Django&rsquo;s <strong>render()<\/strong> function. Here&rsquo;s an example of how to render the <strong>homepage.html<\/strong> template with some context data in a <strong>function-based view (FBV)<\/strong>:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.shortcuts import render\n\ndef homepage(request):\n    context = {\n        'site_name': 'My Django Website',\n        'message': 'This is the homepage content!'\n    }\n    return render(request, 'myapp\/homepage.html', context)<\/pre><p>In this example:<\/p><ul class=\"wp-block-list\">\n<li><strong>render()<\/strong>: Combines the template (<strong>homepage.html<\/strong>) with the context data.<\/li>\n\n\n\n<li><strong>context<\/strong>: A dictionary containing the data (<strong>site_name<\/strong> and <strong>message<\/strong>) to be inserted into the template.<\/li>\n<\/ul><p>When a user visits this page, the placeholders <strong>{{ site_name }}<\/strong> and <strong>{{ message }}<\/strong> in the template will be replaced by &ldquo;My Django Website&rdquo; and &ldquo;This is the homepage content!&rdquo; respectively.<\/p><p><strong>Template tags and filters<\/strong><\/p><p>Django templates also support <strong>template tags<\/strong> and <strong>filters<\/strong>, which allow you to add dynamic content and logic inside your HTML files.<\/p><ul class=\"wp-block-list\">\n<li><strong>Template Tags<\/strong>: Perform logic inside templates, such as loops and conditionals.For example, an <strong>if <\/strong>condition:<\/li>\n<\/ul><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{% if user.is_authenticated %}\n    &lt;p&gt;Welcome back, {{ user.username }}!&lt;\/p&gt;\n{% else %}\n    &lt;p&gt;Hello, Guest!&lt;\/p&gt;\n{% endif %}<\/pre><ul class=\"wp-block-list\">\n<li><strong>Template Filters<\/strong>: Modify variables for display purposes.For example, formatting dates with a filter:<\/li>\n<\/ul><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;p&gt;Published on {{ article.published_date|date:\"F j, Y\" }}&lt;\/p&gt;<\/pre><p><strong>Extending templates<\/strong><\/p><p>Django supports template inheritance, allowing you to create base templates that other templates can extend. This is especially useful for maintaining a consistent layout across multiple pages, such as a common header and footer.<\/p><ol class=\"wp-block-list\">\n<li>Create a base template (<strong>base.html<\/strong>):<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n    &lt;title&gt;{% block title %}My Site{% endblock %}&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;header&gt;\n        &lt;h1&gt;Site Header&lt;\/h1&gt;\n    &lt;\/header&gt;\n\n    &lt;main&gt;\n        {% block content %}\n        &lt;!-- Page-specific content goes here --&gt;\n        {% endblock %}\n    &lt;\/main&gt;\n\n    &lt;footer&gt;\n        &lt;p&gt;Footer Content&lt;\/p&gt;\n    &lt;\/footer&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/pre><ol start=\"2\" class=\"wp-block-list\">\n<li>Extend the base template in a child template (<strong>homepage.html<\/strong>):<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{% extends 'base.html' %}\n\n{% block title %}Home Page{% endblock %}\n\n{% block content %}\n    &lt;h2&gt;Welcome to the homepage!&lt;\/h2&gt;\n    &lt;p&gt;This is the homepage content.&lt;\/p&gt;\n{% endblock %}<\/pre><p>By extending the base template, you can reuse the header and footer across different pages, maintaining a consistent layout and avoiding repetition.<\/p><p><strong>Using static files in templates<\/strong><\/p><p>Templates also allow you to reference static files (like CSS, JavaScript, or images) using the <strong>{% static %}<\/strong> template tag. For example, to include a CSS file:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;link rel=\"stylesheet\" type=\"text\/css\" href=\"{% static 'css\/style.css' %}\"&gt;<\/pre><p>Make sure you&rsquo;ve set up your static file directories correctly in <strong>settings.py<\/strong>:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">STATIC_URL = '\/static\/'<\/pre><p>By effectively using Django&rsquo;s template system, you can create dynamic, data-driven web pages and maintain a clean separation between logic and presentation.<\/p><h2 class=\"wp-block-heading\" id=\"h-working-with-url-patterns\">Working with URL patterns<\/h2><p><a href=\"\/tutorials\/django-url-patterns\">Django&rsquo;s URL dispatcher<\/a> relies on regular expressions or path converters to match incoming URL requests with specific views. These URL patterns are defined in<strong> urls.py<\/strong>, and Django uses this configuration to determine which view should handle a particular request.<\/p><p>Each Django project typically has two levels of URL configuration:<\/p><ol class=\"wp-block-list\">\n<li><strong>Project-level URLs<\/strong>: Defined in the root<strong> urls.py<\/strong> file (found in the project&rsquo;s main directory), this file contains the overall structure of the project&rsquo;s URL routing.<\/li>\n\n\n\n<li><strong>App-level URLs<\/strong>: Each app within your project can have its own <strong>urls.py<\/strong> file, allowing for modular URL management. These app-level URLs are then linked to the project-level URLs.<\/li>\n<\/ol><p><strong>Basic URL configuration<\/strong><\/p><p>Let&rsquo;s look at how a simple project might set up URL patterns:<\/p><ol class=\"wp-block-list\">\n<li>Project-Level URLs (<strong>myproject&rarr;urls.py<\/strong>)<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.contrib import admin\nfrom django.urls import path, include\n\nurlpatterns = [\n    path('admin\/', admin.site.urls),  # Admin site\n    path('', include('myapp.urls')),  # Include app-level URLs for \"myapp\"\n]<\/pre><ul class=\"wp-block-list\">\n<li><strong>path()<\/strong>: Django&rsquo;s function for defining URL patterns.<\/li>\n\n\n\n<li><strong>admin.site.urls<\/strong>: Handles all admin-related requests.<\/li>\n\n\n\n<li><strong>include()<\/strong>: Used to include app-level URLs (from myapp.urls) in the main project configuration.<\/li>\n<\/ul><ol start=\"2\" class=\"wp-block-list\">\n<li>App-Level URLs (<strong>myproject&rarr;myapp&rarr;urls.py<\/strong>)<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.urls import path\nfrom . import views\n\nurlpatterns = [\n    path('', views.homepage, name='home'),  # Maps the root URL to the homepage view\n    path('about\/', views.about, name='about'),  # Maps \"\/about\/\" to the about view\n]<\/pre><ul class=\"wp-block-list\">\n<li>The <strong>root URL<\/strong> (represented by &lsquo; &lsquo;) is mapped to the homepage view.<\/li>\n\n\n\n<li>The<strong> \/about\/ URL<\/strong> is mapped to the <strong>about <\/strong>view.<\/li>\n<\/ul><p><strong>URL routing with function-based views (FBVs)<\/strong><\/p><p>Here&rsquo;s how the corresponding views might look in <strong>views.py<\/strong> for the above URL configuration:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.shortcuts import render\n\ndef homepage(request):\n    return render(request, 'homepage.html')\n\ndef about(request):\n    return render(request, 'about.html')<\/pre><p>This setup links the <strong>homepage <\/strong>and <strong>about <\/strong>URLs to their respective views, ensuring that when a user visits<strong> http:\/\/example.com\/<\/strong> or<strong> http:\/\/example.com\/about\/<\/strong>, the correct template is rendered.<\/p><p><strong>URL routing with class-based views (CBVs)<\/strong><\/p><p>You can also map URLs to class-based views (CBVs), which are handled slightly differently. Here&rsquo;s an example of a CBV URL mapping:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.urls import path\nfrom .views import HomePageView, AboutPageView\n\nurlpatterns = [\n    path('', HomePageView.as_view(), name='home'),\n    path('about\/', AboutPageView.as_view(), name='about'),\n]<\/pre><p>And the corresponding class-based views in <strong>views.py<\/strong>:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.views.generic import TemplateView\n\nclass HomePageView(TemplateView):\n    template_name = 'homepage.html'\n\nclass AboutPageView(TemplateView):\n    template_name = 'about.html'<\/pre><p>In this case, the <strong>.as_view()<\/strong> method is used to link the class-based views to the URL patterns.<\/p><p><strong>URL parameters and dynamic routing<\/strong><\/p><p>Django also allows you to capture URL parameters and pass them to views, which is useful for dynamic URL mapping for things like blog posts or product pages.<\/p><p>Here&rsquo;s an example where the URL captures an integer parameter:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.urls import path\nfrom . import views\n\nurlpatterns = [\n    path('article\/&lt;int:id&gt;\/', views.article_detail, name='article_detail'),\n]<\/pre><p>In this case, <strong>&lt;int:id&gt;<\/strong> captures an integer from the URL and passes it to the <strong>article_detail <\/strong>view as an argument:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def article_detail(request, id):\n    # Fetch the article using the provided ID\n    article = get_object_or_404(Article, pk=id)\n    return render(request, 'article_detail.html', {'article': article})<\/pre><p>If a user visits <strong>http:\/\/example.com\/article\/5\/<\/strong>, Django will pass <strong>5<\/strong> as the<strong> id<\/strong> argument to the <strong>article_detail<\/strong> view, allowing you to retrieve and display the specific article<\/p><p><strong>Named URL patterns<\/strong><\/p><p>It&rsquo;s a good practice to <strong>name <\/strong>your URL patterns. This allows you to reference URLs by name in your templates and views rather than having to hard-code them.<\/p><p>In the<strong> urls.py<\/strong> example above, each URL has a name argument:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">path('about\/', views.about, name='about')<\/pre><p>In your templates, you can then use the <strong>{% url %}<\/strong> template tag to reference these named URLs:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;a href=\"{% url 'about' %}\"&gt;About Us&lt;\/a&gt;<\/pre><p>This way, if the <strong>about <\/strong>URL ever changes, you only need to update it in the URL configuration rather than in every template.<\/p><p>By configuring and working with Django&rsquo;s URL patterns, you can efficiently map different URLs to their respective views. This flexibility allows you to handle both simple static pages and more complex, dynamic content that&rsquo;s tailored to user input.<\/p><h2 class=\"wp-block-heading\" id=\"h-managing-static-files-in-django\">Managing static files in Django<\/h2><p>We&rsquo;ve set up views, templates, and URL patterns. Now, to build a fully functional Django application, we need to start <a href=\"\/tutorials\/django-static-files\">handling <strong>static files<\/strong><\/a>, such as CSS, JavaScript, and images.<\/p><p>Luckily, Django provides a simple and efficient way to manage static files, ensuring they are properly served and organized during development and deployment.<\/p><p><strong>Setting Up static files in Django<\/strong><\/p><p>To manage static files in Django, you need to configure your project to know where to look for and serve them.<\/p><p>Define the Static URL and Directory in <strong>settings.py<\/strong>:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># settings.py\nSTATIC_URL = '\/static\/'\nSTATICFILES_DIRS = [\n    BASE_DIR \/ \"static\",  # Optional: Add this if you want to store static files in a 'static' folder within your project\n]<\/pre><ul class=\"wp-block-list\">\n<li><strong>STATIC_URL<\/strong>: Defines the URL prefix Django will use when serving static files.<\/li>\n\n\n\n<li><strong>STATICFILES_DIRS<\/strong>: Specifies additional directories where Django will look for static files during development.<\/li>\n<\/ul><p>By default, Django will also look for static files inside each app&rsquo;s <strong>static <\/strong>directory. For example, if you have an app named <strong>myapp<\/strong>, you can create a folder structure like this:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">myapp\/\n&#9474;\n&#9500;&#9472;&#9472; static\/\n&#9474;   &#9492;&#9472;&#9472; myapp\/\n&#9474;       &#9492;&#9472;&#9472; style.css\n&#9492;&#9472;&#9472; views.py<\/pre><p>Django will automatically recognize and serve these files during development.<\/p><p><strong>Using static files in templates<\/strong><\/p><p>To use static files in your templates, you must first load Django&rsquo;s <strong>{% static %}<\/strong> template tag. Then, you can reference your static files by their relative paths:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n    &lt;title&gt;Home Page&lt;\/title&gt;\n    {% load static %}\n    &lt;link rel=\"stylesheet\" href=\"{% static 'myapp\/style.css' %}\"&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h1&gt;Welcome to My Django App&lt;\/h1&gt;\n    &lt;img src=\"{% static 'myapp\/images\/logo.png' %}\" alt=\"Logo\"&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/pre><p>In this example:<\/p><ul class=\"wp-block-list\">\n<li><strong>{% load static %}<\/strong>: Loads the static files template tag.<\/li>\n\n\n\n<li><strong>{% static &lsquo;myapp\/style.css&rsquo; %}<\/strong>: Resolves the path to the style.css file in the static\/myapp directory.<\/li>\n\n\n\n<li><strong>{% static &lsquo;myapp\/images\/logo.png&rsquo; %}<\/strong>: Resolves the path to an image file.<\/li>\n<\/ul><p><strong>Collecting static files for deployment<\/strong><\/p><p>During development, Django serves static files automatically when <strong>DEBUG = True<\/strong>. However, in production, Django does not serve static files directly. Instead, you need to collect all static files from various locations and store them in a single directory.<\/p><p>To do this, Django provides the <strong>collectstatic <\/strong>management command:<\/p><ol class=\"wp-block-list\">\n<li>Make sure <strong>django.contrib.staticfiles<\/strong> is included in the<strong> INSTALLED_APPS <\/strong>setting:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">INSTALLED_APPS = [\n    # Other installed apps\n    'django.contrib.staticfiles',\n]<\/pre><ol start=\"2\" class=\"wp-block-list\">\n<li>Configure the Static Root Directory in <strong>settings.py<\/strong>:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">STATIC_ROOT = BASE_DIR \/ 'staticfiles'<\/pre><p><strong>STATIC_ROOT<\/strong>: Defines the directory where Django will collect static files for deployment.<\/p><ol start=\"3\" class=\"wp-block-list\">\n<li>Run the collectstatic command:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">python manage.py collectstatic<\/pre><p>This command collects all static files from each app&rsquo;s <strong>static <\/strong>directory and any additional locations specified in <strong>STATICFILES_DIRS<\/strong>, and then stores them in the <strong>STATIC_ROOT<\/strong> directory.<\/p><p><strong>Serving static files in production<\/strong><\/p><p>In a production environment, you typically use a web server (like <strong>Nginx <\/strong>or <strong>Apache<\/strong>) to serve static files. Django recommends configuring your web server to serve static content efficiently, reducing the load on your Django application.<\/p><p>Here&rsquo;s how you might configure static file serving in an Nginx setup:<\/p><ol class=\"wp-block-list\">\n<li>Nginx Configuration for Static Files:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"nginx\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">server {\n    listen 80;\n    server_name yourdomain.com;\n\n    location \/static\/ {\n        alias \/path\/to\/your\/project\/staticfiles\/;  # The path to STATIC_ROOT\n    }\n\n    location \/ {\n        proxy_pass http:\/\/127.0.0.1:8000;  # Pass requests to Django app\n    }\n}<\/pre><p>In this configuration, Nginx serves static files directly from the<strong> \/static\/<\/strong> directory, while forwarding all other requests to the Django application.<\/p><p>By properly managing static files in Django, you ensure that your application not only looks good with styles and images but also performs efficiently when deployed.<\/p><h2 class=\"wp-block-heading\" id=\"h-implementing-user-authentication-and-authorization\">Implementing user authentication and authorization<\/h2><p>As we continue building more dynamic and complex web applications, the need to manage users, secure content, and control access becomes critical.<\/p><p><a href=\"\/tutorials\/django-user-model\">Django provides a built-in authentication system<\/a> that makes it easy to handle user login, logout, registration, and permissions. This allows a Django developer to efficiently manage both user authentication and authorization.<\/p><h3 class=\"wp-block-heading\" id=\"h-user-authentication\">User Authentication<\/h3><p>Django&rsquo;s built-in authentication system simplifies user management with features like login, logout, password management, and registration. By default, Django offers user model functionality and authentication views that handle most of these tasks out of the box.<\/p><p><strong>Setting up user login and logout<\/strong><\/p><p>To implement login and logout functionality, you can use Django&rsquo;s built-in views found in <strong>django.contrib.auth.views<\/strong>. These views handle the authentication process and simplify the code required for these operations.<\/p><ol class=\"wp-block-list\">\n<li>Set up URLs for login and logout in your<strong> urls.py<\/strong> file:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.urls import path\nfrom django.contrib.auth import views as auth_views\n\nurlpatterns = [\n    path('login\/', auth_views.LoginView.as_view(), name='login'),\n    path('logout\/', auth_views.LogoutView.as_view(), name='logout'),\n]<\/pre><ul class=\"wp-block-list\">\n<li><strong>LoginView<\/strong>: Handles user login.<\/li>\n\n\n\n<li><strong>LogoutView<\/strong>: Logs the user out and redirects them to the specified page.<\/li>\n<\/ul><ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Create a login form template:<\/strong> You can create a simple login template (<strong>login.html<\/strong>) inside your app&rsquo;s <strong>templates <\/strong>directory:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;form method=\"post\"&gt;\n    {% csrf_token %}\n    &lt;div&gt;\n        &lt;label for=\"username\"&gt;Username:&lt;\/label&gt;\n        &lt;input type=\"text\" id=\"username\" name=\"username\" required&gt;\n    &lt;\/div&gt;\n    &lt;div&gt;\n        &lt;label for=\"password\"&gt;Password:&lt;\/label&gt;\n        &lt;input type=\"password\" id=\"password\" name=\"password\" required&gt;\n    &lt;\/div&gt;\n    &lt;button type=\"submit\"&gt;Login&lt;\/button&gt;\n&lt;\/form&gt;<\/pre><p>This template will handle user authentication when a valid username and password are submitted.<\/p><ol start=\"3\" class=\"wp-block-list\">\n<li><strong>Create logout:<\/strong> You don&rsquo;t need a separate template to log out, as Django&rsquo;s LogoutView handles it. You can simply add a logout link in your template:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;a href=\"{% url 'logout' %}\"&gt;Logout&lt;\/a&gt;<\/pre><p><strong>Creating a User Registration View<\/strong><\/p><p>Django doesn&rsquo;t provide a built-in registration view by default, but you can create one using Django&rsquo;s <strong>UserCreationForm<\/strong>:<\/p><ol class=\"wp-block-list\">\n<li>Create a registration view in <strong>views.py<\/strong>:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.shortcuts import render, redirect\nfrom django.contrib.auth.forms import UserCreationForm\nfrom django.contrib.auth import login\n\ndef register(request):\n    if request.method == 'POST':\n        form = UserCreationForm(request.POST)\n        if form.is_valid():\n            user = form.save()\n            login(request, user)  # Automatically log the user in after registration\n            return redirect('home')  # Redirect to home page after successful registration\n    else:\n        form = UserCreationForm()\n    return render(request, 'register.html', {'form': form})<\/pre><ol start=\"2\" class=\"wp-block-list\">\n<li>Set up the URL for registration in <strong>urls.py<\/strong>:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">urlpatterns = [\n    path('register\/', views.register, name='register'),\n]<\/pre><ol start=\"3\" class=\"wp-block-list\">\n<li>Create the registration form template (<strong>register.html<\/strong>):<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;form method=\"post\"&gt;\n    {% csrf_token %}\n    {{ form.as_p }}\n    &lt;button type=\"submit\"&gt;Register&lt;\/button&gt;\n&lt;\/form&gt;<\/pre><p>This registration view allows users to create an account using a simple form. After successful registration, users are automatically logged in.<\/p><h3 class=\"wp-block-heading\" id=\"h-user-authorization\">User Authorization<\/h3><p>User authorization allows controlling access to certain views and actions based on the user&rsquo;s permissions or roles. Django&rsquo;s permission system makes it easy to manage which users can access specific parts of your application.<\/p><p><strong>Restricting access with login required<\/strong><\/p><p>To restrict access to certain views, you can use Django&rsquo;s <strong>@login_required<\/strong> decorator, which ensures that only authenticated users can access a view:<\/p><ol class=\"wp-block-list\">\n<li>Using <strong>@login_required<\/strong> in views:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.contrib.auth.decorators import login_required\n\n@login_required\ndef dashboard(request):\n    return render(request, 'dashboard.html')<\/pre><p>This ensures that if a user is not logged in, they will be redirected to the login page.<\/p><ol start=\"2\" class=\"wp-block-list\">\n<li>Applying <strong>@login_required<\/strong> in URLs:Alternatively, you can apply <strong>@login_required<\/strong> directly in your <strong>urls.py<\/strong> using Django&rsquo;s <strong>LoginRequiredMixin <\/strong>for class-based views:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.contrib.auth.mixins import LoginRequiredMixin\nfrom django.views.generic import TemplateView\n\nclass DashboardView(LoginRequiredMixin, TemplateView):\n    template_name = 'dashboard.html'<\/pre><p><strong>Managing user permissions<\/strong><\/p><p>Django allows you to assign different <strong>permissions <\/strong>to users and groups, which can be used to control access to specific views or actions. Permissions can be added to user models and checked within your views.<\/p><ol class=\"wp-block-list\">\n<li><strong>Assigning permissions: <\/strong>When creating users or groups, you can assign permissions. For example, an admin might have permission to add or delete content, while regular users can only view content.<\/li>\n<\/ol><ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Checking permissions in views: <\/strong>You can check if a user has the required permissions before allowing access to certain views using the <strong>@permission_required<\/strong> decorator:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.contrib.auth.decorators import permission_required\n\n@permission_required('app.add_article')\ndef add_article(request):\n    # View code for adding an article<\/pre><p>Only users with the add_article permission will be able to access this view.<\/p><p><strong>Restricting access based on user roles<\/strong><\/p><p>Django&rsquo;s <strong>groups <\/strong>feature allows you to create roles (such as &ldquo;editor&rdquo; or &ldquo;viewer&rdquo;) and assign users to these groups. You can then check a user&rsquo;s group membership to control access.<\/p><ol class=\"wp-block-list\">\n<li><strong>Assigning users to groups:<\/strong> Groups can be created in the Django admin panel or programmatically:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.contrib.auth.models import Group, User\n\ngroup = Group.objects.get(name='editors')\nuser = User.objects.get(username='john')\nuser.groups.add(group)  # Assign the user to the 'editors' group<\/pre><ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Checking group membership in views: <\/strong>You can restrict views based on group membership:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from django.contrib.auth.decorators import user_passes_test\n\ndef is_editor(user):\n    return user.groups.filter(name='editors').exists()\n\n@user_passes_test(is_editor)\ndef editor_dashboard(request):\n    return render(request, 'editor_dashboard.html')<\/pre><p>In this example, only users who belong to the &ldquo;editors&rdquo; group can access the <strong>editor_dashboard<\/strong> view.<\/p><p>By leveraging Django&rsquo;s built-in authentication and authorization systems, you can securely manage user login, registration, and permissions, ensuring that sensitive content is protected and access is properly controlled.<\/p><h2 class=\"wp-block-heading\" id=\"h-handling-forms-in-django\">Handling forms in Django<\/h2><p>After implementing user authentication and authorization, the next crucial feature in any web page is handling user input through forms. Django provides a powerful and flexible system for creating, processing, and validating forms.<\/p><p><a href=\"\/tutorials\/django-forms\">Django&rsquo;s form-handling system<\/a> is built on Python classes that represent forms as objects. These forms can be rendered in templates, validated, and processed using just a few lines of code. Forms can either be created manually using Django&rsquo;s <strong>Form <\/strong>class or generated automatically from models using <strong>ModelForm<\/strong>.<\/p><h3 class=\"wp-block-heading\" id=\"h-creating-forms-using-django-s-form-class\">Creating forms using Django&rsquo;s form class<\/h3><p>To create a form in Django, you start by defining a form class in your <strong>forms.py<\/strong> file. This class will define the fields and validation rules.<\/p><ol class=\"wp-block-list\">\n<li><strong>Defining a form:<\/strong> Here&rsquo;s an example of a simple contact form:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># forms.py\nfrom django import forms\n\nclass ContactForm(forms.Form):\n    name = forms.CharField(max_length=100, label='Your Name')\n    email = forms.EmailField(label='Your Email')\n    message = forms.CharField(widget=forms.Textarea, label='Your Message')<\/pre><p>This form includes three fields: name, email, and message. Each field is represented by a form field class, such as <strong>CharField <\/strong>for short text, <strong>EmailField <\/strong>for emails, and <strong>Textarea <\/strong>for longer text inputs.<\/p><ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Rendering the form in a template:<\/strong> To display the form on a webpage, you need to render it inside a template. You can render the form manually or use Django&rsquo;s built-in form rendering helpers:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;form method=\"post\"&gt;\n    {% csrf_token %}\n    {{ form.as_p }}\n    &lt;button type=\"submit\"&gt;Send Message&lt;\/button&gt;\n&lt;\/form&gt;<\/pre><ul class=\"wp-block-list\">\n<li><strong>{% csrf_token %}<\/strong>: Adds a CSRF token to protect against cross-site request forgery attacks.<\/li>\n\n\n\n<li><strong>{{ form.as_p }}<\/strong>: Renders the form fields with each field wrapped in a<strong> &lt;p&gt;<\/strong> tag for easy styling.<\/li>\n<\/ul><ol start=\"3\" class=\"wp-block-list\">\n<li><strong>Handling form submissions:<\/strong> In the view that handles the form submission, you&rsquo;ll need to validate the form data and process it if the form is valid:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># views.py\nfrom django.shortcuts import render\nfrom .forms import ContactForm\n\ndef contact_view(request):\n    if request.method == 'POST':\n        form = ContactForm(request.POST)\n        if form.is_valid():\n            # Process the data, e.g., send an email or save it to the database\n            name = form.cleaned_data['name']\n            email = form.cleaned_data['email']\n            message = form.cleaned_data['message']\n            # Redirect to a success page or show a success message\n            return render(request, 'thanks.html')\n    else:\n        form = ContactForm()\n    return render(request, 'contact.html', {'form': form})<\/pre><p>In this view:<\/p><ul class=\"wp-block-list\">\n<li>If the form is submitted via a POST request, the form data is validated.<\/li>\n\n\n\n<li><strong>form.is_valid()<\/strong>: Checks whether the form data passes validation.<\/li>\n\n\n\n<li><strong>form.cleaned_data<\/strong>: Contains the validated form data that can now be processed (e.g., sending an email).<\/li>\n\n\n\n<li>If the request is not a <strong>POST<\/strong>, an empty form is displayed for the user to fill out.<\/li>\n<\/ul><h3 class=\"wp-block-heading\" id=\"h-form-validation-and-error-handling\">Form validation and error handling<\/h3><p>Django&rsquo;s forms come with built-in validation that ensures the data submitted is correct and secure. Fields such as <strong>EmailField <\/strong>automatically validate that the input is a valid email address. You can also create custom validation logic to enforce specific rules.<\/p><p><strong>Built-in validation<\/strong><\/p><p>Django automatically performs some validation checks for you:<\/p><ul class=\"wp-block-list\">\n<li><strong>Required fields<\/strong>: By default, all fields are required unless you specify required=False.<\/li>\n\n\n\n<li><strong>Field types<\/strong>: Fields like <strong>EmailField<\/strong>, <strong>IntegerField<\/strong>, and <strong>URLField <\/strong>automatically validate the type of data entered.<\/li>\n<\/ul><p><strong>Custom validation<\/strong><\/p><p>You can also define custom validation logic by overriding the<strong> clean() <\/strong>method or creating custom field validators.<\/p><ol class=\"wp-block-list\">\n<li>Adding a custom validator for the name field:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># forms.py\nfrom django import forms\nfrom django.core.exceptions import ValidationError\n\nclass ContactForm(forms.Form):\n    name = forms.CharField(max_length=100, label='Your Name')\n    email = forms.EmailField(label='Your Email')\n    message = forms.CharField(widget=forms.Textarea, label='Your Message')\n\n    def clean_name(self):\n        name = self.cleaned_data.get('name')\n        if \"spam\" in name.lower():\n            raise ValidationError(\"Invalid name: 'spam' is not allowed.\")\n        return name<\/pre><p>In this example, if the name contains the word <strong>spam<\/strong>, Django will raise a validation error.<\/p><ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Handling form errors in templates:<\/strong> You can customize how form errors are displayed in templates. Django automatically adds error messages to each field, which you can display like this:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;form method=\"post\"&gt;\n    {% csrf_token %}\n    &lt;div&gt;\n        {{ form.name.label_tag }} {{ form.name }}\n        {% if form.name.errors %}\n            &lt;div class=\"error\"&gt;{{ form.name.errors }}&lt;\/div&gt;\n        {% endif %}\n    &lt;\/div&gt;\n    &lt;div&gt;\n        {{ form.email.label_tag }} {{ form.email }}\n        {% if form.email.errors %}\n            &lt;div class=\"error\"&gt;{{ form.email.errors }}&lt;\/div&gt;\n        {% endif %}\n    &lt;\/div&gt;\n    &lt;div&gt;\n        {{ form.message.label_tag }} {{ form.message }}\n        {% if form.message.errors %}\n            &lt;div class=\"error\"&gt;{{ form.message.errors }}&lt;\/div&gt;\n        {% endif %}\n    &lt;\/div&gt;\n    &lt;button type=\"submit\"&gt;Send Message&lt;\/button&gt;\n&lt;\/form&gt;<\/pre><p>This ensures users can see relevant error messages next to the fields they need to correct.<\/p><h3 class=\"wp-block-heading\" id=\"h-creating-forms-from-models-using-modelform\">Creating forms from models using ModelForm<\/h3><p>In many cases, forms are tied to models. Django makes it easy to create forms directly from models using <strong>ModelForm<\/strong>. This saves time by automatically generating form fields based on the model&rsquo;s fields.<\/p><ol class=\"wp-block-list\">\n<li><strong>Creating a ModelForm:<\/strong> Suppose you have a <strong>Post <\/strong>model in your <strong>models.py<\/strong> file:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># models.py\nfrom django.db import models\n\nclass Post(models.Model):\n    title = models.CharField(max_length=200)\n    content = models.TextField()\n    created_at = models.DateTimeField(auto_now_add=True)<\/pre><p>You can create a form for this model as follows:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># forms.py\nfrom django import forms\nfrom .models import Post\n\nclass PostForm(forms.ModelForm):\n    class Meta:\n        model = Post\n        fields = ['title', 'content']<\/pre><ol start=\"2\" class=\"wp-block-list\">\n<li>Using the <strong>ModelForm <\/strong>in a view:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># views.py\nfrom django.shortcuts import render\nfrom .forms import PostForm\n\ndef create_post(request):\n    if request.method == 'POST':\n        form = PostForm(request.POST)\n        if form.is_valid():\n            form.save()  # Saves the form data to the database\n            return redirect('post_list')  # Redirect to a list of posts\n    else:\n        form = PostForm()\n    return render(request, 'create_post.html', {'form': form})<\/pre><p>By using <strong>ModelForm<\/strong>, Django automatically generates form fields based on the Post model&rsquo;s fields and handles saving the form to the database.<\/p><h2 class=\"wp-block-heading\" id=\"h-deploying-a-django-application\">Deploying a Django application<\/h2><p>Once your application is fully developed and tested on your local machine, the final step is deploying it to a live server so that users can access it. Deploying a Django project requires careful consideration of best practices to ensure security, scalability, and performance. In this section, we&rsquo;ll cover the essential steps for deploying your application on a VPS that every Django developer should know.<\/p><h3 class=\"wp-block-heading\" id=\"h-best-practices-for-deploying-a-django-project\">Best practices for deploying a Django project<\/h3><p>Before diving into the technical steps, it&rsquo;s important to follow some <a href=\"\/tutorials\/django-best-practices\">best practices when preparing your Django project<\/a> for deployment:<\/p><ol class=\"wp-block-list\">\n<li><strong>Use environment variables<\/strong>: Store sensitive information such as secret keys, database credentials, and API keys in environment variables instead of hard-coding them into your settings.<\/li>\n\n\n\n<li><strong>Enable debug mode off<\/strong>: Make sure to set <strong>DEBUG = False<\/strong> in your <strong>settings.py<\/strong> file before deploying your project to production. Debug mode can expose sensitive information to attackers.<\/li>\n\n\n\n<li><strong>Set allowed hosts<\/strong>: In your <strong>settings.py<\/strong>, set the <strong>ALLOWED_HOSTS<\/strong> parameter to include the domain name(s) where your app will be hosted. For example:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']<\/pre><ol start=\"4\" class=\"wp-block-list\">\n<li><strong>Secure the application<\/strong>: Consider using HTTPS for secure communication between the server and users, and use Django&rsquo;s built-in security settings such as <strong>SECURE_SSL_REDIRECT<\/strong>, <strong>CSRF_COOKIE_SECURE<\/strong>, and <strong>SESSION_COOKIE_SECURE<\/strong>.<\/li>\n\n\n\n<li><strong>Static files handling<\/strong>: Ensure static files like CSS and JavaScript are properly collected and served. Django provides the <strong>collectstatic <\/strong>command to handle this.<\/li>\n\n\n\n<li><strong>Database configuration<\/strong>: Ensure the database is properly configured, and avoid using SQLite for production. Use a more robust database like PostgreSQL or MySQL.<\/li>\n<\/ol><h3 class=\"wp-block-heading\" id=\"h-deploying-django-on-a-vps\">Deploying Django on a VPS<\/h3><p>Now that you&rsquo;ve learned the best practices for preparing a Django project, it&rsquo;s time to deploy it to a Virtual Private Server (VPS). In this section, we&rsquo;ll guide you through the steps to set up your server, configure necessary services, and get your Django application live and accessible to users.<\/p><p><strong>Creating a Python requirements.txt file<\/strong><\/p><p>A <strong>requirements.txt<\/strong> file lists all the Python dependencies your Django project needs to run. This file allows you to install all required packages with a single command.<\/p><p>Make sure you&rsquo;re in your project&rsquo;s main directory, where you have the <strong>manage.py<\/strong> file, and ensure that your virtual environment is active.<\/p><p>Then, generate the <strong>requirements.txt<\/strong> file with the following command:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">pip3 freeze &gt; requirements.txt<\/pre><p>This command will create a <strong>requirements.txt<\/strong> file in your present directory with all installed packages and their versions that you have in your current virtual environment.<\/p><p>Afterward, open the <strong>requirements.txt<\/strong> and ensure all the dependencies necessary to run your project are listed.<\/p><p><strong>Uploading the project to a remote repository (GitHub)<\/strong><\/p><p>Before deploying your project on a VPS, it&rsquo;s a good practice to upload your code to a remote repository, such as GitHub, for version control and easy collaboration. Plus, it simplifies the deployment process itself.<\/p><ol class=\"wp-block-list\">\n<li>Install Git CLI and initialize a local repository.Make sure you&rsquo;re in your main project folder, where you have the <strong>manage.py<\/strong> file, and run these commands:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo apt install git-all<\/pre><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git init<\/pre><ol start=\"2\" class=\"wp-block-list\">\n<li>Create a <strong>.gitignore<\/strong> file and add contents to it.The <a href=\"https:\/\/docs.github.com\/en\/get-started\/getting-started-with-git\/ignoring-files\" target=\"_blank\" rel=\"noopener\">.gitignore file<\/a> tells Git which files to ignore when pushing code to your remote repository. This is done in order to skip files holding sensitive information as well as local, irrelevant files like logs from being published. Here&rsquo;s an example <strong>.gitignore<\/strong> file for a Django project:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">venv\/\n__pycache__\/\ndb.sqlite3\n*.pyc\n*.log\nmedia\/<\/pre><ol start=\"3\" class=\"wp-block-list\">\n<li>Sanitize sensitive information in your <strong>settings.py<\/strong>.Make sure you sanitize sensitive information in your settings.py file, such as passwords, usernames, etc. Once the project is deployed, you can add the credentials to your VPS.<\/li>\n\n\n\n<li>Add and Commit your files.<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git add .<\/pre><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git commit -m \"Initial commit\"<\/pre><ol start=\"5\" class=\"wp-block-list\">\n<li>Register on GitHub and create a remote repositoryGo to <a href=\"https:\/\/github.com\/signup\" target=\"_blank\" rel=\"noopener\">GitHub<\/a> and register or log in to your account. Create a new repository, set it to private, and copy its remote link.<\/li>\n\n\n\n<li>Set up remote Git origin and branch.<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git remote add origin https:\/\/github.com\/url-to-repository-you-created<\/pre><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git branch -M main<\/pre><ol start=\"7\" class=\"wp-block-list\">\n<li>Check the status of your local repository and push files.Prior to pushing files, you should run the <strong>status <\/strong>command and make sure no files you do not want to push are added:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git status<\/pre><p>Confirm that only files that you want to upload are added and push them to the remote repository:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git push -u origin main <\/pre><ol start=\"8\" class=\"wp-block-list\">\n<li>Go to your remote repository on GitHub and confirm the files uploaded.<\/li>\n<\/ol><p><strong>Prepare your VPS and retrieve the project code<\/strong><\/p><p>Next, you need to prepare your VPS for deployment and download your code to it:<\/p><ol class=\"wp-block-list\">\n<li>SSH into your VPS<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ssh root@your_vps_ip<\/pre><ol start=\"2\" class=\"wp-block-list\">\n<li>Instal <strong>Nginx <\/strong>and <strong>Gunicorn<\/strong><\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo apt install nginx<\/pre><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo pip3 install gunicorn<\/pre><p>We&rsquo;ll use <strong>Nginx <\/strong>as the web server and <strong>Gunicorn <\/strong>as the application server<\/p><ol start=\"3\" class=\"wp-block-list\">\n<li>Retrieve code from GitHub<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git clone https:\/\/github.com\/your-repository\/project-name.git<\/pre><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">cd project-name<\/pre><ol start=\"4\" class=\"wp-block-list\">\n<li>Start a virtual environment and install dependencies<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">python3 -m venv env_namesource env_name\/bin\/activate<\/pre><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">pip3 install -r requirements.txt<\/pre><ol start=\"5\" class=\"wp-block-list\">\n<li>Fill in sanitized data back into your <strong>settings.py<\/strong> file<\/li>\n\n\n\n<li>Run migrations and collect static files<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">python manage.py migrate<\/pre><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">python manage.py collectstatic<\/pre><ol start=\"7\" class=\"wp-block-list\">\n<li>Set up Gunicorn as the application server. Create a service file:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nano \/etc\/systemd\/system\/gunicorn.service<\/pre><p>Add the following configuration:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[Unit]\nDescription=gunicorn daemon\nAfter=network.target\n\n[Service]\nUser=your-username\nGroup=www-data\nWorkingDirectory=\/your\/project\/directory\nExecStart=\/your\/project\/directory\/env_name\/bin\/gunicorn --access-logfile - --workers 3 --bind unix:\/your\/project\/directory.sock myproject.wsgi:application\n\n[Install]\nWantedBy=multi-user.target<\/pre><p>Make sure to enter your factual username and project directory path instead of <strong>your-username<\/strong> and <strong>\/your\/project\/directory<\/strong>.<\/p><ol start=\"8\" class=\"wp-block-list\">\n<li>Start and enable Gunicorn<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl start gunicorn<\/pre><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl enable gunicorn<\/pre><ol start=\"9\" class=\"wp-block-list\">\n<li>Configure Nginx as the web server. Create a configuration file:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nano \/etc\/nginx\/sites-available\/myproject<\/pre><p>Add the following configuration:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">server {\n    listen 80;\n    server_name yourdomain.com www.yourdomain.com;\n\n    location \/ {\n        proxy_pass http:\/\/unix:\/your\/project\/directory\/project-name.sock;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n\n    location \/static\/ {\n        alias \/your\/project\/directory\/static\/;\n    }\n\n    location \/media\/ {\n        alias \/your\/project\/directory\/media\/;\n    }\n}<\/pre><p>Make sure to enter your factual directory path instead of <strong>\/your\/project\/directory<\/strong>.<\/p><ol start=\"10\" class=\"wp-block-list\">\n<li>Enable the site and restart Nginx<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo ln -s \/etc\/nginx\/sites-available\/myproject \/etc\/nginx\/sites-enabled<\/pre><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl restart nginx<\/pre><ol start=\"11\" class=\"wp-block-list\">\n<li>Secure the server with SSLWe&rsquo;ll use Certbot to apply an SSL certificate and redirect traffic from HTTP to HTTPS:<\/li>\n<\/ol><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo apt install certbot python3-certbot-nginxsudo certbot --nginx -d yourdomain.com -d www.yourdomain.com<\/pre><p>By following these steps, you&rsquo;ve successfully deployed your Django application on a VPS using best practices, ensuring both security and performance.<\/p><p>With Nginx and Gunicorn handling the web and application serving, your app is now ready to handle live traffic. Visit your domain &ndash; if you&rsquo;ve set everything right you should now see your web application live.<\/p><h2 class=\"wp-block-heading\" id=\"h-conclusion\">Conclusion<\/h2><p>In this tutorial, we covered the essential steps to get started with Django, from setting up your development environment to deploying your project on a VPS. You&rsquo;ve learned how to create a project, manage models and store data, build views and templates, work with URLs, handle static files, implement user authentication, and deploy your application to a live server.<\/p><p>With these foundational skills, you&rsquo;re now equipped to start building your own Django projects. Whether it&rsquo;s a simple blog or a more complex web application, Django provides you with the tools to bring your ideas to life. Dive in, experiment, and see what you can create with this powerful web framework.<\/p><h2 class=\"wp-block-heading\" id=\"h-django-tutorial-faq\">Django tutorial FAQ<\/h2><div class=\"schema-faq wp-block-yoast-faq-block\"><div class=\"schema-faq-section\" id=\"faq-question-1727665574369\"><h3 class=\"schema-faq-question\">What is Django?<\/h3> <p class=\"schema-faq-answer\">Django is a high-level Python web framework designed for rapid development and clean, pragmatic design. It simplifies the process of building web applications by providing reusable components such as authentication, ORM, and routing, while promoting best practices like DRY (Don&rsquo;t Repeat Yourself) and security.<\/p> <\/div> <div class=\"schema-faq-section\" id=\"faq-question-1727665589337\"><h3 class=\"schema-faq-question\">Why use Django?<\/h3> <p class=\"schema-faq-answer\">Django is used for its speed, security, and scalability. It simplifies web development with built-in features like authentication, an ORM for database management, and URL routing. Its &ldquo;batteries-included&rdquo; philosophy allows Django developers to build robust applications quickly while following best practices.<\/p> <\/div> <div class=\"schema-faq-section\" id=\"faq-question-1727665606836\"><h3 class=\"schema-faq-question\">Do I need to know Python to learn Django?<\/h3> <p class=\"schema-faq-answer\">Yes, knowing Python is essential to learning Django, a Python-based web framework. Familiarity with Python&rsquo;s syntax, data structures, and object-oriented programming will help you understand Django&rsquo;s structure and functionality, making the learning process smoother and more efficient.<\/p> <\/div> <div class=\"schema-faq-section\" id=\"faq-question-1741092572519\"><h3 class=\"schema-faq-question\">What are some Django alternatives for creating web apps?<\/h3> <p class=\"schema-faq-answer\">Flask, FastAPI, and Pyramid are Python-based alternatives, while Next.js and Express.js are popular for JavaScript. PHP options like Laravel and Symfony are also widely used. Recently, AI-powered no-code tools like Hostinger Horizons have emerged, allowing users to <a href=\"\/horizons\">build full-stack web apps<\/a> with natural language prompts.<\/p> <\/div> <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Django is a high-level Python web framework used for rapid development and clean, pragmatic design. It simplifies many web development [&#8230;]<\/p>\n<p><a class=\"btn btn-secondary understrap-read-more-link\" href=\"\/tutorials\/django-tutorial\">Read More&#8230;<\/a><\/p>\n","protected":false},"author":471,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Django tutorial: Build and deploy your first project","rank_math_description":"Check out our Django tutorial, where we\u2019ll cover the main fundamentals of getting started with this web framework for rapid development.","rank_math_focus_keyword":"django tutorial","footnotes":""},"categories":[22646,22644],"tags":[],"class_list":["post-116603","post","type-post","status-publish","format-standard","hentry","category-pre-installed-applications","category-vps"],"hreflangs":[{"locale":"en-US","link":"https:\/\/www.hostinger.com\/tutorials\/django-tutorial","default":0},{"locale":"pt-BR","link":"https:\/\/www.hostinger.com\/br\/tutoriais\/tutorial-django","default":0},{"locale":"fr-FR","link":"https:\/\/www.hostinger.com\/fr\/tutoriels\/tutoriel-django","default":0},{"locale":"en-UK","link":"https:\/\/www.hostinger.com\/uk\/tutorials\/django-tutorial","default":0},{"locale":"en-MY","link":"https:\/\/www.hostinger.com\/my\/tutorials\/coolify-vs-dokploy-10","default":0},{"locale":"en-PH","link":"https:\/\/www.hostinger.com\/ph\/tutorials\/django-tutorial","default":0},{"locale":"en-IN","link":"https:\/\/www.hostinger.com\/in\/tutorials\/django-tutorial","default":0},{"locale":"en-CA","link":"https:\/\/www.hostinger.com\/ca\/tutorials\/django-tutorial","default":0},{"locale":"pt-PT","link":"https:\/\/www.hostinger.com\/pt\/tutoriais\/tutorial-django","default":0},{"locale":"en-AU","link":"https:\/\/www.hostinger.com\/au\/tutorials\/django-tutorial","default":0},{"locale":"en-NG","link":"https:\/\/www.hostinger.com\/ng\/tutorials\/django-tutorial","default":0}],"_links":{"self":[{"href":"https:\/\/www.hostinger.com\/tutorials\/wp-json\/wp\/v2\/posts\/116603","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.hostinger.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hostinger.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/tutorials\/wp-json\/wp\/v2\/users\/471"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/tutorials\/wp-json\/wp\/v2\/comments?post=116603"}],"version-history":[{"count":12,"href":"https:\/\/www.hostinger.com\/tutorials\/wp-json\/wp\/v2\/posts\/116603\/revisions"}],"predecessor-version":[{"id":138224,"href":"https:\/\/www.hostinger.com\/tutorials\/wp-json\/wp\/v2\/posts\/116603\/revisions\/138224"}],"wp:attachment":[{"href":"https:\/\/www.hostinger.com\/tutorials\/wp-json\/wp\/v2\/media?parent=116603"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hostinger.com\/tutorials\/wp-json\/wp\/v2\/categories?post=116603"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hostinger.com\/tutorials\/wp-json\/wp\/v2\/tags?post=116603"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}