<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Nitin Raturi's Software Engineering Blog]]></title><description><![CDATA[Full-stack web development with Python, Django, React and computer science concepts.]]></description><link>https://tech.raturi.in</link><image><url>https://substackcdn.com/image/fetch/$s_!iH7f!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F853048bc-ea86-4674-9f79-a1695f7231de_500x500.png</url><title>Nitin Raturi&apos;s Software Engineering Blog</title><link>https://tech.raturi.in</link></image><generator>Substack</generator><lastBuildDate>Thu, 09 Apr 2026 20:25:22 GMT</lastBuildDate><atom:link href="https://tech.raturi.in/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Nitin Raturi]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[raturinitin@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[raturinitin@substack.com]]></itunes:email><itunes:name><![CDATA[Nitin Raturi]]></itunes:name></itunes:owner><itunes:author><![CDATA[Nitin Raturi]]></itunes:author><googleplay:owner><![CDATA[raturinitin@substack.com]]></googleplay:owner><googleplay:email><![CDATA[raturinitin@substack.com]]></googleplay:email><googleplay:author><![CDATA[Nitin Raturi]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Adding Ssh Key To Github]]></title><description><![CDATA[Git & Github: Learn to generate and add ssh keys to github]]></description><link>https://tech.raturi.in/p/how-configure-git-and-github-ssh-key</link><guid isPermaLink="false">https://tech.raturi.in/p/how-configure-git-and-github-ssh-key</guid><dc:creator><![CDATA[Nitin Raturi]]></dc:creator><pubDate>Mon, 10 Mar 2025 09:04:31 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/DOkfpaPM2-A]" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Using the <strong><a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh/about-ssh">Github SSH protocol</a></strong>, you can connect to GitHub and sync with repositories without supplying your username and personal access token each time you push, pull, merge, or any Github-related command.</p><p>You can watch the video tutorial or read the text below.</p><div id="youtube2-DOkfpaPM2-A]" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;DOkfpaPM2-A]&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/DOkfpaPM2-A]?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><h2><strong>Generate SSH Keys for GitHub</strong></h2><blockquote><p><em><strong>If you are a windows user or you face any difficulty while generating your ssh keys, you can <a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent">follow this tutorial</a> and come back to proceed further steps.</strong></em></p></blockquote><p>First, open your terminal and run</p><pre><code><code>ssh-keygen -t rsa -b 4096 -C "youremail@domain.com"
</code></code></pre><blockquote><p><em><strong>Replace "youremail@domain.com" with your email</strong></em></p></blockquote><p>It will ask you a few questions, keep on pressing enter till you get the output something like below.</p><pre><code><code>Generating public/private rsa key pair.
Enter file in which to save the key (/home/nitin/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in id_rsa
Your public key has been saved in id_rsa.pub
The key fingerprint is:
SHA256:5asd2MT5gasdUvqhKhmKsad2qasdSfSQ/ZPgtxVbxjFhfu/U raturi888@gmail.com
The key's randomart image is:
+---[RSA 4096]----+
| ..o. .+.  .     |
| .=  +o = . .    |
|  .++. . +.. .   |
| ..+.o . o  o .  |
|o...+ . D =.   F |
|+.oo .   * o     |
|==+ .     =      |
|A= .       .     |
|*=+              |
+----[SHA256]-----+
</code></code></pre><p>Now run the below command to print the key on the screen.</p><pre><code><code>cat ~/.ssh/id_rsa.pub
</code></code></pre><p>Now copy the output generated.</p><pre><code><code>ssh-rsa AA21adasdasd+VvPxRRYZ7EI354FsLXrsPX97K0XhstPhL3IOKhKUUmD0XuIw7CgNyJuQB7DN1keAM4JPgcfhlzA78RuVJAuUm4MqKrjworsDt4h1olj14FiEu0qpasdasdsadsadwrLGfLEeasdsadasdasdasdT6rqkvnjiIS4iugpbXRK/ykdmNKvBr3ijKmELIuoz5pH32ghDiPwX9u65R0Ss8CYqnODzuE7UxjryNDjyYhCo10TPhFaIwNPu8EP5FzaHBUiN6dm6D7mtORrGtZ8Hhtr5s9rxcuTIc0m1H9rZE799/nyI46Te72CPmNJFnaDT+asdasdasd4aX+CbJEEkQ== raturi888@gmail.com
</code></code></pre><h2><strong>Adding SSH Keys to Github</strong></h2><p>Github SSH keys are added inside the <code>SSH and GPG keys settings</code></p><div data-attrs="{&quot;url&quot;:&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1685452920009/6afea3c7-f2ff-41d9-b5ed-60c9c22a521a.png%20align=&quot;}" data-component-name="AssetErrorToDOM"><picture><img src="/img/missing-image.png" height="455" width="728"></picture></div><p>Follow the steps below to open SSH and GPG keys settings</p><ul><li><p>Visit <strong><a href="https://github.com/">github.com</a></strong> and log in.</p></li><li><p>Click on the profile icon on the top right and click on settings.</p></li><li><p>Now from the left sidebar click on the SSH and GPG keys</p></li><li><p>You can also <strong><a href="https://github.com/settings/keys">click here to open the SSH/GPG settings</a></strong> directly.</p></li></ul><p>To add the key, click on <strong>New SSH key</strong> button at the top right, it will open up a form to fill the key.</p><div data-attrs="{&quot;url&quot;:&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1685452942729/c6bbc1ee-d0a8-4a47-93e7-36d8f93a2f7a.png%20align=&quot;}" data-component-name="AssetErrorToDOM"><picture><img src="/img/missing-image.png" height="455" width="728"></picture></div><ul><li><p>In this <code>Title</code> field, enter any name to differentiate your key from the keys you will enter in the future</p></li><li><p>In <code>Key</code> field paste the key you copied earlier.</p></li><li><p>Finally, click on Add SSH Key button</p></li></ul><h2><strong>Setting Up Git Repository for using with SSH Protocol</strong></h2><p>If you are cloning a new repository then select the ssh tab while cloning</p><div data-attrs="{&quot;url&quot;:&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1685452971780/bfa59449-642a-4c94-9244-ac0e8853f691.png%20align=&quot;}" data-component-name="AssetErrorToDOM"><picture><img src="/img/missing-image.png" height="455" width="728"></picture></div><p>If you already have the repository cloned then follow the steps below:</p><ul><li><p>Open your terminal, change your directory to the cloned repository, and use the below command.</p></li><li><p><code>git remote set-url origin</code> <code>git@github.com:&lt;github username&gt;/&lt;repository name&gt;</code></p></li><li><p>Don't forget to change <code>gitusername</code>, <code>repositoryname</code> to yours, like I have set mine below</p></li><li><p><code>git remote set-url origin</code> <code>git@github.com/nitinraturi/django-structure</code></p></li></ul><p>Now ssh keys are set up, you can try pushing them to your Github repository, you will not be asked for a username and password.</p><p>I hope, by now you should be able to add ssh keys to your Github account.</p><p>You can follow this tutorial to learn <strong><a href="https://tech.raturi.in/p/full-tutorial-git-version-control">basics of Github</a></strong>.</p>]]></content:encoded></item><item><title><![CDATA[Git Remove All Commits History]]></title><description><![CDATA[Git: remove all commit history and reduce the repository size.]]></description><link>https://tech.raturi.in/p/cleaning-git-repository</link><guid isPermaLink="false">https://tech.raturi.in/p/cleaning-git-repository</guid><dc:creator><![CDATA[Nitin Raturi]]></dc:creator><pubDate>Mon, 10 Mar 2025 08:58:56 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iH7f!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F853048bc-ea86-4674-9f79-a1695f7231de_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When working with any project, initially we do not take care of how to write commits and end up with a large unnecessary commit history. In this tutorial, you will learn how to clean the git commit history.</p><h2><strong>How to remove git commit history</strong></h2><p>Our approach is to tell Git that your current commit is the initial commit. For that first checkout to the commit, which you want to make as the initial commit. Then run the following commands :</p><pre><code><code>git checkout --orphan latest_branch

git add -A

git commit -am "Initial commit message" #Committing the changes

git branch -D master #Deleting master branch

git branch -m master #renaming branch as master

git push -f origin master #pushes to master branch

git gc --aggressive --prune=all # remove the old files
</code></code></pre><p>The above commands will forcefully push the current source code to the master branch as the first command.</p><blockquote><p><em><strong>Note: You should delete all other branches and tags, because they may still contain the old history.</strong></em></p></blockquote>]]></content:encoded></item><item><title><![CDATA[Convert A Django Queryset To List]]></title><description><![CDATA[Use list(queryset) to convert a queryset to a list. Read more for alternate methods]]></description><link>https://tech.raturi.in/p/django-queryset-to-list</link><guid isPermaLink="false">https://tech.raturi.in/p/django-queryset-to-list</guid><dc:creator><![CDATA[Nitin Raturi]]></dc:creator><pubDate>Mon, 10 Mar 2025 08:50:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iH7f!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F853048bc-ea86-4674-9f79-a1695f7231de_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>While working with Django queryset, at some point you need more than just a queryset object type like converting a queryset to a list.</p><p><strong>Django queryset can be converted to a list using the</strong> <strong>python's</strong> <strong>built-in list method (list(queryset.objects.all())) but note that it is not ideal to load the whole result into memory via list() in terms of memory and time optimization</strong>.</p><p>Let's cover other approaches we can work to convert <strong>django</strong> queryset to list.</p><h2><strong>Django queryset to list using list() method</strong></h2><p><strong><a href="https://tech.raturi.in/tag/python/">Python's</a></strong> built-in list() method to convert a queryset to a list is not an optimized approach as this will load all the objects in your memory.</p><pre><code><code>from apps.blog.models import *
articles = Blog.objects.all()

# This will return a queryset type
print(type(articles))

# Convert articles queryset to a python's list type
articles_list = list(articles)

# This will return a list type
print(type(articles_list))
</code></code></pre><pre><code><code>&lt;class 'django.db.models.query.QuerySet'&gt;
&lt;class 'list'&gt;
</code></code></pre><h2><strong>Django Queryset to list using values_list() method</strong></h2><p>Django's built-in <strong><a href="https://docs.djangoproject.com/en/stable/ref/models/querysets/#values-list">model.objects.values_list()</a></strong> method is one of the ideal ways of converting a queryset to a list.</p><h3><strong>It returns tuples when iterated over. Each tuple contains the value from the respective field or expression passed into the values_list(). For example:</strong></h3><pre><code><code>from apps.blog.models import Blog
articles = Blog.objects.values_list()
print(articles)
print(list(articles))
</code></code></pre><pre><code><code>&lt;QuerySet [(32, 'List of useful websites for software engineers', 5, 'list-useful-websites-software-engineers', None, datetime.date(2022, 3, 3), datetime.date(2022, 4, 20), 18, 'List of useful websites for software engineers', '', None, 1, True, &lt;StreamValue [&lt;block richtext: &lt;wagtail.core.rich_text.RichText object at 0x7f61cefeb20&gt;&gt;]&gt;)]&gt;

[(26, 'List of useful websites for software engineers', 5, 'list-useful-websites-software-engineers', None, datetime.date(2022, 3, 3), datetime.date(2022, 4, 20), 18, 'List of useful websites for software engineers', '', None, 1, True, &lt;StreamValue [&lt;block richtext: &lt;wagtail.core.rich_text.RichText object at 0x7f61cefeb20&gt;&gt;]&gt;)]
</code></code></pre><h3><strong>If you only want single values in a list, then you have to pass a single field and a flat parameter set as True.</strong></h3><pre><code><code>from apps.blog.models import Blog

articles = Blog.objects.values_list('id',flat=True)
print(articles)
print(list(articles))
</code></code></pre><pre><code><code>&lt;QuerySet [87, 83, 35, 84, 86]&gt;
[87, 83, 35, 84, 86]
</code></code></pre><h3><strong>If you want multiple values in a list, then you have to pass multiple arguments in values_list().</strong></h3><pre><code><code>from apps.blog.models import Blog

articles = Blog.objects.values_list('id','category')
print(articles)
print(list(articles))
</code></code></pre><pre><code><code>&lt;QuerySet [(87, 18)]&gt;
[(87, 18)]
</code></code></pre><p>If you want to read about Django queryset in detail then I want you to go through this guide on <strong><a href="https://tech.raturi.in/p/everything-about-django-orm-querysets-field-lookups-model-managers-aggregate-functions-tutorial">Django ORM in detail</a></strong>.</p>]]></content:encoded></item><item><title><![CDATA[Queryparam Chrome Extension Tutorial]]></title><description><![CDATA[How to use and install queryparam chrome extension]]></description><link>https://tech.raturi.in/p/queryparam-chrome-extension-tutorial</link><guid isPermaLink="false">https://tech.raturi.in/p/queryparam-chrome-extension-tutorial</guid><dc:creator><![CDATA[Nitin Raturi]]></dc:creator><pubDate>Mon, 10 Mar 2025 08:44:59 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iH7f!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F853048bc-ea86-4674-9f79-a1695f7231de_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this tutorial, you will learn about QueryParam Chrome Extension. QueryParam chrome extension is a utility for making urls easy.</p><p>For example: You have a website <strong>tech.raturi.in</strong> and there is a query parameter <strong>mob=false</strong> i.e., </p><p>http://tech.raturi.in/?mob=false</p><p> , that is used to render a mobile site. So everytime you have to modify your url mob=false and mob=true. Imagine if you have <strong>10 or 20 or more</strong>, is not this a head ache to change the parameters everytime to render a different page. If you are having a similar kind of problem or is related than this extension is for you.</p><blockquote><p><em><strong>Refer to the <a href="https://github.com/nitinraturi/queryparams_chrome_extension">github repo</a></strong></em></p></blockquote><h2><strong>Installation</strong></h2><ul><li><p>Open extension on <strong><a href="https://chrome.google.com/webstore/detail/queryparam/debkbpaaeaocgianodbgghkhkjjlclhg?hl=en-GB&amp;utm_source=chrome-ntp-launcher">store</a></strong></p></li><li><p>Click Add To Chrome</p></li></ul><h2><strong>Usage</strong></h2><ul><li><p>To use it you have to create action buttons once.</p></li><li><p>To create an action button, fill in the unique action name and action value with the query parameters you want attach in your urls whenever an action button is clicked.</p></li><li><p><strong>Dont include ? in your action value</strong>.</p></li><li><p>Example for action value: <code>m=t&amp;a=t</code></p></li><li><p>Now you can see an action button has been created. Click on it and thats it.</p></li></ul><h2><strong>Contribute</strong></h2><p>If you found any bugs or have any improvements for this utility dont forget to contribute. Just create a pull request whenever you feel is the right time.</p><blockquote><p><em><strong><a href="https://github.com/nitinraturi/queryparams_chrome_extension">Repository Link</a></strong></em></p></blockquote>]]></content:encoded></item><item><title><![CDATA[Django Mixin: Custom Class Based Mixins, Example, And Types]]></title><description><![CDATA[A Mixin is a special kind of inheritance in Python to allow classes to share methods between any class.]]></description><link>https://tech.raturi.in/p/custom-mixins-django-class-based-views</link><guid isPermaLink="false">https://tech.raturi.in/p/custom-mixins-django-class-based-views</guid><dc:creator><![CDATA[Nitin Raturi]]></dc:creator><pubDate>Mon, 10 Mar 2025 08:41:43 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iH7f!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F853048bc-ea86-4674-9f79-a1695f7231de_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Mixin in Django is a</strong> <strong><a href="https://tech.raturi.in/t/python">Python</a></strong> <strong>class inherited by another class to accomplish additional functionality. Mixins are reusable and scalable classes.</strong></p><blockquote><p><em><strong>Prerequisite: Understanding Django&#8217;s class-based views is required before exploring Mixins.</strong></em></p></blockquote><h2><strong>How Mixin works in Django</strong></h2><p>Let me take an example, to help you understand the working of a mixin.</p><p>Suppose you want only logged-in users to have access to an <strong>URL</strong>. For this, you can use <strong>Django's</strong> built-in <strong>LoginRequiredMixin</strong> in your view, just like the code snippet below.</p><pre><code><code> from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'
</code></code></pre><blockquote><p><em><strong>LoginRequiredMixin overrides one or more methods of the View class to achieve this functionality. You don't need to delve into the exact methods at this point for the sake of simplicity of this tutorial, this is just to give an idea of how mixin works. You will get a clear understanding, once you create a custom mixin.</strong></em></p></blockquote><h2><strong>Create a custom mixin in Django</strong></h2><p>Let's create a mixin that redirects a user based on some condition.</p><p>Before that, you need to know why to create a mixin. <strong>Well, if you don't create a mixin then you have to write the redirect logic to every view and also if you have to update redirect logic at a later point of time then you have to make changes at every view.</strong></p><p>In Django's class-based views, there is a method called <code>dispatch</code>, that you will have to override to achieve any mixin-related functionality.</p><p>Let's consider the below code snippet as your view that is called when a user logged in.</p><pre><code><code>from django.views.generic import TemplateView

class LoginView(TemplateView):
    template_name="account/login.html"
</code></code></pre><p>Now you have to create two python classes to create the redirect mixin. First, create a GENERIC mixin to be used by any other mixin for redirecting.</p><pre><code><code>from django.core.exceptions import ImproperlyConfigured
from django.shortcuts import redirect

class RedirectMixin:
    """
    Redirect to redirect_url if the test_func() method returns False.
    """

    redirect_url = None

    def get_redirect_url(self):
        """
        Override this method to override the redirect_url attribute.
        """
        redirect_url = self.redirect_url
        if not redirect_url:
            raise ImproperlyConfigured(
                '{0} is missing the redirect_url attribute. Define {0}.redirect_url or override '
                '{0}.get_redirect_url().'.format(self.__class__.__name__)
            )
        return str(redirect_url)

    def test_func(self):
        raise NotImplementedError(
            '{0} is missing the implementation of the test_func() method.'.format(self.__class__.__name__)
        )

    def get_test_func(self):
        """
        Override this method to use a different test_func method.
        """
        return self.test_func

    def dispatch(self, request, *args, **kwargs):
        test_result = self.get_test_func()()
        if not test_result:
            return redirect(self.get_redirect_url())
        return super().dispatch(request, *args, **kwargs)
</code></code></pre><p>The above <strong>RedirectMixin</strong> class has two important things that make it a mixin, <strong>redirect_url</strong> which is going to be used by the final view, and <strong>test_func</strong> which is going to be used by the next specific redirect mixin.</p><p>Now create a mixin that uses the above RedirectMixin to redirect authenticated users.</p><pre><code><code>class LoggedInRedirectMixin(RedirectMixin):
    def test_func(self):
        return self.request.user.is_authenticated
</code></code></pre><p>Notice, in the above LoggedInRedirectMixin, RedirectMixin is inherited and the test_func() method is overridden.</p><p><strong>test_func()</strong> is a very important method here, as all the redirect logic is placed inside it.</p><p>Now you have created a mixin, which is going to be used in the <strong>LoginView</strong> you considered initially. Remember!</p><blockquote><p><em><strong>Note: You can create as many as mixins like LoggedInRedirectMixin based on different conditions, just try to create more generic ones as it's the whole purpose of creating mixins.</strong></em></p></blockquote><p>Finally, you can use this mixin just by inheriting it.</p><pre><code><code>from django.views.generic import TemplateView

class LoginView(LoggedInRedirectMixin,TemplateView):
    template_name="account/login.html"
    redirect_url = "/some-url/"
</code></code></pre><p>Don't forget to add the <code>redirect_url</code> attribute in your view. Set it to the URL you want to redirect authenticated users.</p><p>You have successfully created a custom mixin. The next section covers a few of the built-in mixins in Django, you can skip &#128640; it if you are here only for custom mixins.</p><h2><strong>Types of Mixins</strong></h2><p>In Django, there are two types of mixins: built-in mixins, and custom mixins.</p><p><strong>Custom Mixins</strong>: These are the mixins created by a user for their specific purpose just like the above LoggedInRedirectMixin.</p><p><strong>Built-in Mixins</strong>: These are the default mixins that come with Django to provide out-of-the-box functionalities. Here are a list few built-in mixins in Django.</p><ul><li><p>LoginRequiredMixin</p></li><li><p>TemplateResponseMixin</p></li><li><p>SingleObjectMixin</p></li><li><p>MultipleObjectMixin</p></li><li><p>FormMixin</p></li></ul><p>You can learn more about built-in class-based mixins in Django from <strong><a href="https://docs.djangoproject.com/en/stable/topics/class-based-views/mixins/">official docs</a></strong>.</p><h2><strong>Example of Mixins</strong></h2><ul><li><p>JSONResponseMixin</p></li></ul><h3><strong>JSONResponseMixin</strong></h3><p>Suppose you are writing a set of APIs and each view should return JSON instead of plain HTML. I am taking this code snippet from <strong><a href="https://docs.djangoproject.com/en/stable/topics/class-based-views/mixins/#more-than-just-html">official Django documentation</a></strong>.</p><pre><code><code>from django.http import JsonResponse

class JSONResponseMixin:
    """
    A mixin that can be used to render a JSON response.
    """
    def render_to_json_response(self, context, **response_kwargs):
        """
        Returns a JSON response, transforming 'context' to make the payload.
        """
        return JsonResponse(
            self.get_data(context),
            **response_kwargs
        )

    def get_data(self, context):
        """
        Returns an object that will be serialized as JSON by json.dumps().
        """
        # Note: This is *EXTREMELY* naive; in reality, you'll need
        # to do much more complex handling to ensure that arbitrary
        # objects -- such as Django model instances or querysets
        # -- can be serialized as JSON.
        return context
</code></code></pre><p>Use this mixin in your view like this</p><pre><code><code>from django.views.generic import TemplateView

class JSONView(JSONResponseMixin, TemplateView):
    def render_to_response(self, context, **response_kwargs):
        return self.render_to_json_response(context, **response_kwargs)
</code></code></pre><p>More examples will be added in the future in this post.</p>]]></content:encoded></item><item><title><![CDATA[Django Custom User Model: Abstractuser]]></title><description><![CDATA[Extend or create a custom user model in django using AbstractUser]]></description><link>https://tech.raturi.in/p/how-extend-django-user-model</link><guid isPermaLink="false">https://tech.raturi.in/p/how-extend-django-user-model</guid><dc:creator><![CDATA[Nitin Raturi]]></dc:creator><pubDate>Mon, 10 Mar 2025 08:38:55 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iH7f!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F853048bc-ea86-4674-9f79-a1695f7231de_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><a href="https://tech.raturi.in/tag/django/">Django</a></strong> ships with a built-in <strong><a href="https://docs.djangoproject.com/en/stable/ref/contrib/auth/#django.contrib.auth.models.User">User model</a></strong> for authentication, however, the <strong><a href="https://docs.djangoproject.com/en/stable/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project">official Django documentation</a></strong> highly recommends using a custom user model for new projects.</p><p>There are two modern ways to create a custom user model in Django: <strong>AbstractUser</strong> and <strong>AbstractBaseUser</strong>. In both cases, we can subclass them to extend existing functionality.</p><p>However, <strong>AbstractBaseUser</strong> requires much, much more work. So here we will use <strong>AbstractUser</strong>.</p><p>We will also create a <strong>UserProfile</strong> model to store additional information about users with the help of a One-To-One Link. After this, we will extend the <strong>BaseUserManager</strong> functionality a little bit. We will also configure <strong><a href="https://tech.raturi.in/p/django-signals">signals</a></strong> to automatically create <strong>UserProfile</strong> whenever a User object is created. Finally, we will customize the Django admin.</p><blockquote><p><em><strong>Note: This should be done at the begining of the project before running any migrations.</strong></em></p></blockquote><h2><strong>Step 1: New app</strong></h2><ul><li><p>Create app users using the command <code>python</code> <code>manage.py</code> <code>startapp users</code></p></li><li><p>Now register your app in your installed apps in <strong>settings.py</strong>: <code>INSTALLED_APPS += [ 'users', ]</code></p></li><li><p>Set <strong>AUTH_USER_MODEL</strong> in <strong>settings.py</strong> to the new user model: <code>AUTH_USER_MODEL = 'users.User'</code></p></li></ul><h2><strong>Step 2: Extend model and manager</strong></h2><p>Create a file <strong>constants.py</strong> inside <strong>users</strong> app directory</p><pre><code><code># users/constants.py
SUPERUSER = 1
STAFF = 2
STUDENT = 3
TUTOR = 4

USER_TYPE_CHOICES = (
      (SUPERUSER, 'superuser'),
      (STAFF, 'staff'),
      (STUDENT, 'student'),
      (TUTOR, 'tutor'),
  )
</code></code></pre><p>Extend the <strong>User</strong> model in your <strong>users/models.py</strong></p><pre><code><code># users/models.py

from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils import timezone
from apps.users.managers import UserManager
from . import constants as user_constants

class User(AbstractUser):
    username = None # remove username field, we will use email as unique identifier
    email = models.EmailField(unique=True, null=True, db_index=True)
    is_active = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)
    date_joined = models.DateTimeField(default=timezone.now)
    user_type = models.PositiveSmallIntegerField(choices=user_constants.USER_TYPE_CHOICES)

    REQUIRED_FIELDS = []
    USERNAME_FIELD = 'email'

    objects = UserManager()


class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True,related_name="user_profile")
    phone = models.CharField(max_length=255,blank=True,null=True)
    is_verified = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.user.email
</code></code></pre><p>Extend <strong>UserManager</strong> in <strong>users/managers.py</strong></p><pre><code><code># users/managers.py

from django.contrib.auth.models import BaseUserManager
from . import constants as user_constants


class UserManager(BaseUserManager):
    def create_user(self, email, password, **extra_fields):

        if not email:
            raise ValueError('The Email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_active', True)
        extra_fields.setdefault('user_type', user_constants.SUPERUSER)
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')
        return self.create_user(email, password, **extra_fields)
</code></code></pre><h2><strong>Step 3: Migrations</strong></h2><p>Run the commands below to make <strong>database</strong> changes</p><pre><code><code>python manage.py makemigrations 
python manage.py migrate
</code></code></pre><h2><strong>Step 4: Create Signal</strong></h2><p>Now let's create <strong>signals</strong> for automatically creating a <strong>UserProfile</strong> instance in <strong>users/signals.py</strong></p><pre><code><code># users/signals.py
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import UserProfile, User

@receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)
    instance.user_profile.save()
</code></code></pre><p>Now, register your signals file inside <strong>users/apps.py</strong> by adding a method <strong>ready</strong> and importing the signals file path.</p><pre><code><code># users/apps.py
from django.apps import AppConfig

class UsersConfig(AppConfig):
    name = 'apps.users'

    def ready(self):
        import apps.users.signals
</code></code></pre><p>Now, add <strong>default_app_config</strong> to <strong>users/init.py</strong></p><pre><code><code># users/__init__.py
default_app_config = 'users.apps.UsersConfig'
</code></code></pre><h2><strong>Step 5: Extend the admin form</strong></h2><p>Let's extend <strong>UserCreationForm</strong> and <strong>UserChangeForm</strong> in <strong>users/forms.py</strong></p><pre><code><code># users/forms.py
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import User


class CustomUserCreationForm(UserCreationForm):

    class Meta(UserCreationForm):
        model = User
        fields = ('email',)


class CustomUserChangeForm(UserChangeForm):

    class Meta:
        model = User
        fields = ('email',)
</code></code></pre><h2><strong>Step 6: Customize Django user admin</strong></h2><p>Let's customize Django's admin now</p><pre><code><code># users/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import UserProfile, User
from .forms import CustomUserCreationForm, CustomUserChangeForm


class UserProfileInline(admin.StackedInline):
    model = UserProfile
    can_delete=False
    verbose_plural_name="User Profile"
    fk_name = 'user'  

class CustomUserAdmin(UserAdmin):
    add_form = CustomUserCreationForm
    form = CustomUserChangeForm
    model = User
    list_display_links = ['email']
    search_fields = ('email',)
    ordering = ('email',)
    # inlines = (UserProfileInline,)
    list_display = ('email', 'is_staff', 'is_active', 'is_superuser',)
    list_filter = ('email', 'is_staff', 'is_active', 'is_superuser', 'user_type')
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email','user_type')}),
        (_('Permissions'), {
            'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions'),
        }),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active', 'user_type')}
         ),
    )

    def get_inline_instances(self, request, obj=None):
        if not obj:
            return list()
        return super(CustomUserAdmin, self).get_inline_instances(request, obj)

admin.site.register(User, CustomUserAdmin)
</code></code></pre><h2><strong>Step 7: Verifying</strong></h2><p>You have successfully extended the user model. Let's create a user</p><pre><code><code>python manage.py createsuperuser

#output
Email: develop@raturi.in
Password: ..........
Password (again): ..........
Superuser created successfully
</code></code></pre><p>Your user should be created by now, login in to your admin panel to see.</p><p>That's all.</p>]]></content:encoded></item><item><title><![CDATA[Deploying Django Application With Nginx And Postgresql]]></title><description><![CDATA[How to setup nginx,django and postgresql]]></description><link>https://tech.raturi.in/p/setup-python3-django-nginx-gunicorn-and-postgresql</link><guid isPermaLink="false">https://tech.raturi.in/p/setup-python3-django-nginx-gunicorn-and-postgresql</guid><dc:creator><![CDATA[Nitin Raturi]]></dc:creator><pubDate>Mon, 10 Mar 2025 08:30:01 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iH7f!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F853048bc-ea86-4674-9f79-a1695f7231de_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this guide, I will demonstrate how to install and configure some components on Ubuntu to support and serve <strong><a href="https://tech.raturi.in/t/django">Django</a></strong> applications. We will configure the Gunicorn application server to interface with our applications.</p><p>We will then set up Nginx to reverse proxy to Gunicorn, giving us access to its security and performance features to serve our apps.</p><h2><strong>Prerequisites</strong></h2><ul><li><p>You have an ubuntu server with sudo privileges</p></li><li><p>You already have your <strong><a href="https://tech.raturi.in/p/setting-django-development-environment-for-starting-a-project">Django application running</a></strong>.</p></li></ul><h2><strong>Installation</strong></h2><p>First, we will install the required packages and libraries one by one.</p><p><strong>Python</strong></p><pre><code><code># Python3 Installation

sudo apt-get update
sudo apt-get install python3
sudo apt-get install python3-pip

# Now check python version installed
python -V

Python 3.5.2

# Replace x below with your python version second digit which is 5 in my case
# sudo apt install python3.x-dev
sudo apt install python3.5-dev

sudo apt-get install build-essential
</code></code></pre><p><strong>Virtual environment</strong></p><pre><code><code># [OPTIONAL]
# Virtual environment installation

sudo apt-get install virtualenv

# Create a virtual environment
virtualenv -p python3 venv

# Activate virtual environment
source venv/bin/activate
</code></code></pre><blockquote><p><em><strong>Follow the <a href="https://tech.raturi.in/p/installing-python3-and-pip3-ubuntu-mac-and-windows">python installation</a> guide if you face any issue while install from above code. For production its a ideal way to use <a href="https://tech.raturi.in/p/installing-python-virtual-environment-ubuntu-mac-and-windows">virtual environment</a> and <a href="https://tech.raturi.in/p/manage-django-environments-secrets-using-python-decouple">environment variables</a>.</strong></em></p></blockquote><p><strong>Postgresql</strong></p><pre><code><code># Install Postgresql
sudo apt-get install libpq-dev  
sudo apt-get install postgresql
sudo apt-get install postgresql-contrib
</code></code></pre><p><strong>Nginx</strong></p><pre><code><code># Nginx Installation

sudo apt update
sudo apt install nginx
</code></code></pre><p><strong>Gunicorn</strong></p><pre><code><code># Gunicorn Installation

pip install gunicorn

# Install Postgresql package for django

pip install psycopg2
</code></code></pre><h2><strong>Create the PostgreSQL Database and User</strong></h2><p>We&#8217;re going to jump right in and create a database and database user for our Django application.</p><p>By default, Postgres uses an authentication scheme called <strong>peer authentication</strong> for local connections. Basically, this means that if the user&#8217;s operating system username matches a valid Postgres username, that user can log in with no further authentication.</p><p>During the Postgres installation, an operating system user named <strong>postgres</strong> was created to correspond to the <strong>postgres</strong> PostgreSQL administrative user. We need to use this user to perform administrative tasks. We can use sudo and pass in the username with the -u option.</p><p>Log into an interactive Postgres session by typing:</p><pre><code><code>sudo -u postgres psql
</code></code></pre><p>You will be given a PostgreSQL prompt where we can set up our requirements. First, create a database for your project:</p><pre><code><code>CREATE DATABASE myproject;
</code></code></pre><p>Next, create a database user for our project. Make sure to select a secure password:</p><pre><code><code>CREATE USER myprojectuser WITH PASSWORD 'password';
</code></code></pre><p>Afterward, we&#8217;ll modify a few of the connection parameters for the user we just created. This will speed up database operations so that the correct values do not have to be queried and set each time a connection is established.</p><p>We are setting the default encoding to UTF-8, which Django expects. We are also setting the default transaction isolation scheme to &#8220;read committed&#8221;, which blocks reads from uncommitted transactions. Lastly, we are setting the timezone. By default, our Django projects will be set to use UTC.</p><p>These are all recommendations from the <strong><a href="https://docs.djangoproject.com/en/stable/ref/databases/#optimizing-postgresql-s-configuration">Django project itself</a></strong></p><pre><code><code>ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE myprojectuser SET timezone TO 'UTC';
</code></code></pre><p>Now, we can give our new user access to administer our new database:</p><pre><code><code>GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
</code></code></pre><p>When you are finished, exit out of the PostgreSQL prompt by typing:</p><pre><code><code>\q
</code></code></pre><h2><strong>Setting Up Django</strong></h2><p>We need to configure <strong>settings.py</strong> and main <strong>urls.py</strong></p><p>Next, find the section that configures database access. It will start with <strong>DATABASES</strong>. The configuration in the file is for an SQLite database. We already created a PostgreSQL database for our project, so we need to adjust the settings.</p><p>Change the settings with your PostgreSQL database information. We tell Django to use the <strong>psycopg2</strong> adaptor we installed with <strong>pip</strong>. We need to give the database name, the database username, and the database user&#8217;s password, and then specify that the database is located on the local computer. You can leave the <strong>PORT</strong> setting as an empty string:</p><pre><code><code># /myproject/myproject/settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'myproject',
        'USER': 'myprojectuser',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '',
    }
}
</code></code></pre><p>Configure <strong>staticfiles</strong> path and <strong>url.py</strong></p><pre><code><code># settings.py

# You can set your own path or you can do the same

STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]
STATIC_ROOT = os.path.join(BASE_DIR,"static_root")

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,"media_root")
</code></code></pre><blockquote><p><em><strong>NOTE: Your project will probably also have static assets that aren&#8217;t tied to a particular app. In addition to using a static/ directory inside your apps, you can define a list of directories (STATICFILES_DIRS) in your settings file where Django will also look for static files.</strong></em></p></blockquote><pre><code><code># urls.py

from django.conf import settings
from django.conf.urls.static import static

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
</code></code></pre><p>If your <strong>debug=False</strong>, then run the command to collect all static files to your static root</p><pre><code><code>python manage.py collectstatic
</code></code></pre><p>Finally test your project, by running:</p><pre><code><code>python manage.py runserver 0.0.0.0:8000


# Make sure you have your ssh service running.
# By default when [ufw](https://tech.raturi.in/how-set-firewall-ufw-ubuntu-debian/) is enabled it blocks ssh, which means you cannot log in to the server. 
# Do not close your terminal and start your ssh service by running:

sudo service ssh start or sudo service ssh restart
sudo ufw allow OpenSSH or sudo ufw allow 22

# If you have your ssh port something else then mention your port number
# sudo ufw allow &lt;portnumber&gt;
</code></code></pre><p>Note: If you are facing any problem related to port or firewall which might have blocked your port, checkout the <strong><a href="https://tech.raturi.in/p/how-set-firewall-ufw-ubuntu-debian">ufw firewall tutorial</a></strong>.</p><h2><strong>Testing Gunicorn&#8217;s Ability to Serve the Project</strong></h2><pre><code><code>gunicorn --bind 0.0.0.0:8000 yourproject.wsgi:application
</code></code></pre><blockquote><p><em><strong>Note: Change yourproject above to the name of your project folder where wsgi.py is located, basically its in the same folder where settings.py is located.This will start Gunicorn on the same interface that the Django development server was running on. You can go back and test the app again.</strong></em></p></blockquote><p>We passed Gunicorn a module by specifying the relative directory path to Django&#8217;s <strong><a href="http://wsgi.py/">wsgi.py</a></strong> file, which is the entry point to our application, using Python's module syntax. Inside of this file, a function called application is defined, which is used to communicate with the application.</p><h2><strong>Creating Gunicorn service file</strong></h2><p>Open the file in: <strong>/etc/systemd/system/gunicorn.service</strong> and paste the following:</p><pre><code><code>[Unit] 
Description=gunicorn daemon 
After=network.target 

[Service] 
User=ubuntu 
Group=www-data 
WorkingDirectory=/path/to/yourproject-directory 
ExecStart=path/to/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/path/to/project/project.sock yourproject.wsgi:application 

[Install] 
WantedBy=multi-user.target
</code></code></pre><blockquote><p><em><strong>Note: Replace WorkinDirectory , ExecStart path to your path</strong></em></p></blockquote><p>Now save and close the file. Next, load your service file using:</p><pre><code><code>sudo systemctl daemon-reload
</code></code></pre><p>Now start your service by:</p><pre><code><code>sudo service gunicorn start
</code></code></pre><p>By now, a socket file should have been created at your specified <strong>WorkinDirectory</strong> path: <strong>/path/to/project/project.sock</strong> if not, verify the process again and then proceed further To check gunicorn status, run:</p><pre><code><code>sudo service gunicorn status
</code></code></pre><h2><strong>Configure Nginx to Proxy Pass to Gunicorn</strong></h2><p>Now that Gunicorn is set up, we need to configure Nginx to pass traffic to the process. Start by creating and opening a new server block in Nginx&#8217;s sites-available directory:</p><pre><code><code>sudo nano /etc/nginx/sites-available/yourproject
</code></code></pre><p>Inside, open up a new server block. We will start by specifying that this block should listen on the normal port 80 and that it should respond to our server&#8217;s domain name or IP address:</p><p>Next, we will tell Nginx to ignore any problems with finding a favicon. We will also tell it where to find the static assets that we collected in our <strong>~/myproject/static</strong> directory. All of these files have a standard URI prefix of <strong>/static</strong>, so we can create a location block to match those requests:</p><p>Finally, we&#8217;ll create a <strong>location / {}</strong> block to match all other requests. Inside this location, we'll include the standard <strong>proxy_params</strong> file included with the Nginx installation and then we will pass the traffic to the socket that our Gunicorn process created:</p><pre><code><code>server { 
listen 80; 
server_name server_domain_or_IP; 
location = /favicon.ico { 
access_log off; log_not_found off; 
} 
location /static { 
alias /your-static-root-path/; 
}
location /media { 
alias /your-media-root-path/; 
}  
location / { 
include proxy_params; 
proxy_pass http://unix:/your/socket-file-path/yourproject.sock; 
} 
}
</code></code></pre><ul><li><p>Note: Change <strong>server_name</strong>, <strong>server_domain_or_IP</strong> to your domain or IP. For example example.com or 192.168.1.0</p></li><li><p>Note: Change alias** /your-static-root-path/ to your static_root** path. For example alias /home/nitin/project/static_root/</p></li><li><p>Note: Change alias <strong>/your-media-root-path/ to your media_root</strong> path. For example alias /home/nitin/project/media_root/</p></li><li><p>Note: change <strong>proxy_pass</strong> <strong>http://unix:/your/socket-file-path/yourproject.sock</strong> to your <strong>.sock</strong> file path</p></li></ul><p>Save and close the file when you are finished.</p><p>Now, we can enable the file by linking it to the sites-enabled directory:</p><pre><code><code>sudo ln -s /etc/nginx/sites-available/yourproject /etc/nginx/sites-enabled/
</code></code></pre><p>Test your Nginx configuration for syntax errors by typing:</p><pre><code><code>sudo nginx -t
</code></code></pre><p>If no errors are reported, go ahead and restart Nginx by typing:</p><pre><code><code>sudo service nginx restart
</code></code></pre><p>You should now be able to go to your server&#8217;s domain or IP address to view your application.</p><p>That's all. If you want to add HTTPS or SSL certificates to your website, check out this <strong><a href="https://tech.raturi.in/p/how-to-implement-https-django-nginx-ubuntu-letsencrypt-certbot">tutorial</a></strong>.</p>]]></content:encoded></item><item><title><![CDATA[Django Middleware: Types, Examples, And Custom Middleware]]></title><description><![CDATA[Django Middleware is a plugin system for altering Django&#8217;s request or response. Learn about various built-in middlewares plus create a custom one.]]></description><link>https://tech.raturi.in/p/understand-and-create-custom-django-middleware</link><guid isPermaLink="false">https://tech.raturi.in/p/understand-and-create-custom-django-middleware</guid><dc:creator><![CDATA[Nitin Raturi]]></dc:creator><pubDate>Mon, 10 Mar 2025 08:20:47 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/LmvHZvXnhR8]" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Middlewares are hooks to modify <strong><a href="https://tech.raturi.in/t/django">Django</a></strong> requests or response objects. You can use middleware if you want to modify the request i.e HttpRequest object which is sent to the view. Or you might want to modify the HttpResponse object returned from the view. Both these can be achieved by using middleware.</p><h2><strong>How does Django middleware work</strong></h2><p>Middleware in Django is a hook or a plugin system for altering request and response objects.</p><p>For example, let's say you have two types of <strong><a href="https://tech.raturi.in/p/how-extend-django-user-model">users</a></strong> in your application i.e., free and paid.</p><p>There are few URLs or views that a free user cannot access, so in this case either you can handle free users at every view or you can create a middleware that can handle all the free users in one place.</p><p>Now, let's discuss the types of middleware in Django.</p><h2><strong>Types of Middleware in Django</strong></h2><p>Django's middleware can be divided into 2 types: built-in and custom.</p><p><strong>Built-in Middleware</strong>: These are the default middlewares that come with Django. Few of the built-in middlewares are:</p><ul><li><p>Cache middleware</p></li><li><p>Common middleware</p></li><li><p>GZip middleware</p></li><li><p>Message middleware</p></li><li><p>Security middleware</p></li><li><p>Session middleware</p></li><li><p>Site middleware</p></li><li><p>Authentication middleware</p></li><li><p>CSRF protection middleware</p></li></ul><p>Some default middleware from <strong>settings.py</strong>.</p><pre><code><code>MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
</code></code></pre><p><strong>Custom Middleware</strong>: These are the middleware that a user creates for their purpose.</p><p>Now let's check out some of the built-in middleware.</p><h2><strong>Examples of Middleware in Django</strong></h2><p>Here, you will learn about a few of the built-in middlewares. This will help you create your custom middleware in the coming section.</p><h3><strong>Authentication middleware</strong></h3><p><strong><a href="https://docs.djangoproject.com/en/stable/topics/auth/default/#auth-web-requests">Authentication middleware</a></strong> adds the user attribute, representing the logged-in user, to every incoming request object. If the user is not logged in then it will be set as an AnonymousUser object.</p><h3><strong>Session middleware</strong></h3><p>Session middleware helps you to store arbitrary data on a per-user basis like username, email, etc on the server side.</p><p>On every request and response, a session_id is attached to the cookies that you can check in your browser through the console.</p><p>Every time a request is made, session middleware gets the stored session data for the particular session_id and attaches it to the request object.</p><p>Read more about the session middleware from the <strong><a href="https://docs.djangoproject.com/en/stable/topics/http/sessions/">official doc</a></strong>.</p><h3><strong>Message middleware</strong></h3><p>Message middleware is used to display some notification message aka flash message to the user after form submission.</p><p>You can store the message to the request object in your view and then show the message on your front end. You can check out <strong><a href="https://docs.djangoproject.com/en/stable/ref/contrib/messages/">official documentation</a></strong> for detailed usage.</p><h3><strong>CSRF middleware</strong></h3><p>CSRF middleware prevents Cross-Site Request Forgery attacks by adding hidden fields like CSRF_TOKEN to the POST forms and later validating for the correct value.</p><p>Now let's focus on another important aspect of middleware i.e., ordering</p><h2><strong>Ordering of middleware in Django</strong></h2><p>Order of the middleware is very important because a middleware can depend on the other middleware. For example Authentication Middleware depends on Session Middleware to store the authenticated user in session (request.session['user']) therefore, it must be placed after session middleware.</p><h2><strong>Custom Middleware in Django</strong></h2><p>**<strong><a href="https://docs.djangoproject.com/en/stable/topics/http/middleware/">Custom middleware in Django</a></strong> is created either as a function style that takes a get_response callable or a class-based style whose call method is used to process requests and responses. It is created inside a file <code>middleware.py</code>. A middleware is activated by adding it to the MIDDLEWARE list in Django settings. **</p><p>Very often you would have used <code>request.user</code> inside the view. Django wants <code>user</code> attribute to be set on <code>request</code> before any view executes. Django takes a middleware approach to accomplish this. So Django provides an <code>AuthenticationMiddleware</code> which can modify the request object.</p><p>%[</p><div id="youtube2-LmvHZvXnhR8]" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;LmvHZvXnhR8]&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/LmvHZvXnhR8]?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>A middleware factory is a callable that takes a <code>get_response</code> callable and returns a middleware. A middleware is a callable that takes a request and returns a response, just like a view.</p><p>A middleware can be written in two ways</p><ul><li><p><strong><a href="https://tech.raturi.in/understand-and-create-custom-django-middleware/#django-middleware-as-a-function">As a function</a></strong></p></li><li><p><strong><a href="https://tech.raturi.in/understand-and-create-custom-django-middleware/#django-middleware-as-a-class">As a class</a></strong></p></li></ul><p>The first step is to create a file <code>midleware.py</code> inside your app. Mine structure looks like this after creating the file</p><pre><code><code>custom_middleware/
&#9500;&#9472;&#9472; admin.py
&#9500;&#9472;&#9472; apps.py
&#9500;&#9472;&#9472; __init__.py
&#9500;&#9472;&#9472; middleware.py
&#9500;&#9472;&#9472; migrations
&#9474;   &#9492;&#9472;&#9472; __init__.py
&#9500;&#9472;&#9472; models.py
&#9500;&#9472;&#9472; tests.py
&#9492;&#9472;&#9472; views.py
</code></code></pre><p>Now You can follow any of the two ways of creating a middleware as a class or as a function.</p><h3><strong>Django Middleware: As a function</strong></h3><p>You can use this function based middleware code snippet inside <code>middleware.py</code></p><pre><code><code>def simple_middleware(get_response):
    # One-time configuration and initialization.

    def middleware(request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.
        print("before response")
        response = get_response(request)
        print("After response")
        # Code to be executed for each request/response after
        # the view is called.

        return response

    return middleware
</code></code></pre><h3><strong>Django Middleware: As a Class</strong></h3><p>You can use this class based middleware code snippet inside <code>middleware.py</code></p><pre><code><code>class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        print("before response")
        response = self.get_response(request)
        print("After response")
        # Code to be executed for each request/response after
        # the view is called.

        return response
</code></code></pre><h3><strong>Activating Custom Middleware</strong></h3><p>Activating a middleware is very simple, you have to add it inside the <code>MIDDLEWARE</code> list in <code>settings.py</code>. In the middleware list, each middleware component is represented by a string that is the full python path of the middleware. You can add your SimpleMiddleware at the last of the middleware list.</p><pre><code><code>MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

    'custom_middleware.middleware.SimpleMiddleware', # Class based custom Middleware
    'custom_middleware.middleware.simple_middleware', # Function based custom Middleware
]
</code></code></pre><blockquote><p><em><strong>Order of the middleware is very important because a middleware can depend on the other middleware. For example Authentication Middleware depends on Session Middleware to store the authenticated user in session (</strong></em><code>request.session['user']</code><em><strong>) therefore, it must be placed after session middleware.</strong></em></p></blockquote><p>After adding your middleware, run your server and visit the URL </p><p>http://localhost:8080/</p><pre><code><code>python manage.py runserver 0:8080
</code></code></pre><p>Now check your terminal for the <code>print</code> statements.</p><pre><code><code>Django version 3.2, using settings 'conf.settings'
Starting development server at http://0:8080/
Quit the server with CONTROL-C.
before response
After response
</code></code></pre><p>If you can see the print statements <code>before response</code> and <code>After response</code>, it means you have successfully created your own custom Django middleware.</p><p>You can check out this <code>middleware.py</code> file and all the implementation. You can also contribute new or different ways of making and working with middlewares in the same above repository.</p><p>Now, you can build a basic middleware but there is more about how <strong><a href="https://tech.raturi.in/t/django">Django's</a></strong> middleware works. Therefore let's understand the middleware structure.</p><h2><strong>Django Middleware Structure</strong></h2><p>First of all, middleware is a <strong><a href="https://tech.raturi.in/t/python">python</a></strong> class or object that is capable of processing each request and response object. Here is a complete <strong><a href="https://tech.raturi.in/p/setting-django-development-environment-for-starting-a-project">structure</a></strong> of a middleware:</p><pre><code><code>class SimpleMiddlewareStructure:

    def _init_(self, get_response):
        self.get_response = get_response

    def _call_(self, request):

        # Code that is executed in each request before the view is called

        response = self.get_response(request)

        # Code that is executed in each request after the view is called
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        # This code is executed just before the view is called
        pass

    def process_exception(self, request, exception):
        # This code is executed if an exception is raised
        pass

    def process_template_response(self, request, response):
        # This code is executed if the response contains a render() method
        return response
</code></code></pre><p>Let's understand the structure and lifecycle of middleware.</p><p>You can also overwrite these methods instead of <code>__call__</code> method:</p><ul><li><p><code>__init__(get_response)</code></p></li><li><p><code>__call__()</code></p></li><li><p><code>process_view(request, view_func, view_args, view_kwargs)</code></p></li><li><p><code>process_exception(request, exception)</code></p></li><li><p><code>process_template_response(request, response)</code></p></li></ul><p>Let's cover each method one by one.</p><p>Only the first two methods, <code>__init__</code> and <code>__call__</code>, are required by the Django framework for your middleware to work properly. The other three are special <code>hooks</code> that allow you to invoke your middleware under specific conditions. Therefore, the other three are optional.</p><h3><strong>Method 1: init() in middleware</strong></h3><p>The first method, <strong><a href="https://docs.djangoproject.com/en/4.0/topics/http/middleware/#init-get-response">init</a></strong>, is the constructor for our Python class. It is called only once, at the time the server starts up. It takes <code>get_response</code> as a parameter, which is passed by the Django itself when we add it inside the <strong>Middleware</strong> list like this: 'custom_middleware.middleware.SimpleMiddleware'</p><h3><strong>Method 2: call() in middleware</strong></h3><p><code>__call__()</code> method is called <strong>once per request</strong> .This method invokes the middleware. Here is what it looks like:</p><pre><code><code>def _call_(self, request):

        # Code that is executed in each request before the view is called

        response = self.get_response(request)

        # Code that is executed in each request after the view is called
        return response
</code></code></pre><blockquote><p><em><strong>You can add validation or feature to the request or response object before or after the view is called.</strong></em></p></blockquote><h3><strong>Method 3: process_view() in middleware</strong></h3><p><strong><a href="https://docs.djangoproject.com/en/stable/topics/http/middleware/#process-view">process_view()</a></strong> is called just before Django calls the view.</p><p>It should return either <code>None</code> or an <code>HttpResponse</code> object.</p><ul><li><p>If it returns <code>None</code>, Django will continue processing this request, executing any other <code>process_view()</code> middleware and, then, the appropriate view.</p></li><li><p>If it returns an <code>HttpResponse</code> object, Django won&#8217;t bother calling the appropriate view; it&#8217;ll apply response middleware to that <code>HttpResponse</code> and return the result.</p></li></ul><h3><strong>Method 4: process_exception() in middleware</strong></h3><p>Django calls <strong><a href="https://docs.djangoproject.com/en/stable/topics/http/middleware/#process-exception">process_exception()</a></strong> when a view raises an exception.</p><p><code>process_exception()</code> should return either None or an <code>HttpResponse</code> object.</p><ul><li><p>If it returns an <code>HttpResponse</code> object, the template response and response middleware will be applied and the resulting response returned to the browser.</p></li><li><p>Otherwise, default exception handling kicks in.</p></li></ul><h3><strong>Method 5: process_template_response() in middleware</strong></h3><p><strong><a href="https://docs.djangoproject.com/en/stable/topics/http/middleware/#process-template-response">process_template_response()</a></strong> is called just after the view has finished executing if the response instance has a render() method, indicating that it is a TemplateResponse or equivalent.</p><p>It must return a response object that implements a <code>render</code> method. It could alter the given response by changing response.template_name and response.context_data, or it could create and return a brand-new TemplateResponse or equivalent.</p><p>That's all about middleware. I hope you like it.</p>]]></content:encoded></item><item><title><![CDATA[Creating Signals In Django: An Introduction]]></title><description><![CDATA[The Django Signals is a strategy to allow decoupled applications to get notified when certain events occur.]]></description><link>https://tech.raturi.in/p/django-signals</link><guid isPermaLink="false">https://tech.raturi.in/p/django-signals</guid><dc:creator><![CDATA[Nitin Raturi]]></dc:creator><pubDate>Mon, 10 Mar 2025 08:18:01 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iH7f!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F853048bc-ea86-4674-9f79-a1695f7231de_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Django is a powerful web framework that provides developers with a wide range of tools to build web applications quickly and efficiently. One of the most useful features of Django is the ability to create signals, which allow developers to respond to events that occur within their applications.</p><p>In this article, we will discuss what signals are, how to create them, and some examples of how they can be used in Django applications.</p><h2><strong>What Are Signals?</strong></h2><p>Signals are a way for different parts of a Django application to communicate with each other. They allow one part of the application to send a message, or signal, to another part of the application when a particular event occurs.</p><p>Signals can be used to trigger actions when certain events happen within the application, such as when a user logs in or when a new record is added to the database. They can also be used to implement custom functionality, such as sending notifications or logging events.</p><h2><strong>Creating Signals in Django</strong></h2><p>To create a signal in Django, we need to define a sender and a receiver. The sender is the part of the application that sends the signal, while the receiver is the part of the application that receives the signal and responds to it.</p><h3><strong>Defining a Signal</strong></h3><p>To define a signal in Django, we first need to import the Signal class from the django.dispatch module. We can then create an instance of the Signal class, which will represent our signal.</p><pre><code><code>from django.dispatch import Signal

my_signal = Signal()
</code></code></pre><p>In this example, we have created a signal called my_signal.</p><h3><strong>Connecting a Receiver</strong></h3><p>Once we have defined our signal, we need to connect a receiver to it. A receiver is a function that will be called when the signal is sent.</p><p>To connect a receiver to a signal, we use the receiver decorator provided by Django. The receiver decorator takes two arguments: the signal to which we want to connect the receiver, and the sender of the signal.</p><pre><code><code>from django.dispatch import receiver

@receiver(my_signal, sender=MyModel)
def my_receiver(sender, **kwargs):
    # do something here
</code></code></pre><p>In this example, we have defined a receiver function called my_receiver. We have used the @receiver decorator to connect this function to our my_signal signal, and we have specified that the sender of the signal should be the MyModel class.</p><h3><strong>Sending a Signal</strong></h3><p>Now that we have defined our signal and connected a receiver to it, we can send the signal. To send a signal, we simply call the signal object and pass any data that we want to send with the signal.</p><pre><code><code>my_signal.send(sender=MyModel, data="Hello, World!")
</code></code></pre><p>In this example, we are sending our my_signal signal and specifying that the sender of the signal is the MyModel class. We are also passing some data with the signal, which will be available to the receiver function when it is called.</p><h2><strong>Examples of Using Signals in Django</strong></h2><p>Now that we know how to create and use signals in Django, let's take a look at some examples of how they can be used in practice.</p><h3><strong>Logging User Actions</strong></h3><p>One common use case for signals is logging user actions. For example, we might want to log when a user logs in or logs out of our application.</p><p>To do this, we can create a signal that is sent when a user logs in or logs out. We can then connect a receiver function that will log the event to our application's logging system.</p><pre><code><code>from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.dispatch import receiver

@receiver(user_logged_in)
def log_user_logged_in(sender, request
</code></code></pre><h2><strong>Django Built-In Signals</strong></h2><p>Here are some examples of built-in signals that Django provides:</p><h3><strong>pre_save and post_save</strong></h3><p>The pre_save and post_save signals are sent before and after a model instance is saved to the database, respectively.</p><pre><code><code>from django.db.models.signals import pre_save, post_save
from django.dispatch import receiver
from myapp.models import MyModel

@receiver(pre_save, sender=MyModel)
def my_pre_save(sender, **kwargs):
    # do something before MyModel is saved

@receiver(post_save, sender=MyModel)
def my_post_save(sender, **kwargs):
    # do something after MyModel is saved
</code></code></pre><p>In this example, we are defining two receiver functions, one for the pre_save signal and one for the post_save signal. Both of these functions are connected to the MyModel sender. The my_pre_save function will be called before the MyModel instance is saved to the database, and the my_post_save function will be called after the instance is saved.</p><h3><strong>pre_delete and post_delete</strong></h3><p>The pre_delete and post_delete signals are sent before and after a model instance is deleted from the database, respectively.</p><pre><code><code>from django.db.models.signals import pre_delete, post_delete
from django.dispatch import receiver
from myapp.models import MyModel

@receiver(pre_delete, sender=MyModel)
def my_pre_delete(sender, **kwargs):
    # do something before MyModel is deleted

@receiver(post_delete, sender=MyModel)
def my_post_delete(sender, **kwargs):
    # do something after MyModel is deleted
</code></code></pre><p>In this example, we are defining two receiver functions, one for the pre_delete signal and one for the post_delete signal. Both of these functions are connected to the MyModel sender. The my_pre_delete function will be called before the MyModel instance is deleted from the database, and the my_post_delete function will be called after the instance is deleted.</p><h3><strong>user_logged_in and user_logged_out</strong></h3><p>The user_logged_in and user_logged_out signals are sent when a user logs in or logs out of the application, respectively.</p><pre><code><code>from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.dispatch import receiver

@receiver(user_logged_in)
def log_user_logged_in(sender, request, user, **kwargs):
    # log the user login event

@receiver(user_logged_out)
def log_user_logged_out(sender, request, user, **kwargs):
    # log the user logout event</code></code></pre>]]></content:encoded></item><item><title><![CDATA[Python-Decouple: Manage Environment Variables In Django]]></title><description><![CDATA[Learn to manage environment variables for multiple django settings: development, production, testing, stage, etc]]></description><link>https://tech.raturi.in/p/manage-django-environments-secrets-using-python-decouple</link><guid isPermaLink="false">https://tech.raturi.in/p/manage-django-environments-secrets-using-python-decouple</guid><dc:creator><![CDATA[Nitin Raturi]]></dc:creator><pubDate>Mon, 10 Mar 2025 06:51:05 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iH7f!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F853048bc-ea86-4674-9f79-a1695f7231de_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>To organize your settings to have different parameters in your different environments like development and production you need to work with environment variables.</p><h2><strong>What is python-decouple</strong></h2><p><strong><a href="https://pypi.org/project/python-decouple/">python-decouple</a></strong> <strong>is a generic Python library that helps to organize settings (development, production, stage, etc) without having to redeploy the app.</strong></p><p>It was specifically built for <strong><a href="https://tech.raturi.in/t/django">Django</a></strong> but now is used to manage multiple environments or settings across <strong><a href="https://tech.raturi.in/t/python">python</a></strong> development.</p><p>Here are the advantages of using <code>python-decouple</code>:</p><ul><li><p>You can store variables in <code>.env</code> or <code>ini</code> files.</p></li><li><p>Setting default environment values.</p></li><li><p>Conversion of environment values to correct data type.</p></li></ul><h2><strong>Why not just use </strong><code>os.environ</code></h2><p>It works, but since <code>os.environ</code> only returns strings, it&#8217;s tricky.</p><p>Let&#8217;s say you have an environment variable <code>DEBUG=False</code>. If you run</p><pre><code><code>if os.environ['DEBUG']: 
  print(True) 
else: 
  print(False)</code></code></pre><p>It outputs <code>True</code>, because <code>os.environ['DEBUG']</code> returns the string <code>"False"</code>. Since it&#8217;s a non-empty string, it will be evaluated as True.</p><p><code>Python Decouple</code> provides a solution that solves this problem like this</p><pre><code><code>from decouple import config
DEBUG = config('DEBUG', cast=bool)</code></code></pre><h2><strong>Why use environment variables</strong></h2><p>A web application whether small or large will have a lot of app secrets such as <code>SECRET_KEY</code>, <code>API keys</code>, <code>database credentials</code> etc.</p><p>The convenient way for anyone to use these is to hardcode them in the source code. It works, but it is also the most <strong>insecure way</strong>. You often push the code to repositories for version management or share it among others resulting in exposing the app secrets.</p><p>The easiest and most secure way is to use these secrets as <code>environment variables</code> and import them directly into your app. <strong><a href="https://pypi.org/project/python-decouple/">Python decouple</a></strong> manages this for you. It also helps in managing application configurations and secrets based on the development <strong><a href="https://tech.raturi.in/p/installing-python-virtual-environment-ubuntu-mac-and-windows">environments</a></strong>.</p><h2><strong>How to install python decouple</strong></h2><p>You can install <code>python-decouple</code> using the command <code>pip install python-decouple</code></p><blockquote><p><em><strong>Optional: If you are not using virtual environments to install third party packages, I would strongly advice you to <a href="https://tech.raturi.in/p/installing-python-virtual-environment-ubuntu-mac-and-windows">learn about virtual environment</a> to avoid version issues later.</strong></em></p></blockquote><h2><strong>How to use python decouple in django</strong></h2><p><strong>Step 1</strong>: Create a <code>.env</code> file at the root level of your project</p><pre><code><code>project
--- project
------ settings.py
------ urls.py
------ wsgi.py
--- .env</code></code></pre><p><strong>Step 2</strong>: Set your environment variables inside <code>.env</code> file, I have set mine like this:</p><pre><code><code>DEBUG=True
SECRET_KEY=ARANDOMSECRETKEY
DB_HOST=HOSTNAME
DB_PASSWORD=PASSWORD</code></code></pre><p><strong>Step3</strong>: In your <code>settings.py</code>, access your environment variables like this:</p><pre><code><code>from decouple import config

SECRET_KEY = config('SECRET_KEY')
DEBUG = config('DEBUG', cast=bool)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': config('DB_NAME'),
     'USER': config('DB_USER'),
        'PASSWORD': config('DB_PASSWORD'),
        'HOST': config('DB_HOST'),
        'PORT':''
    }
}</code></code></pre><p>That's it for setting up a basic configuration, if you want to know more have a look at the <strong><a href="https://pypi.org/project/python-decouple/">python-decouple official doc</a></strong>.</p><blockquote><p><em><strong>Note: Add .env file to </strong></em><code>.gitignore</code><em><strong>, every user should have their own seperate </strong></em><code>.env</code><em><strong> file which should not be pushed alongwith your repository.</strong></em></p></blockquote><p>A code snippet of <strong>python-decouple</strong> with django taken from the <strong><a href="https://pypi.org/project/python-decouple/#id9">offical python-decouple doc</a></strong>.</p><pre><code><code># coding: utf-8
from decouple import config
from unipath import Path
from dj_database_url import parse as db_url


BASE_DIR = Path(__file__).parent

DEBUG = config('DEBUG', default=False, cast=bool)
TEMPLATE_DEBUG = DEBUG

DATABASES = {
    'default': config(
        'DATABASE_URL',
        default='sqlite:///' + BASE_DIR.child('db.sqlite3'),
        cast=db_url
    )
}

TIME_ZONE = 'America/Sao_Paulo'
USE_L10N = True
USE_TZ = True

SECRET_KEY = config('SECRET_KEY')

EMAIL_HOST = config('EMAIL_HOST', default='localhost')
EMAIL_PORT = config('EMAIL_PORT', default=25, cast=int)
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD', default='')
EMAIL_HOST_USER = config('EMAIL_HOST_USER', default='')
EMAIL_USE_TLS = config('EMAIL_USE_TLS', default=False, cast=bool)</code></code></pre><h2><strong>How to manage multiple django enviroment</strong></h2><p>Managing multiple environments is the most common requirement when we work in a team and across multiple servers like local or development, testing, staging, and production.</p><p>To solve this problem, you should have <code>.env.template</code> file at the root of your repository and this file should be pushed to your repository. Now any team member can follow this <code>.env.template</code> file to create <code>.env</code> file in their own system with their own set of values and the same with multiple servers.</p><p>That's it. I hope you can now manage environment variables.</p>]]></content:encoded></item><item><title><![CDATA[Django Https And Free Letsencrypt Ssl Certificates]]></title><description><![CDATA[Generate SSL (Https) certificates for your django website using certbot and letsencrypt for free. Forever!]]></description><link>https://tech.raturi.in/p/how-to-implement-https-django-nginx-ubuntu-letsencrypt-certbot</link><guid isPermaLink="false">https://tech.raturi.in/p/how-to-implement-https-django-nginx-ubuntu-letsencrypt-certbot</guid><dc:creator><![CDATA[Nitin Raturi]]></dc:creator><pubDate>Mon, 10 Mar 2025 06:49:02 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iH7f!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F853048bc-ea86-4674-9f79-a1695f7231de_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>To set up SSL certificates on the Django application, certbot is used.</strong> <strong><a href="https://certbot.eff.org/">Certbot</a></strong> <strong>gets free SSL (HTTPS) certificates from</strong> <strong><a href="https://letsencrypt.org/">Let's Encrypt</a></strong> <strong>Forever.</strong></p><p>In this article, I am assuming that you already have a <strong><a href="https://tech.raturi.in/tag/django/">Django</a></strong> website up and running using the Nginx web server on HTTP protocol. You can refer to the current <strong><a href="https://tech.raturi.in/p/setting-django-development-environment-for-starting-a-project">Django project structure</a></strong> and <strong><a href="https://tech.raturi.in/p/setup-python3-django-nginx-gunicorn-and-postgresql">deployment instructions</a></strong> if needed.</p><blockquote><p><em><strong>Note: This article is tested on the following tech stack: django, gunicorn, nginx, ubuntu 16. Steps are similar for other versions of ubuntu as well but if you get stuck somewhere, you can follow the instructions from the <a href="https://certbot.eff.org/">official documentation</a>.</strong></em></p></blockquote><h2><strong>Install Certbot</strong></h2><p>First, ssh into your server as a <strong>sudo</strong> user and run the commands below to install certbot.</p><pre><code><code>sudo apt-get update 
sudo apt-get install software-properties-common 
sudo add-apt-repository universe 
sudo add-apt-repository ppa:certbot/certbot 
sudo apt-get update sudo apt-get install certbot python-certbot-nginx</code></code></pre><p>If you face issues while installing certbot via the above commands, install it via snapd otherwise directly jump to the next section. Follow these instructions to install snapd from the <strong><a href="https://snapcraft.io/docs/installing-snapd">snapd official documentation</a></strong>.</p><p>Once snapd is installed, ensure that it's up to date</p><pre><code><code>sudo snap install core; sudo snap refresh core</code></code></pre><p>Remove the previously installed certbot packages via apt to avoid any conflict between apt and snap.</p><pre><code><code>sudo apt-get remove certbot</code></code></pre><p>Now, install certbot via snap.</p><pre><code><code>sudo snap install --classic certbot</code></code></pre><p>At last, link the installed snap to the user bin directory to access it globally.</p><pre><code><code>sudo ln -s /snap/bin/certbot /usr/bin/certbot</code></code></pre><h2><strong>Generating SSL certificates using certbot</strong></h2><p>Let certbot do this automatically, generating certificates and editing the Nginx config file to serve these certificates.</p><pre><code><code>sudo certbot --nginx</code></code></pre><p>Here, you will be asked to enter the names of the website you want to activate HTTPS for, something like this:</p><pre><code><code>Which names would you like to activate HTTPS for? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
1: raturi.in 
2: www.raturi.in</code></code></pre><p>Enter the corresponding number with a comma(,) if you have more than 1 website you want to add HTTPS and press enter. After that fill in the details, it asks, and proceed.</p><p>Finally, restart your Nginx server for the changes to reflect.</p><pre><code><code>sudo service nginx restart</code></code></pre><p>Now, visit your domain, you can check HTTPS there.</p><blockquote><p><em><strong>Note: If you don't want certbot to automatically edit your Nginx file, you can generate the certificates only using </strong></em><code>sudo certbot certonly --nginx</code><em><strong> and server these certificates manually.</strong></em></p></blockquote><h2><strong>Certbot Automating renewal</strong></h2><p>The Certbot packages on your system come with a cron job that will renew your certificates automatically before they expire. Since Let's Encrypt certificates last for 90 days, it's highly advisable to take advantage of this feature. You can test automatic renewal for your certificates by running this command</p><pre><code><code>sudo certbot renew --dry-run</code></code></pre>]]></content:encoded></item></channel></rss>