<?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"><channel><title><![CDATA[Rachit Khurana]]></title><description><![CDATA[Rachit Khurana]]></description><link>https://blog.rachitkhurana.tech</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1752267888841/9a4a5174-b06e-4b6c-a644-c8fe53b7f0f1.jpeg</url><title>Rachit Khurana</title><link>https://blog.rachitkhurana.tech</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 17 May 2026 09:20:14 GMT</lastBuildDate><atom:link href="https://blog.rachitkhurana.tech/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Implementing App notifications: The FOSS way]]></title><description><![CDATA[The Beginning: Building My First "Real" App
Recently, I embarked on building a Splitwise-like expense-splitting app using React Native and Expo. This wasn't just another side project—it was my first proper dive into this tech stack, with React Native...]]></description><link>https://blog.rachitkhurana.tech/implementing-app-notifications-the-foss-way</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/implementing-app-notifications-the-foss-way</guid><category><![CDATA[Open Source]]></category><category><![CDATA[Android]]></category><category><![CDATA[Mobile Development]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Sat, 12 Jul 2025 06:32:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752318032494/95863616-8927-483a-b3a2-a838a1db04f9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-the-beginning-building-my-first-real-app">The Beginning: Building My First "Real" App</h2>
<p>Recently, I embarked on building a Splitwise-like expense-splitting app using React Native and Expo. This wasn't just another side project—it was my first proper dive into this tech stack, with React Native for mobile development and Golang powering the backend.</p>
<p>From the start, I had one clear goal: <strong>avoid third-party dependencies wherever possible</strong>. No BaaS solutions like Supabase, Appwrite, or Firebase. I wanted to build everything myself to truly understand the underlying technologies.</p>
<p>This philosophy led me down some interesting rabbit holes. I even implemented native Google Login without relying on any auth provider service—quite challenging since Expo's official Documentation's free solution was being deprecated, and the new approach was locked behind a SaaS paywall. But I persevered and found a way to make it work using a package that used the native credential manager APIs and worked great.</p>
<h2 id="heading-the-notification-wall">The Notification Wall</h2>
<p>Then came the next feature: <strong>push notifications</strong>.</p>
<p>A quick Google search seemed to confirm what every developer "knows"—Firebase Cloud Messaging (FCM) is <em>the</em> solution for mobile notifications. FCM appeared to be the only viable option.</p>
<p>Reluctantly, I integrated FCM into both my app and backend. It worked.</p>
<h2 id="heading-the-f-droid-reality-check">The F-Droid Reality Check</h2>
<p>Everything changed when I decided to release my app on <strong>F-Droid</strong>—the open-source Android app marketplace.</p>
<p>That's when I discovered F-Droid's strict policy: apps must be completely open source and cannot depend on any proprietary services. My FCM integration meant I will not be able to release my app on F-Droid.</p>
<p>But this sparked a crucial question: <em>If other apps on F-Droid support notifications, there must be alternatives to FCM, right?</em></p>
<h2 id="heading-down-the-rabbit-hole-discovering-unifiedpush">Down the Rabbit Hole: Discovering UnifiedPush</h2>
<p>This question sent me deep into research mode. And that's when I stumbled upon something revolutionary: <a target="_blank" href="https://unifiedpush.org/"><strong>UnifiedPush</strong></a>.</p>
<blockquote>
<p><strong>UnifiedPush</strong> is a decentralized push notification system that lets you choose the service you want to use. It's designed to be privacy-friendly, flexible, and open—making it perfect if you want control over your push notifications.</p>
</blockquote>
<p>Instead of forcing all notifications through a single company's servers (like FCM), UnifiedPush lets <strong>users choose their notification provider</strong>. This was a paradigm shift I hadn't considered.</p>
<h2 id="heading-understanding-the-foundation-webpush-and-vapid">Understanding the Foundation: WebPush and VAPID</h2>
<p>To truly grasp UnifiedPush, I needed to understand how notifications actually work. This led me to discover the open standards that power web notifications:</p>
<h3 id="heading-webpush-protocolhttpstoolsietforghtmlrfc8030"><a target="_blank" href="https://tools.ietf.org/html/rfc8030">WebPush Protocol</a></h3>
<p>This is a <strong>W3C standard</strong> that defines how push notifications work on the web. It's the foundation that browsers use for notifications.<br />WebPush is defined by 3 standards: for the transport (RFC8030), for the authorization (VAPID, RFC8292), for the encryption (RFC8291)</p>
<h3 id="heading-vapid-voluntary-application-server-identificationhttpsdatatrackerietforgdochtmlrfc8292"><a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc8292">VAPID (Voluntary Application Server Identification)</a></h3>
<p>Think of this as a way for your server to prove its identity when sending notifications. Instead of using proprietary API keys tied to specific services, you generate your own cryptographic key pair:</p>
<ul>
<li><p><strong>Public key</strong>: Identifies your app</p>
</li>
<li><p><strong>Private key</strong>: Signs your messages</p>
</li>
</ul>
<p>What's beautiful about this approach is that it's <strong>service-agnostic</strong>. The same VAPID keys and WebPush messages work whether the user chooses Google's servers, a self-hosted solution, or anything in between.</p>
<p><strong>Privacy by Design</strong>: Here's a crucial security feature that sets webpush apart—<strong>encryption</strong>. When your server sends a notification, the message is encrypted using the user webpush keys. This means:</p>
<ul>
<li><p>✅ <strong>Only your app can decrypt the notification content</strong></p>
</li>
<li><p>✅ <strong>Distributors (ntfy, NextPush, etc.) cannot read your messages</strong></p>
</li>
<li><p>✅ <strong>Even if using FCM as a distributor, Google cannot see your data</strong></p>
</li>
<li><p>✅ <strong>True privacy regardless of which distributor the user chooses</strong></p>
</li>
</ul>
<p>This is fundamentally different from traditional FCM, where Google's servers can potentially access all notification content. With UnifiedPush's VAPID encryption, the distributor is just a secure messenger—they can deliver your encrypted package, but they can't open it.</p>
<h3 id="heading-the-mobile-connection">The Mobile Connection</h3>
<p>Here's the key insight: <strong>mobile devices can receive WebPush notifications too</strong>. The same standards that power web notifications work on mobile platforms.</p>
<h2 id="heading-how-unifiedpush-works">How UnifiedPush Works</h2>
<p>UnifiedPush elegantly bridges the gap between open standards and mobile notifications:</p>
<h3 id="heading-the-flow">The Flow</h3>
<pre><code class="lang-plaintext">Step 1: App Sends Notification
Your server sends a WebPush message to the user's chosen distributor

Step 2: Distributor Delivers Notification  
The distributor receives the message and forwards it to your app

Step 3: Device Receives Notification
Your app wakes up and processes the data, showing a notification to the user
</code></pre>
<h3 id="heading-what-are-distributors">What Are Distributors?</h3>
<p><strong>Distributors</strong> (or Notification Providers) are apps that run in the background and handle notification delivery. Users can choose from various options:</p>
<ul>
<li><p><a target="_blank" href="https://play.google.com/store/apps/details?id=io.heckel.ntfy"><strong>ntfy</strong></a>: Self-hosted, maximum privacy</p>
</li>
<li><p><a target="_blank" href="https://f-droid.org/en/packages/org.unifiedpush.distributor.sunup/"><strong>Sunup</strong></a>: Uses Mozilla's Push Servers</p>
</li>
<li><p><a target="_blank" href="https://play.google.com/store/apps/details?id=org.unifiedpush.distributor.fcm"><strong>gCompat-UP</strong></a>: Uses Google's infrastructure as a fallback</p>
</li>
<li><p><strong>Custom solutions</strong>: Roll your own</p>
</li>
</ul>
<p><img src="https://us-east-1.tixte.net/uploads/dilutewater.is-from.space/Screencast_20250711_202611.gif" alt="UnifiedPush Flow" /></p>
<h2 id="heading-the-elegant-solution-embedded-distributors">The Elegant Solution: Embedded Distributors</h2>
<p>Now, you might be thinking: "This sounds great, but requiring users to install another app seems like a UX nightmare. Users will have to install another app"</p>
<p>Here's where UnifiedPush gets really clever: <a target="_blank" href="https://unifiedpush.org/news/20250131_push_for_decentralized/#webpush-to-google-services"><strong>embedded distributor modules</strong></a>.</p>
<h3 id="heading-how-it-works">How It Works</h3>
<p>UnifiedPush provides an embedded distributor that your app can use internally. When using this embedded module:</p>
<ol>
<li><p>Your app registers for notifications directly with FCM endpoints</p>
</li>
<li><p><strong>No Firebase project or configuration required</strong></p>
</li>
<li><p><strong>No Firebase libraries needed</strong></p>
</li>
<li><p>FCM natively supports WebPush and VAPID standards</p>
</li>
</ol>
<p>This means you can send notifications to your app using direct FCM endpoints without any Firebase setup—just pure WebPush with VAPID authentication.</p>
<h3 id="heading-the-best-of-both-worlds">The Best of Both Worlds</h3>
<p>My implementation strategy became clear:</p>
<pre><code class="lang-plaintext">1. Check if user has any external distributors installed
2. If yes → Give them the option to choose their preferred distributor  
3. If no → Use the embedded distributor seamlessly
</code></pre>
<p>This approach provides:</p>
<ul>
<li><p><strong>Zero UX friction</strong> for mainstream users</p>
</li>
<li><p><strong>Full choice and privacy</strong> for power users</p>
</li>
<li><p><strong>F-Droid compatibility</strong></p>
</li>
</ul>
<h2 id="heading-the-implementation-reality">The Implementation Reality</h2>
<h3 id="heading-server-side-changes">Server-Side Changes</h3>
<p>The backend migration was surprisingly straightforward. I simply replaced the Firebase library with a standard web-push library. Instead of dealing with Firebase service accounts and complex authentication, I just needed:</p>
<ol>
<li><p>Generate VAPID key pairs</p>
</li>
<li><p>Use WebPush protocol for sending notifications</p>
</li>
<li><p>Handle subscription management</p>
</li>
</ol>
<h3 id="heading-mobile-app-integration">Mobile App Integration</h3>
<p>On the React Native side, replacing FCM with UnifiedPush was not exactly smooth for me. The <a target="_blank" href="https://github.com/juandjara/expo-unified-push"><code>expo-unified-push</code></a> library provided a cleaner API than Firebase's implementation, with better debugging capabilities and more predictable behavior.</p>
<h3 id="heading-the-debugging-nightmare-and-its-embarrassingly-simple-solution">The Debugging Nightmare (And Its Embarrassingly Simple Solution)</h3>
<p>However, I hit a frustrating wall.</p>
<p><strong>The Problem</strong>: Notifications worked perfectly when my app was in the foreground, but completely failed when the app was closed or in the background. This is obviously a deal-breaker for any notification system.</p>
<p><strong>My Desperate Debugging Journey</strong>:</p>
<ul>
<li><p>Spent countless hours debugging the UnifiedPush library source code</p>
</li>
<li><p>Tried different distributors, thinking it was distributor-specific</p>
</li>
<li><p>Even <strong>forked the</strong> <code>expo-unified-push</code> repository and made custom modifications</p>
</li>
<li><p>Used my own version of the library as the npm package instead</p>
</li>
<li><p>Tested various permission configurations and background processing settings</p>
</li>
</ul>
<p><img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foemg84iiad2l89cv254y.png" alt="Me debugging for hours" /></p>
<p><em>Me debugging for hours</em></p>
<p><strong>The False Victory</strong>: My forked version seemed to work initially, which made me think I'd solved some complex architectural issue. I was ready to write a detailed post about the "fixes" needed for background notifications.</p>
<p><strong>The Humbling Reality</strong>: The next day, after seeing the developer's comments, I discovered the real culprit. It wasn't the library, the distributors, or any complex background processing limitation.</p>
<p><strong>The actual issue</strong>: The notification <code>id</code> field format.</p>
<p>I had been either:</p>
<ul>
<li><p>Omitting the <code>id</code> field entirely, or</p>
</li>
<li><p>Using hexadecimal IDs (like MongoDB ObjectIds or UUIDs)</p>
</li>
</ul>
<p><strong>The solution</strong>: Unified push library requires notification IDs to be <strong>numeric only</strong>.</p>
<p><img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftunap3rrf08ll9o52qmw.gif" alt="Facepalm" /></p>
<p><em>Me realizing the bug was just using wrong ID format</em></p>
<p><strong>The Lesson</strong>: Sometimes the most frustrating bugs have the simplest solutions. What felt like a fundamental architectural problem was actually a basic data format requirement that I'd overlooked.</p>
<h3 id="heading-the-community-that-made-all-the-difference">The Community That Made All the Difference</h3>
<p>Throughout this debugging nightmare, I wasn't struggling alone. The <strong>UnifiedPush community on Matrix</strong> was incredibly supportive and patient with my questions.</p>
<p>Even when I was going down the wrong path with my forked library approach, the community helped me think through the problem systematically. They suggested checking payload formats, testing with different distributors, and reviewing the notification ID requirements—which ultimately led me to discover the numeric ID issue.</p>
<p><strong>The human side of open source</strong>: This experience reminded me why I love open source communities. Instead of being stuck with corporate support tickets or waiting for Stack Overflow responses, I had direct access to the people building and maintaining the tools I was using. They were invested in my success because my success meant UnifiedPush was working for more developers.</p>
<h2 id="heading-the-results-better-than-expected">The Results: Better Than Expected</h2>
<h3 id="heading-user-experience-wins">User Experience Wins</h3>
<ul>
<li><p><strong>Mainstream users</strong>: Zero change in experience—notifications "just work"</p>
</li>
<li><p><strong>Privacy-conscious users</strong>: Full control over notification routing</p>
</li>
<li><p><strong>Degoogled device users</strong>: Finally have access to full app functionality</p>
</li>
</ul>
<h2 id="heading-the-ios-reality-apples-walled-garden">The iOS Reality: Apple's Walled Garden</h2>
<p>Now, let's address the elephant in the room: <strong>iOS</strong>.</p>
<p>Apple's ecosystem presents unique challenges for alternative notification systems. Unlike Android, where users can install alternative app stores and modify system behavior, iOS maintains strict control over push notifications through APNs (Apple Push Notification service).</p>
<p><strong>The Current iOS Situation:</strong></p>
<ul>
<li><p>All iOS notifications must go through Apple's APNs servers</p>
</li>
<li><p>No alternative notification distributors allowed</p>
</li>
<li><p>Users cannot choose their notification provider</p>
</li>
<li><p>Apps distributed outside the App Store (sideloaded) still require APNs for notifications</p>
</li>
</ul>
<p>Apple being apple, they have won't allow any third-party notification systems to replace APNs. They won't wanna give up control over notifications, which is a shame because it limits user choice and privacy.</p>
<h2 id="heading-whats-next">What's Next?</h2>
<p>I will soon be releasing my app on F-Droid (Hopefully)</p>
<p>But more importantly, I've discovered an entire ecosystem of developers building user-centric, privacy-respecting technology. The UnifiedPush community is growing rapidly, with major apps like <a target="_blank" href="https://element.io/">Element</a>, <a target="_blank" href="https://tusky.app/">Tusky</a>, and <a target="_blank" href="https://fluffychat.im/">FluffyChat</a> all adopting this approach.</p>
<h2 id="heading-for-fellow-developers">For Fellow Developers</h2>
<p>If you're building mobile apps and care about user privacy, open standards, or F-Droid compatibility, I highly recommend exploring UnifiedPush. The implementation is often simpler than traditional solutions, and your users will appreciate having real choice in how their data flows.</p>
<p>The future of mobile notifications doesn't have to be controlled by Big Tech. We can build something better—something that puts users first.</p>
<h2 id="heading-resources">Resources</h2>
<p><a target="_blank" href="https://unifiedpush.org/news/20250131_push_for_decentralized/">https://unifiedpush.org/news/20250131_push_for_decentralized/</a><br /><a target="_blank" href="https://unifiedpush.org/">https://unifiedpush.org/</a><br /><a target="_blank" href="https://developer.chrome.com/blog/web-push-interop-wins">https://developer.chrome.com/blog/web-push-interop-wins</a></p>
<hr />
<p><em>Want to follow my journey building privacy-first mobile apps? Connect with me or check out my other projects!</em></p>
]]></content:encoded></item><item><title><![CDATA[Building a RAG with Supabase Vector & OpenAI]]></title><description><![CDATA[As AI continues to evolve, one of the limitations of generative AI is its tendency to hallucinate—producing inaccurate or nonsensical outputs, especially when it lacks relevant context. This is where Retrieval-Augmented Generation (RAG) comes in. RAG...]]></description><link>https://blog.rachitkhurana.tech/building-a-rag-with-supabase-vector-openai</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/building-a-rag-with-supabase-vector-openai</guid><category><![CDATA[AI]]></category><category><![CDATA[supabase]]></category><category><![CDATA[Azure]]></category><category><![CDATA[RAG ]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Mon, 16 Sep 2024 11:55:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1726487437379/18373414-7667-4187-a7e2-466b632234dc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As AI continues to evolve, one of the limitations of generative AI is its tendency to hallucinate—producing inaccurate or nonsensical outputs, especially when it lacks relevant context. This is where <strong>Retrieval-Augmented Generation (RAG)</strong> comes in. RAG combines a large language model (LLM) with a knowledge retriever, helping provide context to queries and significantly improving accuracy. In this blog, we’ll explore how to build a RAG system for image descriptions using <strong>Supabase Vector</strong> and <strong>Azure OpenAI</strong>.</p>
<h2 id="heading-what-is-rag">What is RAG??</h2>
<p>When we normally run a query in any LLM, it processes it and gives response according to the data it has been trained on. But what if the query asked something it has not been trained on? That’s where RAG comes in. <strong>Retrieval-Augmented Generation (RAG)</strong> basically allows us to provide the missing context to the query so that the LLM can respond more accurately. The query is first sent to a knowledge retriever that can retrieve the relevant context/information. After that, the context from the relevant information is added to the query and then the query is sent to the LLM.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726487245388/eaf1ecee-4176-4daa-b3ca-7761a34e7fb8.png" alt class="image--center mx-auto" /></p>
<p>So how exactly are we going to build a Knowledge retrieval?? For that we would be storing the data in Vector format. Vector embeddings are numerical representations of data, including text or images, in a multi-dimensional space. Similar items are grouped closer together, allowing us to search semantically. For example, images with similar descriptions would have embeddings close to one another, enabling <strong>semantic search</strong>.</p>
<h2 id="heading-lets-build-an-image-based-rag">Let’s Build an Image-Based RAG</h2>
<h3 id="heading-1-uploading-and-storing-the-image"><strong>1. Uploading and Storing the Image</strong></h3>
<p>We begin by uploading an image and storing it in <strong>Supabase Storage</strong>. Using the following code, we handle the image upload and return a publicly accessible URL.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">upload_image</span>(<span class="hljs-params">image, name, img_type</span>):</span>
    temp = BytesIO()
    image.save(temp, format=<span class="hljs-string">'PNG'</span>)
    res = supabase.storage.from_(<span class="hljs-string">"images"</span>).upload(file=temp.getvalue(), path=<span class="hljs-string">f"<span class="hljs-subst">{name}</span>"</span>, file_options={<span class="hljs-string">"content-type"</span>: img_type})
    url = supabase.storage.from_(<span class="hljs-string">'images'</span>).get_public_url(name)
    <span class="hljs-keyword">return</span> url
</code></pre>
<h3 id="heading-2-generating-an-image-description"><strong>2. Generating an Image Description</strong></h3>
<p>Next, we use Azure OpenAI’s powerful LLM to generate a description for the image. I am using Azure OpenAI, however you can use any multimodal llm.</p>
<p>Here’s the code for generating that description:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generate_image_description</span>(<span class="hljs-params">url</span>):</span>
    headers = {<span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>, <span class="hljs-string">"api-key"</span>: os.getenv(<span class="hljs-string">"AZURE_OPENAI_API_KEY"</span>)}
    payload = {<span class="hljs-string">"messages"</span>: [{<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are a helpful assistant."</span>}, {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: [{<span class="hljs-string">"type"</span>: <span class="hljs-string">"text"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"Generate a description for this image:"</span>}, {<span class="hljs-string">"type"</span>: <span class="hljs-string">"image_url"</span>, <span class="hljs-string">"image_url"</span>: {<span class="hljs-string">"url"</span>: url}}]}]}
    response = requests.post(ENDPOINT, headers=headers, json=payload)
    <span class="hljs-keyword">return</span> response.json()[<span class="hljs-string">"choices"</span>][<span class="hljs-number">0</span>][<span class="hljs-string">"message"</span>][<span class="hljs-string">"content"</span>]
</code></pre>
<p>This provides a meaningful textual description of the image, which we use in the next step.</p>
<h3 id="heading-3-creating-embeddings"><strong>3. Creating Embeddings</strong></h3>
<p>With the description ready, we convert it into vector embeddings using Azure OpenAI. These embeddings are crucial for enabling search functionality:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generate_embeddings</span>(<span class="hljs-params">description</span>):</span>
    headers = {<span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>, <span class="hljs-string">"api-key"</span>: os.getenv(<span class="hljs-string">"AZURE_OPENAI_API_KEY"</span>)}
    payload = {<span class="hljs-string">"input"</span>: description, <span class="hljs-string">"model"</span>: <span class="hljs-string">"text-embedding-3-small"</span>}
    response = requests.post(ENDPOINT, headers=headers, json=payload)
    <span class="hljs-keyword">return</span> response.json()[<span class="hljs-string">"data"</span>][<span class="hljs-number">0</span>][<span class="hljs-string">"embedding"</span>]
</code></pre>
<p>This code transforms the image description into a vector embedding, making it searchable.</p>
<h3 id="heading-4-saving-the-embedding"><strong>4. Saving the Embedding</strong></h3>
<p>We store these embeddings in <strong>Supabase Vector</strong>, allowing us to efficiently search through them later.</p>
<p>To use vectors, you need to enable that in Supabase. For that, go to your supabase dashboard and select your database. Then click on extensions and finally search and enable the <code>vector</code> extension.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">save_embedding</span>(<span class="hljs-params">name, embedding, url</span>):</span>
    embeddings = vx.get_or_create_collection(name=<span class="hljs-string">"docs"</span>, dimension=<span class="hljs-number">1536</span>)
    vectors = [(name, embedding, {<span class="hljs-string">"url"</span>: url})]
    embeddings.upsert(vectors)
</code></pre>
<p>The whole upload workflow will be like the following:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726487292892/4022431b-fa3f-43cd-8ff2-f4d900ac4f19.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-5-querying-the-images"><strong>5. Querying the Images</strong></h3>
<p>When users query an image, we generate a vector embedding for their query and use it to search through the stored embeddings to find the most relevant match:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">query_images</span>(<span class="hljs-params">query</span>):</span>
    embeddings = generate_embeddings(query)
    docs = vx.get_collection(name=<span class="hljs-string">"docs"</span>)
    results = docs.query(embeddings, limit=<span class="hljs-number">1</span>, include_metadata=<span class="hljs-literal">True</span>)
    <span class="hljs-keyword">return</span> results[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>][<span class="hljs-string">"url"</span>]
</code></pre>
<p>The vector search identifies the most similar image based on its embeddings, and the corresponding URL is returned.</p>
<p>And the whole query workflow will be like the following:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726487318390/028731ea-9216-4e61-946c-96ee87ea9a02.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-adding-a-simple-ui-with-streamlit"><strong>Adding a Simple UI with Streamlit</strong></h3>
<p>Now that we’ve built the backend logic for our RAG system using Supabase and Azure OpenAI, it’s time to add a user-friendly interface. I used streamlit since it allows me to quickly build a clean UI using very little python code. It has a lot of prebuilt components that we can use directly.</p>
<p>You can find the whole code on my GitHub repository: <a target="_blank" href="https://github.com/notnotrachit/Sample-Rag">https://github.com/notnotrachit/Sample-Rag</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>By using <strong>Supabase Vector</strong> and <strong>Azure OpenAI</strong>, we can build a RAG system that efficiently retrieves relevant data (images in our case) and augments the language model’s responses. This approach not only improves the quality of the generated content but also addresses one of the major limitations of LLMs—hallucination.</p>
<p>Git Repo: <a target="_blank" href="https://github.com/notnotrachit/Sample-Rag">https://github.com/notnotrachit/Sample-Rag</a></p>
<p>I also gave a talk on this topic recently at the Supabase LW12 Noida Meetup, so you can also check out the slides for your reference: <a target="_blank" href="https://www.canva.com/design/DAGOzSBkY4U/9lxkf7dNpDSvY_0nZSqD8Q/view?utm_content=DAGOzSBkY4U&amp;utm_campaign=designshare&amp;utm_medium=link&amp;utm_source=editor">Slides Link</a></p>
]]></content:encoded></item><item><title><![CDATA[Deploy Django to Azure - The Easy Way]]></title><description><![CDATA[The general perception is that deploying applications on the cloud is complicated, but that is not always true. We have really easy ways to deploy stuff on the cloud as well. So I will be demonstrating how to deploy Django Webpps to Azure easily. 
Pr...]]></description><link>https://blog.rachitkhurana.tech/deploy-django-to-azure-the-easy-way</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/deploy-django-to-azure-the-easy-way</guid><category><![CDATA[Web Development]]></category><category><![CDATA[Django]]></category><category><![CDATA[Azure]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Cloud Computing]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Thu, 11 Jul 2024 12:26:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700663233/0ab67771-1d84-48e3-92ab-42eaec5d272c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The general perception is that deploying applications on the cloud is complicated, but that is not always true. We have really easy ways to deploy stuff on the cloud as well. So I will be demonstrating how to deploy Django Webpps to Azure easily. </p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li>Azure account</li>
</ul>
<p>If you don’t have an azure account yet, no issues, you can signup for free and get 200USD credits for the first month <a target="_blank" href="https://azure.microsoft.com/free/?wt.mc_id=studentamb_285271">here</a> . </p>
<p>If you are a student and don’t have a credit card, no worries. You can sign up for Azure for Students and get $100 credit for free using your student email ID <a target="_blank" href="https://azure.microsoft.com/free/students/?wt.mc_id=studentamb_285271">here</a>. (Can be renewed annually as long as you are a student)</p>
<ul>
<li>Hosted database</li>
</ul>
<p>If you have a web app on Django that is dependent on a database, make sure it is using a hosted database instead of the default SQLite database. The hosted database can be anywhere, be it Azure itself, or you can use <a target="_blank" href="http://neon.tech">neon.tech</a> as well. </p>
<ul>
<li>A django project ofcourse (😆)</li>
</ul>
<p>For this blog, I will be using my demo app, which is in this repository: https://github.com/notnotrachit/django_todolist_demo_sample</p>
<p>Keep in mind that my sample app is not dependent on any database, its just using the client’s localstorage, if your app is dependent on the database then it is highly recommended to first add a hosted database and configure it accordingly. 
You can refer to django’s docs for the same: <a target="_blank" href="https://docs.djangoproject.com/en/5.0/ref/databases">https://docs.djangoproject.com/en/5.0/ref/databases</a></p>
<p>If you are still facing issues, kindly let me know, I will make another blog regarding the same. </p>
<h2 id="heading-lets-deploy">Lets Deploy</h2>
<h3 id="heading-1-make-a-github-repository">1) Make a GitHub repository</h3>
<p>Make sure you make a GitHub repository and make sure you push all your code to that repository. The repository can be public or private. </p>
<h3 id="heading-2-head-over-to-azure-portal">2) Head over to Azure Portal</h3>
<p>Go to the azure portal’s home page at:  <a target="_blank" href="https://portal.azure.com/#home?wt.mc_id=studentamb_285271">https://portal.azure.com/#home</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700612406/d2576c77-0467-4d2c-abd7-4742e4eb368a.png" alt="Azure Portal Homescreen" /></p>
<p>You might see a different kind of homepage. Since I already have many things deployed, it shows up differently for me, but don’t worry—the process remains the same. </p>
<h3 id="heading-3-creating-an-app-service">3) Creating an App Service</h3>
<p>We will be deploying our webapp using Azure App Service. Azure App service is a really amazing service that we can use to very easily deploy our webapps to the cloud without worrying or configuring any infrastructure. It handles that automatically. </p>
<p>To create a service, search for 'App Service' in the top search bar and click on it. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700614114/1f79454d-f6d5-4b21-af03-519f3b091911.png" alt="Azure search bar" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700615742/767aa4f5-8aeb-4f5a-82f5-00f9eb838485.png" alt="Azure app service" /></p>
<p>You might see an empty list. </p>
<p>Now you need to click on <code>Create</code> and then select <code>Web App</code> </p>
<p>After that a long form type page will open up.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700617178/a845c492-45db-4fa4-bf76-5c5713c94bec.png" alt="Create app service" /></p>
<p>The first field is for the subscription. It will most likely be prefilled. If not, select your subscription from the dropdown.</p>
<p>Next is the resource group. You can leave it for now; it will be automatically created once we assign a name.</p>
<p>Now, we need to set a name for our web app. This name needs to be globally unique. 
In publish option, leave code as selected. </p>
<p>In the Runtime Stack, select Python 3.10 or higher
Next you can select the region or leave it at the default as well. </p>
<p>Next, you will see under Pricing plan that a new Linux plan has already been created for you. 
You can now select the pricing plan according to your needs. I am selecting Basic B1 for now. </p>
<p>Your final page will look something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700618652/008f6945-ff2d-41bf-b883-bf1b5e9e2733.png" alt="Create app service final" /></p>
<p>Now we need to go to the deployment tab. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700620758/3425503b-6007-434c-a805-6b92f6ed18a6.png" alt="Deployment" /></p>
<p>Here you first need to enable Continuous deployment. 
After enabling that, you need to Authorize your GitHub account by logging into your account. </p>
<p>Once you authorize that, you need to select the repository and branch.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700623017/bc29e5d3-4038-4cff-ac03-93ee3a5a049a.png" alt="Deployment tab final" /></p>
<p>Now click on <code>Review + create</code> . 
You will be taken to the final page where you can review everything. 
Finally, you can click on <code>Create</code> now. </p>
<p>Now it will takes few minutes to deploy your application on the cloud. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700625036/35af2ed0-5a25-4c96-9e3f-a38418b6a401.png" alt="Deployment in process" /></p>
<p>After the deployment has been done, you will see a page like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700626579/cc2a95aa-0997-46e6-b41d-d043e2c9e85c.png" alt="Deployment done" /></p>
<p>Now click on <code>Go to resource</code> . 
It will take few seconds to load. After all data has been loaded, you will be able to see the domain. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700628903/e027b6ab-9e89-4c13-9dc4-d9ade7d0dd1f.png" alt="Resource Page" /></p>
<p>You can try visiting it, but you will be greeted with an error. 
Don’t worry, we will solve that as well. </p>
<p>The error is mainly because we haven’t really allowed our application to run on this domain. 
To allow that, we would need to add this domain in our settings file. </p>
<h3 id="heading-4-making-required-changes">4) Making Required Changes</h3>
<p>We will now go to our editor and open the <code>settings.py</code> file. 
Find <code>ALLOWED_HOSTS</code> in that file. By default, it will be an empty list. Or in some cases there might be previously added domains as well. Don’t worry. 
Now, we need to add our domain in that list. </p>
<p>Kinda like this: <code>ALLOWED_HOSTS = ["rachit-todo.azurewebsites.net"]</code> 
But make sure you enter your webapp’s domain. </p>
<p>Once done, save the file and commit it. Then once you push the commit to GitHub, Azure will automatically start deploying the webapp again. It will take few minutes to deploy.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700630868/19e014d9-ed80-45d3-a733-f48a4dc8f0fc.png" alt="GitHub Actions" /></p>
<p>Congratulations 🎉, You have succesfully deployed your Django Web App to Azure. 🎉</p>
<p>Give yourself a pat on the back </p>
<p><img src="https://i.imgur.com/brtcekW.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1720700632728/f19433a9-cffc-421b-a9ee-dedcaf39a7bd.gif" /></p>
<p>I hope you find this blog helpful. 
Feel free to write any doubts in the comments. </p>
]]></content:encoded></item><item><title><![CDATA[Top 5 Must-Have Tools for Linux Users]]></title><description><![CDATA[Linux is known for its flexibility and powerful command-line tools. To make the most out of your Linux system, here are five productivity tools that can enhance your workflow.
1) Zoxide (z)
So you might be wondering what exactly is zoxide ? According...]]></description><link>https://blog.rachitkhurana.tech/top-5-must-have-tools-for-linux-users</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/top-5-must-have-tools-for-linux-users</guid><category><![CDATA[Linux]]></category><category><![CDATA[linux for beginners]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[tools]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Tue, 02 Jul 2024 11:13:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1719918488148/ba34b0d7-99b7-4f93-ba59-75881a435a80.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Linux is known for its flexibility and powerful command-line tools. To make the most out of your Linux system, here are five productivity tools that can enhance your workflow.</p>
<h2 id="heading-1-zoxide-z">1) Zoxide (<code>z</code>)</h2>
<p>So you might be wondering what exactly is zoxide ? According to the developer, its “A smarter cd command”.</p>
<p>Lemme explain it with example, so for example you want to go to a project directory named <code>webapp1234</code> , and its inside a GitHub directory in the Documents directory.</p>
<p>So with cd, you either need to use the following commands:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> Documents/
<span class="hljs-built_in">cd</span> Github/
<span class="hljs-built_in">cd</span> webapp1234/
</code></pre>
<p>or you can use the following command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> Documents/GitHub/webapp1234/
</code></pre>
<p>but with zoxide, you can do this with a simple simple command:</p>
<pre><code class="lang-bash">z webapp1234
</code></pre>
<p>and you will be in the webapp directory.<br />Isn’t this cool?</p>
<p>You can check it out at: <a target="_blank" href="https://github.com/ajeetdsouza/zoxide">https://github.com/ajeetdsouza/zoxide</a></p>
<h2 id="heading-2-wakapi">2) Wakapi</h2>
<p>Many of you may be programmers and spend a lot of your time programming and making projects. However, we often don’t know how much time have we actually spent on a particular project or on a particular day. That’s why tracking time while coding is important.</p>
<p>For that, we can use wakapi. Wakapi is basically an open source implementation of Wakatime. Wakatime is a closed sourced solution and has paid plans that are quite expensive. So instead you can use Wakapi.</p>
<p>You can install it on your local system as a service that automatically runs when your system boots. Then you can use any Wakatime extension that is available for most Code Editors/IDEs. For complete client setup guide, refer to: <a target="_blank" href="https://github.com/muety/wakapi?tab=readme-ov-file#-client-setup">https://github.com/muety/wakapi?tab=readme-ov-file#-client-setup</a></p>
<p>My dashboard of the last 6 months:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719918446055/0806ef9b-563b-457a-9081-5d51588fc878.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-3-ollama-openwebui">3) Ollama + OpenWebUI</h2>
<p>In this world of AI, everyone uses chatgpt and various other online AI tools, however, that comes with its own limitations. Some are paid, or some have limited responses, some are slow while some are very limiting.</p>
<p>So that’s where ollama comes in. Ollama basically allows you to run open source models directly on your laptop.</p>
<p>Checkout ollama at: <a target="_blank" href="https://ollama.com/">https://ollama.com/</a></p>
<p>Once you have ollama installed, you can install any open source model from the ollama library. You can checkout the library at: <a target="_blank" href="https://ollama.com/library">https://ollama.com/library</a></p>
<p>I would suggest you to download llama3 and phi3. These 2 are really capable models.</p>
<p>Now that we have the models, but currently we can only use them in the terminal, but we want to use it in the browser with a ChatGPT like interface, so thats where OpenWebUI comes in.</p>
<h3 id="heading-openwebui">OpenWebUI</h3>
<p>OpenWebUI is basically a web interface for ollama. It’s interface is very familiar and similar to ChatGPT.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719918398926/789d76d0-2b61-412a-b3f4-667bc128c949.gif" alt /></p>
<p>Keep in mind that the speed of responses and performance depends upon your system specs and the model selected. If you have any GPU , then it will work decently, otherwise it will be quite slow.</p>
<h2 id="heading-4-fish-shell">4) Fish Shell</h2>
<p>You probably might have used any terminal on Linux few times. By default, the default shell on most Distros is bash. However, there are many more shells other than bash as well. Fish Shell is one of them.</p>
<p>itsFOSS also published an amazing article a while back on Fish Shell, you can check it out at:</p>
<p><a target="_blank" href="https://itsfoss.com/fish-shell-features/">https://itsfoss.com/fish-shell-features/</a></p>
<p>In short, fish shell has some really amazing features like:</p>
<ul>
<li><p>Syntax highlighting</p>
</li>
<li><p>Auto Suggestions</p>
</li>
<li><p>Easier path navigation</p>
</li>
<li><p>Interactive history search</p>
</li>
</ul>
<p>and much more…</p>
<h2 id="heading-5-distrobox">5) distrobox</h2>
<p>There may have been many situations when you wanted to install a software but it wasn’t compatible with your distro, but worry not, you can use distrobox. It basically allows you to use any linux distribution inside your terminal.</p>
<p>You can check it out at: <a target="_blank" href="https://github.com/89luca89/distrobox">https://github.com/89luca89/distrobox</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719918360571/b5fbb4db-dbf0-41bb-9bd5-5dd932eef064.png" alt="Distrobox" class="image--center mx-auto" /></p>
<p>As you can see, my main host OS is fedora, however, I have install multiple OS in containers using distrobox.</p>
<p>So, these were the 5 tools that I thought might be incredibly useful for many people in their daily lives. Each of these tools offers unique features and functionalities that can significantly enhance productivity and efficiency. Whether it's leveraging the power of a language model, optimizing terminal usage with Fish Shell, or running different Linux distributions seamlessly with Distrobox, these tools are designed to make your tech experience smoother and more enjoyable.</p>
<p>If you have any more suggestions or know of other tools that can be beneficial, please feel free to drop a comment and let me know. I am always on the lookout for new and innovative tools that can improve our daily workflows. Your recommendations are highly appreciated, and I would love to explore and share them with the community. Let's keep the conversation going and help each other discover the best tools out there!</p>
]]></content:encoded></item><item><title><![CDATA[Let's Learn Django #6:  Using Database & Admin Panel]]></title><description><![CDATA[In the last blog, we discussed how can we use Django templating to the fullest. In this blog, we will discuss how can we use databases and handle our data in Django.
Introduction to Django databases
I am hoping everyone knows what a database is, but ...]]></description><link>https://blog.rachitkhurana.tech/lets-learn-django-6-using-database-admin-panel</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/lets-learn-django-6-using-database-admin-panel</guid><category><![CDATA[Python]]></category><category><![CDATA[WeMakeDevs]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Django]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Sat, 22 Jul 2023 20:32:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1687799950722/e8fa254f-5909-41a2-a010-88add8082159.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last blog, we discussed how can we use Django templating to the fullest. In this blog, we will discuss how can we use databases and handle our data in Django.</p>
<h2 id="heading-introduction-to-django-databases"><strong>Introduction to Django databases</strong></h2>
<p>I am hoping everyone knows what a database is, but for those who don't know, it's a structured way we store our data.</p>
<p>Django supports many relational databases like SQLite, MySQL, Postgres etc.</p>
<p>By default, Django uses SQLite, but feel free to use any according to your preference/use case.</p>
<p>We will also be using SQLite in this blog.</p>
<p>To know more about how to use different databases, check out the following Django documentation: <a target="_blank" href="https://docs.djangoproject.com/en/4.2/ref/databases/">https://docs.djangoproject.com/en/4.2/ref/databases/</a></p>
<h2 id="heading-what-are-models">What are models?</h2>
<p>Models are basically Python classes that represent a table in the database. Each attribute of the class represents a field in the database table. By defining a model, Django can automatically create the corresponding database table and handle database operations such as creating, updating, and deleting records.</p>
<h2 id="heading-migrations">Migrations</h2>
<p>Migrations are the way Django stores changes to your models (and thus your database schema) - they’re just files on disk. Migrations are designed to be run as a sequence, and to avoid conflicts and mistakes during development, we create them every time we make changes to our models. We’ll cover how to generate and apply migrations in the next blog.</p>
<h2 id="heading-set-up-db">Set Up DB</h2>
<p>By default, Django uses SQLite database, and hence we won’t change it for now. The first command that we need to run is :</p>
<pre><code class="lang-bash">python manage.py migrate
</code></pre>
<p>This command will create all the necessary tables in the database that Django uses to keep track of its own models. Once this command is run, you can create your own models and Django will automatically create the corresponding tables in the database.</p>
<p>After creating your models, you can use Django's Object-Relational Mapping (ORM) to interact with the database and perform various CRUD (Create, Read, Update, Delete) operations on the data.</p>
<p>Every time you change something in your model, you need to make the migrations again to make changes to the database tables.</p>
<p>For that, we can run the following commands to make migrations and apply changes to the db structure.</p>
<pre><code class="lang-bash">python manage.py makemigrations
python manage.py migrate
</code></pre>
<p>The first command <code>makemigrations</code> will create a new migration file in the migrations directory for every model that has changed. The second command <code>migrate</code> will apply those changes to the database. It's important to always run both commands in order to keep the database structure in sync with your models.</p>
<h2 id="heading-django-orm">Django ORM</h2>
<p>Django ORM stands for Object-Relational Mapping. It is a powerful feature that allows us to interact with our database like we're working with Python objects. With the ORM, we can create, retrieve, update, and delete objects from the database using simple Python code. This makes working with databases in Django much easier and faster than writing SQL queries manually.</p>
<h2 id="heading-creating-models">Creating Models</h2>
<p>In order to create models, we need to define a Python class that extends Django's <code>Model</code> class. Each attribute of the class represents a field in the database table. Django provides a variety of fields like <code>CharField</code>, <code>IntegerField</code>, <code>DateField</code>, <code>DateTimeField</code>, etc. that we can use to define our model's fields. We can also define relationships between models using fields like <code>ForeignKey</code>, <code>ManyToManyField</code>, and <code>OneToOneField</code>.</p>
<p>For eg. lets create a sample model for our <code>triviaquiz</code> app in <code>/quiz/models.py</code> file</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> models

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TriviaQuestion</span>(<span class="hljs-params">models.Model</span>):</span>
    question_text = models.CharField(max_length=<span class="hljs-number">200</span>)
    pub_date = models.DateTimeField(<span class="hljs-string">'date published'</span>)
    answer = models.CharField(max_length=<span class="hljs-number">200</span>)
    option1 = models.CharField(max_length=<span class="hljs-number">200</span>)
    option2 = models.CharField(max_length=<span class="hljs-number">200</span>)
    option3 = models.CharField(max_length=<span class="hljs-number">200</span>)
    option4 = models.CharField(max_length=<span class="hljs-number">200</span>)

        <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__str__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self.question_text
</code></pre>
<p>In this model, we have created a simple model for defining the attributes we want in the TriviaQuestion model. Do note the different kinds on fields we are using.</p>
<p>Now to use this, we need to add this model to our database.</p>
<p>To add the newly created model to the database, we need to create a migration for it. We can do this by running the following command in the terminal:</p>
<pre><code class="lang-bash">python manage.py makemigrations
</code></pre>
<p>This will create a new migration file , which includes the changes we made to the <code>TriviaQuestion</code> model. Next, we apply the migration using the following command:</p>
<pre><code class="lang-bash">python manage.py migrate
</code></pre>
<p>This will create the <code>triviaquestion</code> table in the database. Now to easily edit the data, we will also add this model in the <code>admin.py</code> file.</p>
<p>For example, let's say we want to display the TriviaQuestion model in the admin interface. We can create a custom admin class for this model in our <code>admin.py</code> file:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> admin
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> TriviaQuestion

admin.site.register(TriviaQuestion)
</code></pre>
<p>This will display the question text and the date it was published in the admin interface for the TriviaQuestion model.</p>
<h2 id="heading-django-admin">Django Admin</h2>
<p>Django Admin is a feature that comes with Django that allows us to easily manage our database data using a web interface. It is automatically generated based on the models we define in our app. To use it, we need to create a superuser first. We can do this by running the following command in the terminal:</p>
<pre><code class="lang-bash">python manage.py createsuperuser
</code></pre>
<p>This will prompt us to enter a username, email, and password for the superuser. Once we have created a superuser, we can access the admin interface by going to <a target="_blank" href="http://localhost:8000/admin"><code>localhost:8000/admin</code></a> in our browser and logging in with the superuser credentials.</p>
<p>In the next blog, we will dive deeper into how to use Django ORM to interact with the database and perform CRUD operations on the data. We will also discuss how to create custom admin classes and how to use the Django Admin interface to manage our database data more efficiently.</p>
]]></content:encoded></item><item><title><![CDATA[Let's Learn Django #5 Django Template]]></title><description><![CDATA[In the previous blog, we looked at how to set up and use Django templating. Now, let's dive deeper into Django templating and explore its powerful features.
Django templating is very powerful. It supports a large number of tags like if, for, cycle et...]]></description><link>https://blog.rachitkhurana.tech/lets-learn-django-5-django-template</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/lets-learn-django-5-django-template</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Python]]></category><category><![CDATA[Django]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Wed, 21 Jun 2023 18:23:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1687173667259/bb50a5fa-ec04-488e-8e62-99a54c72d0b2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the previous blog, we looked at how to set up and use Django templating. Now, let's dive deeper into Django templating and explore its powerful features.</p>
<p>Django templating is very powerful. It supports a large number of tags like if, for, cycle etc.</p>
<h3 id="heading-basics">Basics:</h3>
<p>We display the variables we passed using double curly brackets<br />Like this: <code>{{ variable_name }}</code></p>
<p>And we use Django template tags using a pair of curly brackets &amp; percent sign.<br />Like this: <code>{% if age&gt;18 %}Adult{% else %}Child{% endif %}</code></p>
<p>To use filters, we add a pipe symbol in front of the variable.<br />Like this: <code>{{ name|length }}</code></p>
<p>Now we will have a look at the common template tags in Django</p>
<h2 id="heading-template-tags">Template Tags</h2>
<h3 id="heading-if-tag">if tag</h3>
<p>If tag is a pretty simple tag used to add a condition to the template content.<br />it supports almost all conditions we use in python. Like comparing values, checking membership etc. We can check if an element is in the list.<br />Do note that we also need to add an endif tag when we are done with the condition.<br />For eg.</p>
<pre><code class="lang-xml">    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>My name is <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{{name}}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {% if name|length <span class="hljs-tag">&lt; <span class="hljs-attr">5</span> %}
            &lt;<span class="hljs-attr">p</span>&gt;</span>My name is short<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {% elif name|length <span class="hljs-tag">&lt; <span class="hljs-attr">10</span> %}
            &lt;<span class="hljs-attr">p</span>&gt;</span>My name is long<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {% else %}
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>My name is very long<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {% endif %}
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>My age is <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{{age}}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<h3 id="heading-for-tag">for Tag</h3>
<p>The "for" tag allows us to iterate over sequences, such as lists, dictionaries, or querysets, similar to looping in Python. By utilizing this tag, we can display and manipulate each item in the sequence.<br />For eg:</p>
<p>For this, I passed a basic list from the views.py file like this:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hello</span>(<span class="hljs-params">request</span>):</span>
    name=<span class="hljs-string">"Rachit"</span>
    age=<span class="hljs-number">19</span>
    Interests=[<span class="hljs-string">'Coding'</span>, <span class="hljs-string">'Reading'</span>, <span class="hljs-string">'Gaming'</span>]
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'hello.html'</span>, {<span class="hljs-string">'name'</span>:name, <span class="hljs-string">'age'</span>:age, <span class="hljs-string">'Interests'</span>:Interests})
</code></pre>
<p>and the template will contain:</p>
<pre><code class="lang-xml">{% load static %}
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'style.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>My name is <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{{name}}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>My age is <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{{age}}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> Interests: <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
            {% for interest in Interests %}
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{{interest}}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            {% endfor %}
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h3 id="heading-extends-and-block-tag">extends and block tag</h3>
<p>These 2 tags are generally used together. If we want to create a base template &amp; then put data or other HTML elements inside it using a different file, we use these tags.<br />First, we will add a block tag in the base file &amp; then extend that base file to another file, &amp; use the block tag to put more HTML elements in it.<br />For eg. I will create a new <code>base.html</code> file with the following content making use of the block tag.</p>
<pre><code class="lang-xml">{% load static %}
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'style.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Django Tutorial<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hi there! This is a Django tutorial.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {% block content %}
        {% endblock content %}
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Now, we will edit <code>hello.html</code> to extend this &amp; place more content in the content block.</p>
<pre><code class="lang-xml">{% extends 'base.html' %}
{% block content %}
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> Welcome to the home page!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{% endblock %}
</code></pre>
<p>This allows us to reuse templates &amp; follow the DRY(Don't repeat yourself) principle.</p>
<h3 id="heading-include-tag">include Tag</h3>
<p>Now what if we need to add a simple component to the current file without extending the base file in that component file?<br />That's where the include tag comes in.<br />Using it is pretty straightforward. Let's add a header component to our <code>base.html</code> file<br />For that, we will create a new file with the header component. I am going to name it <code>header.html</code> and add a simple marquee to it.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">marquee</span>&gt;</span>
Welcome to this django tutorial !
<span class="hljs-tag">&lt;/<span class="hljs-name">marquee</span>&gt;</span>
</code></pre>
<p>Now, to include it in <code>base.html</code>, we will use the include tag like this:</p>
<pre><code class="lang-xml">{% load static %}
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'style.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
        {% include 'header.html' %}
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Django Tutorial<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hi there! This is a Django tutorial.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {% block content %}
        {% endblock content %}
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>This also helps us in following in DRY principle.<br />These were the main tags we will use while building any web apps. Apart from this, there are a lot more template tags &amp; filters in Django. To know more about them, I suggest reading the following Django docs: <a target="_blank" href="https://docs.djangoproject.com/en/4.2/ref/templates/builtins/">https://docs.djangoproject.com/en/4.2/ref/templates/builtins/</a></p>
]]></content:encoded></item><item><title><![CDATA[Let's Learn Django #4 Using templates & static files]]></title><description><![CDATA[We have already seen how to write our first view in the previous blogs. In this blog, we will explore how to use & render templates.
What are templates?
Templates are simply HTML files that we can render as a response to a URL/view.Django templates o...]]></description><link>https://blog.rachitkhurana.tech/lets-learn-django-4-using-templates-static-files</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/lets-learn-django-4-using-templates-static-files</guid><category><![CDATA[Python]]></category><category><![CDATA[Django]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Sat, 17 Jun 2023 10:51:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1686945608072/c42a09e0-9ccb-4b91-9d9d-258ba97ab9b3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We have already seen how to write our first view in the previous blogs. In this blog, we will explore how to use &amp; render templates.</p>
<h3 id="heading-what-are-templates">What are templates?</h3>
<p>Templates are simply HTML files that we can render as a response to a URL/view.<br />Django templates offer a robust templating language with various built-in tags and filters that you can utilize to manipulate and display data in your HTML templates.<br />We will explore it in detail in the next blog</p>
<h3 id="heading-setting-up-templates-folder">Setting up templates folder</h3>
<p>Setting up a templates folder is quite easy. First, we will create a new folder in the base directory with the name <code>templates</code>.<br />Next, we need to tell Django that we will be using this folder for placing all our templates.</p>
<p>For that, we all navigate to our settings.py file. There is a list named <code>TEMPLATES</code> &amp; it will have a JSON object with a field named <code>DIRS</code> that contain an empty list. We just need to add <code>templates</code> (the name of our folder) to it.<br />Finally, it should look something like this:  </p>
<pre><code class="lang-python">TEMPLATES = [
    {
        <span class="hljs-string">'BACKEND'</span>: <span class="hljs-string">'django.template.backends.django.DjangoTemplates'</span>,
        <span class="hljs-string">'DIRS'</span>: [<span class="hljs-string">'templates'</span>],
        <span class="hljs-string">'APP_DIRS'</span>: <span class="hljs-literal">True</span>,
        <span class="hljs-string">'OPTIONS'</span>: {
            <span class="hljs-string">'context_processors'</span>: [
                <span class="hljs-string">'django.template.context_processors.debug'</span>,
                <span class="hljs-string">'django.template.context_processors.request'</span>,
                <span class="hljs-string">'django.contrib.auth.context_processors.auth'</span>,
                <span class="hljs-string">'django.contrib.messages.context_processors.messages'</span>,
            ],
        },
    },
]
</code></pre>
<p>That is all we need to do to set up templates.<br />Now we will see how to use templates.</p>
<h3 id="heading-rendering-templates">Rendering templates</h3>
<p>Rendering a template means generating an HTML response that incorporates the dynamic data and logic defined in your views, which is then sent to the user's browser.</p>
<p>In the last blog, we saw how to write our views. So now, let's render an HTML template as a response to that view.<br />First, we will create a new HTML file in the templates directory with the name <code>hello.html</code><br />You can then add any HTML page design you want.<br />I will go with a simple one.  </p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>My name is <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Rachit Khurana<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Now, we will return this template when the user goes to the index page.<br />For that, we will navigate to <code>views.py</code> where we defined a hello function that gets called when the user goes to the index page.<br />We will then use <code>render</code> function from <code>django.shortcuts</code> to render this template.<br />The <code>render</code> function simplifies the process of rendering templates by handling the template loading and rendering process automatically. It takes the request, the template file path, and an optional context as arguments and returns an HTTP response with the rendered template.</p>
<p>The <code>views.py</code> code will look like this</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.shortcuts <span class="hljs-keyword">import</span> render, HttpResponse

<span class="hljs-comment"># Create your views here.</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hello</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'hello.html'</span>)
</code></pre>
<p>Now if we run the server &amp; go to <a target="_blank" href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a>, we will be able to see this as an HTML-rendered page. Awesome right?  </p>
<p>However, do note that you won't be able to create CSS or JS files in the templates folder &amp; use those in the HTML file.<br />This is because Django only takes the HTML file, &amp; returns the rendered file directly. It doesn't take the CSS &amp; JS files. To use separate CSS &amp; JS files, we need to serve them as static files.<br />We will now see how to serve static files.</p>
<h2 id="heading-static-files">Static Files</h2>
<p>Static files include CSS, JavaScript, images, and other files that remain constant for all users visiting your website. These files are served directly to the client's browser and contribute to the visual and interactive aspects of your web pages.  </p>
<p>To set up static files, we will create a new folder named <code>static</code>.<br />Now we need to tell Django to use this folder for serving static files. For that, we will add the following line to the <code>settings.py</code> file:</p>
<pre><code class="lang-python">STATICFILES_DIRS = [
    BASE_DIR / <span class="hljs-string">"static"</span>
]
</code></pre>
<p><code>STATICFILES_DIRS</code> is a list where you specify the directory paths where Django should look for static files.</p>
<p>That's it. Now whatever file we store in the static folder will be available at http://127.0.0.1:8000/static/&lt;filename&gt;.  </p>
<h3 id="heading-using-static-files-inside-templates">Using static files inside templates</h3>
<p>Now, let's create a simple CSS file with the name <code>style.css</code>. I will be using a pretty simple CSS file for demonstration.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span>{
    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#ca1c1c</span>;
    <span class="hljs-attribute">color</span>: aqua;
}
</code></pre>
<p>Now, we will use this in our <code>hello.html</code> file by making use of the static tag. First, we will import it &amp; then use it as shown below:</p>
<pre><code class="lang-xml">{% load static %}
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'style.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>My name is <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Rachit Khurana<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Now when we run the server &amp; go to <a target="_blank" href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a> we will see the new HTML page with the CSS.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686997678145/76fe5f0e-bef4-4d63-ac65-22fb3ea6cd09.png" alt class="image--center mx-auto" /></p>
<p>Congratulations, you know know how to render an HTML template &amp; use static files. But what if we need to pass an argument from the code to the template?<br />We can also do that easily. Let's take a look at how to do that.</p>
<h3 id="heading-passing-arguments-to-the-template">Passing arguments to the template</h3>
<p>We can easily pass variables to the template to render.<br />For eg, I want to pass my name &amp; age to the template. We will go to the <code>views.py</code> file &amp; declare these variables in the function.<br />We then need to pass another argument to the render function with all the variables we need to pass to the template as a dictionary.<br />The final code will look like this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.shortcuts <span class="hljs-keyword">import</span> render, HttpResponse

<span class="hljs-comment"># Create your views here.</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hello</span>(<span class="hljs-params">request</span>):</span>
    name=<span class="hljs-string">"Rachit Khurana"</span>
    age=<span class="hljs-number">19</span>
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'hello.html'</span>, {<span class="hljs-string">'name'</span>:name, <span class="hljs-string">'age'</span>:age})
</code></pre>
<p>Now we can use these variables in the template <code>hello.html</code> by wrapping them with double curly brackets like this:</p>
<pre><code class="lang-xml">{% load static %}
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'style.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>My name is <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{{name}}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>My age is <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{{age}}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Here <code>{{name}}</code> will get replaced by the value of <code>name</code> we have passed to the template. Now if we try to run the server &amp; go to <a target="_blank" href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a> we can see the new rendered HTML page with those variables.</p>
<p>Like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686998271696/d587636e-1ade-43d3-a06c-e7c100ef5a3c.png" alt class="image--center mx-auto" /></p>
<p>We can not only pass string or int values, but we can also pass lists, tuples, dictionaries etc.  </p>
<p>Congratulations, you now know how to render templates, serve static files &amp; pass variables to the template. But that's not all, Django templating is way more powerful than this. We will explore more about it in the next blog.</p>
]]></content:encoded></item><item><title><![CDATA[Let's Learn Django #3 Writing our first view]]></title><description><![CDATA[By now, we have seen how to initialise our project and the overview of different files in a Django project.Now, we will write out the first view/page.
Creating the First View - Hello World!
Let's start by creating a simple view that will return a sim...]]></description><link>https://blog.rachitkhurana.tech/lets-learn-django-3-writing-our-first-view</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/lets-learn-django-3-writing-our-first-view</guid><category><![CDATA[Python]]></category><category><![CDATA[Django]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Thu, 15 Jun 2023 12:31:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1686832059181/42f24d05-abc3-4263-9ff3-7dc344c6c267.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>By now, we have seen how to initialise our project and the overview of different files in a Django project.<br />Now, we will write out the first view/page.</p>
<h3 id="heading-creating-the-first-view-hello-world">Creating the First View - Hello World!</h3>
<p>Let's start by creating a simple view that will return a simple Hello World text.</p>
<p>For that, we first need to tell Django to include our app (the app that we created before using the <code>django-admin startapp command</code>) in the project.<br />We will open the <code>settings.py</code> file. There would be a list named <code>INSTALLED_APPS</code> . We just need to add our app name to that file. This allows Django to recognize and include your app in the project.<br />Somewhat like this:</p>
<pre><code class="lang-python">INSTALLED_APPS = [
    <span class="hljs-string">'django.contrib.admin'</span>,
    <span class="hljs-string">'django.contrib.auth'</span>,
    <span class="hljs-string">'django.contrib.contenttypes'</span>,
    <span class="hljs-string">'django.contrib.sessions'</span>,
    <span class="hljs-string">'django.contrib.messages'</span>,
    <span class="hljs-string">'django.contrib.staticfiles'</span>,
    <span class="hljs-string">'quiz'</span>
]
</code></pre>
<p>Here, <code>quiz</code> is the name of the app I created before.</p>
<p>Now, we will create a function that will take the request as a parameter &amp; return Hello World! or anything you like. Kindly note, that request is a required parameter as it will contain all the details of the HTTP request.<br />We will create this function in <code>quiz/views.py</code> file.</p>
<p>Since we want to return plain text in the HTTP response, we will import it here.<br />HttpResponse is used to return plain text in the HTTP response. <code>django.shortcuts</code> already provide us with many methods through which we can return data.</p>
<p>The file will look like this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.shortcuts <span class="hljs-keyword">import</span> render, HttpResponse

<span class="hljs-comment"># Create your views here.</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hello</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">"Hello World!"</span>)
</code></pre>
<p>Now to map this function to the home URL, we will edit the <code>urls.py</code> file.<br /><code>urls.py</code> file already contains a list by the name of <code>urlpatterns</code>. We will add our routes to this. Since we want to display Hello World on our homepage, our path will just be an empty string. And to map it to that function, we will import <code>quiz.views</code> here.</p>
<p>Our views.py file should look something like this now:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> admin
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path
<span class="hljs-keyword">import</span> quiz.views

urlpatterns = [
    path(<span class="hljs-string">'admin/'</span>, admin.site.urls),
    path(<span class="hljs-string">""</span>, quiz.views.hello, name=<span class="hljs-string">"hello"</span>)
]
</code></pre>
<p>The <code>name</code> parameter in the path is optional and used for naming the URL pattern, allowing you to refer to it by name in other parts of the code.</p>
<p>Awesome, we have made our first view. Now to test it, we will run it using the following command</p>
<pre><code class="lang-bash">python manage.py runserver
</code></pre>
<p>This will start the Django server &amp; will serve it to the local host.</p>
<p>And now, when we go to <a target="_blank" href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a> we will see Hello World! on that page 🎉</p>
<p>And there you have it! We have successfully created our first view in Django that displays 'Hello World!' when accessing the homepage. This simple example lays the foundation for building more complex views and functionalities in your Django project. Keep exploring and experimenting with Django to unlock its full potential!</p>
<p>In the next blog, we will explore more about how to use templates.</p>
]]></content:encoded></item><item><title><![CDATA[Let's Learn Django #2 File Structure]]></title><description><![CDATA[After initialising a Django project, we can see several files. Don't worry, this blog will explain all of them in detail.
The general file structure of Django looks like this:
├── [appname]
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├──...]]></description><link>https://blog.rachitkhurana.tech/lets-learn-django-2-file-structure</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/lets-learn-django-2-file-structure</guid><category><![CDATA[Python]]></category><category><![CDATA[Django]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Wed, 14 Jun 2023 18:40:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1686766563467/a67a2950-c624-42bd-95c8-a30a6e0d9565.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After initialising a Django project, we can see several files. Don't worry, this blog will explain all of them in detail.</p>
<p>The general file structure of Django looks like this:</p>
<pre><code class="lang-yaml"><span class="hljs-string">├──</span> [<span class="hljs-string">appname</span>]
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">admin.py</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">apps.py</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">__init__.py</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">migrations</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">__init__.py</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">models.py</span>
<span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">views.py</span>
<span class="hljs-string">├──</span> [<span class="hljs-string">projectname</span>]
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">__init__.py</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">asgi.py</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">settings.py</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">urls.py</span>
<span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">wsgi.py</span>
<span class="hljs-string">└──</span> <span class="hljs-string">manage.py</span>
</code></pre>
<p>Here [appname] represents the name of the app you have created &amp; [projectname] represents your project name.</p>
<p>Now, let's go over each file one by one.</p>
<h3 id="heading-managepy">manage.py</h3>
<p>It mainly contains code to manage your Django application, like running the project, applying migrations, etc. Most of the time we would never need to edit this file. So we can even ignore it for now.</p>
<h3 id="heading-settingspy">settings.py</h3>
<p>It contains all the project configs required. It is one of the most important files. We will add more apps here, set up email servers, templating, middleware, databases, and a lot more. Don't worry, we don't need to know everything about it right away.</p>
<h3 id="heading-urlspy">urls.py</h3>
<p>In this file, we will define all the URL routes that we will be using in our projects. We can map the URL routes to a specific view, redirect to another URL etc. We can also define dynamic URLs, parameterised URLs, and much more. This allows us to configure the flow of our project and define how different URLs should be handled.</p>
<h3 id="heading-asgipy-andamp-wsgipy">asgi.py &amp; wsgi.py</h3>
<p>ASGI stands for Asynchronous Server Gateway Interface &amp; WSGI stands for Web Server Gateway Interface. Django automatically generates these files for us so we don't need to modify them initially. These files handle the communication between Django and the web server. While it's a bit of an advanced topic, you can skip it for now. If you're interested, you can read more about ASGI and WSGI online.</p>
<h3 id="heading-viewspy">views.py</h3>
<p>This is the main file where you write the main logic of the web pages. Django supports 2 types of views, function-based views &amp; class-based views. They are used to define what needs to be done &amp; what needs to be returned when a specific URL is called.<br />We can return a JSON response, A HTTP response, a rendered template or anything we want.</p>
<h3 id="heading-modelspy">models.py</h3>
<p>This file is mainly used to define all the models that we want to use. You can think of it as defining the database structure so that we can easily read &amp; write data into the database. After defining the models here, we can use the very powerful Django ORM(Object-Relational Mapping) to interact with the database. I will cover the Django ORM in later blogs of this series.</p>
<h3 id="heading-apppy">app.py</h3>
<p>This file is mainly used to customize the configuration of your app or define additional metadata for it. For now, we can ignore this file.</p>
<h3 id="heading-adminpy">admin.py</h3>
<p>This file is used to register our app &amp; models in the admin panel. So that we can easily edit data in the admin panel. We can also customise the looks &amp; behaviour of the app so that it looks &amp; behaves as we want in the admin panel.</p>
<h3 id="heading-migrations-folder">Migrations folder</h3>
<p>This folder contains all the migrations files that are generated by manage.py when we edit the models in our models.py file. These migration files then make the specified changes in the main database.</p>
<p>With this, we have covered the basics of most of the important Django files that we would need while building a web app.<br />In the next blog, we will cover how to make url routes &amp; views for them in the urls.py &amp; views.py files respectively.</p>
<p>I hope this blog series is helping you learn Django.</p>
<p>Follow my journey on Twitter: <a target="_blank" href="https://twitter.com/notnotrachit">@notnotrachit</a></p>
]]></content:encoded></item><item><title><![CDATA[Let's Learn Django #1 Init]]></title><description><![CDATA[This is a blog series about Django from the very basics
Installing & initialising a project
Django is a really powerful Python-based web framework with the philosophy batteries included. It means it gives you everything you need to build a full-stack...]]></description><link>https://blog.rachitkhurana.tech/lets-learn-django-1-init</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/lets-learn-django-1-init</guid><category><![CDATA[Python]]></category><category><![CDATA[Django]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Wed, 14 Jun 2023 14:38:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1686752793603/5d95df7b-7474-4824-aafe-0316d7d6971e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is a blog series about Django from the very basics</p>
<h2 id="heading-installing-andamp-initialising-a-project">Installing &amp; initialising a project</h2>
<p>Django is a really powerful Python-based web framework with the philosophy <code>batteries included</code>. It means it gives you everything you need to build a full-stack web application. Django's Tag line is <code>The web framework for perfectionists with deadlines</code>. It's because it allows you to create professional-grade web apps very quickly.</p>
<p>However, learning it may seem a bit complex, but believe me, it is not. And to help with that, I'm writing this blog series.</p>
<p>So let's start from the very basics, installation &amp; initialising a project</p>
<h2 id="heading-installation">Installation</h2>
<p>Installing Django is pretty straightforward. You just need to use pip to install Django. However, it's always recommended to use a virtual environment for a project. So we will start by creating a virtual environment.</p>
<pre><code class="lang-shell">python -m venv venv
</code></pre>
<p>This will create a virtual environment in the <code>venv</code> folder. To use this environment, we need to activate it. Activating it is different in Windows, Linux &amp; MacOS.</p>
<p>Bash Shell (Linux)</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> ./venv/bin/activate
</code></pre>
<p>Fish Shell (Linux)</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> ./venv/bin/activate.fish
</code></pre>
<p>CMD (Windows)</p>
<pre><code class="lang-bash">venv\Scripts\activate.bat
</code></pre>
<p>Powershell (Windows)</p>
<pre><code class="lang-powershell">venv\Scripts\Activate.ps1
</code></pre>
<p>MacOS</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> ./venv/bin/activate
</code></pre>
<p>After activating the virtual environment, we can install Django using pip.</p>
<pre><code class="lang-bash">pip install Django
</code></pre>
<p>Of this, we have successfully installed Django on our systems. So what are we waiting for? Let's start a project</p>
<h2 id="heading-initialising-a-project">Initialising a project</h2>
<p>To start a project, we will use the <code>django-admin</code> command. It will help us generate the boilerplate code.</p>
<pre><code class="lang-bash">django-admin startproject &lt;projectname&gt;
</code></pre>
<p>For eg.</p>
<pre><code class="lang-bash">django-admin startproject triviaquiz
</code></pre>
<p>This will generate a boilerplate code for you. It will include a lot of files like manage.py, settings.py, models.py, urls.py etc.</p>
<p>Now to organise our code, we divide our Django web app into several smaller sub-apps. To create a sub-app, we will again use the <code>django-admin</code> command.</p>
<pre><code class="lang-bash">django-admin startapp &lt;app_name&gt;
</code></pre>
<p>For eg.</p>
<pre><code class="lang-bash">django-admin startapp quiz
</code></pre>
<p>This will create a new folder with several other files like models.py, views.py, admin.py etc.<br />You can try exploring all these files yourself as Django provides comments in the boilerplate code for easy understanding.<br />However, I will also explain each of them in detail in my next blog.</p>
<h2 id="heading-running-the-project">Running the project</h2>
<p>To run the project, we will use the following command:  </p>
<pre><code class="lang-bash">python manage.py runserver
</code></pre>
<p>This will start the server with your project at <a target="_blank" href="http://127.0.0.1:8000">http://127.0.0.1:8000</a>.<br />And by going to this url, you will a default Django page like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686750932580/894204aa-069f-4c3d-8166-c721128b908f.png" alt class="image--center mx-auto" /></p>
<p>If you are seeing this, then congrats, you have successfully set up &amp; started your project.  </p>
<p>In the next blog, I will explain all the different Django files in detail. Stay Tuned  </p>
<p>Follow my journey on Twitter: <a target="_blank" href="https://twitter.com/notnotrachit">@notnotrachit</a></p>
]]></content:encoded></item><item><title><![CDATA[Developer Portfolio: Appwrite Hashnode Hackathon]]></title><description><![CDATA[Developer Portfolio: Appwrite Hashnode Hackathon
Team Details
Rachit Khurana - Rachit Khurana
Description of Project
It's a simple portfolio website that I made It has many pages like Projects, skills, education, contact etc.It has displays all the b...]]></description><link>https://blog.rachitkhurana.tech/developer-portfolio-appwrite-hashnode-hackathon</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/developer-portfolio-appwrite-hashnode-hackathon</guid><category><![CDATA[Appwrite]]></category><category><![CDATA[Appwrite Hackathon]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[portfoliowebsite]]></category><category><![CDATA[portfolio]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Tue, 30 May 2023 13:04:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1685451793182/14aba58f-d22b-4bd7-b98d-cbfc5aa67117.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-developer-portfolio-appwritehttpsappwriteio-hashnodehttpshashnodecom-hackathon">Developer Portfolio: <a target="_blank" href="https://appwrite.io">Appwrite</a> <a target="_blank" href="https://hashnode.com">Hashnode</a> Hackathon</h1>
<h2 id="heading-team-details">Team Details</h2>
<p>Rachit Khurana - <a class="user-mention" href="https://hashnode.com/@rachitkhurana">Rachit Khurana</a></p>
<h2 id="heading-description-of-project">Description of Project</h2>
<p>It's a simple portfolio website that I made It has many pages like Projects, skills, education, contact etc.<br />It has displays all the blogs automatically using the APIs</p>
<h2 id="heading-tech-stack">Tech Stack</h2>
<ul>
<li><p>HTML</p>
</li>
<li><p>CSS</p>
</li>
<li><p>Tailwind</p>
</li>
<li><p>DaisyUI</p>
</li>
<li><p>NextJS</p>
</li>
<li><p>Appwrite</p>
<ul>
<li><p>Database</p>
</li>
<li><p>Storage</p>
</li>
</ul>
</li>
</ul>
<p>I built this portfolio using NextJS. I used the Appwrite database for storing &amp; getting all the projects as well as certifications data. I used Appwrite storage to store the project &amp; certificates cover images.</p>
<h2 id="heading-challenges-we-faced">Challenges We Faced</h2>
<p>I faced many challenges while building this. Initially, I was quite confused about how to make it dynamic &amp; easy for me to add more data later on. So I used Appwrite to solve this as it allows me to add data easily.</p>
<h2 id="heading-public-code-repo">Public Code Repo</h2>
<p><a target="_blank" href="https://github.com/notnotrachit/notnotrachit.github.io">GitHub</a></p>
<h2 id="heading-demo-link">Demo Link</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/HuHgsAyI354">https://youtu.be/HuHgsAyI354</a></div>
]]></content:encoded></item><item><title><![CDATA[My Experience with Debian, Arch, Fedora based distros]]></title><description><![CDATA[There are a lot, a loooot of Linux distros out there. However, there are mainly 3 types for distros for general people, Debian based distros, Arch based distros & Fedora based distros. I have tried all these three kinds of distros on my Laptop & here...]]></description><link>https://blog.rachitkhurana.tech/my-experience-with-debian-arch-fedora-based-distros</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/my-experience-with-debian-arch-fedora-based-distros</guid><category><![CDATA[Linux]]></category><category><![CDATA[ArchLinux]]></category><category><![CDATA[debian]]></category><category><![CDATA[Fedora]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Sun, 21 May 2023 18:55:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1684694300417/b94c470b-42a9-43b8-8042-fe00f9728185.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are a lot, a loooot of Linux distros out there. However, there are mainly 3 types for distros for general people, Debian based distros, Arch based distros &amp; Fedora based distros. I have tried all these three kinds of distros on my Laptop &amp; here I am sharing my experience.</p>
<h2 id="heading-my-laptop">My Laptop</h2>
<p>Firstly let me give you a brief about my laptop. I have a HP Victus laptop. It has 8gb RAM, 512gb SSD, Intel i5 11th Gen &amp; NVidia 1650 ti graphics card.</p>
<h2 id="heading-my-distro-hoping-journey">My distro hoping journey</h2>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dt1r0nnm4ysreylrx91w.png" alt="Distro_hoping meme" /></p>
<p>Till now I have switched a lot of distros on this laptop. It initially came with Windows 11 out of the box, however, me being a Linux lover, wanted to install Linux on it. So I installed KDE neon(Debian based) on it in dual boot mode since I had used debian previously. Then I clean installed KDE neon. It was working reasonably well, however NVidia Graphics card was causing a lot of trouble to me. My HDMI port wasn't working since it was directly linked to my graphics card.</p>
<p>So I switched to PopOS!. I switched because it had good NVidia drivers support out of the box. And it worked fine, my HDMI port was finally working. However, I had encountered a lot of bugs &amp; battery issues in it which degraded my experience over time.</p>
<p>So I decided to make another switch. This time, I decided to switch to a Arch Based distro. But I knew that installing Arch directly would be a lot for me, so I thought to go with a Arch based distro like Garuda Linux. So I installed it. However after installing, my laptop wasn't booting. So I asked about it in the Garuda forum &amp; got a quick fix that I needed to edit some grub config. So I edited it exactly the same way, and this time, it was working smoothly. However, my HDMI port still wasn't working. To use the Laptop in hybrid mode, we usually use optimus in Linux. But there was some issue with optimus on my laptop &amp; hence I could make it work. So to use an application using Graphics card, I needed to run it using the prime-run command everytime.</p>
<p>After some time, I decided to make the switch again. This time, I decided to go with Nobara (Fedora based) I specifically chose Nobara as it was gaming focused and included some modification over base fedora. And till now it has been working perfectly. Now let me tell you about my experience with all three types of distros.</p>
<h2 id="heading-debian-based-distros">Debian based distros</h2>
<p>(My experience from: Ubuntu, Kubuntu, KDE Neon &amp; PopOS!)</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l27za3vtdbr2hjvxz879.png" alt="Debian based distros" /></p>
<p>Debian based distros are generally the first Linux distro anyone uses. And that is for a reason, its very beginner friendly. Almost everything can be done easily using GUIs. However, I faced a couple of issues on it. Firstly I have faced dependency issues multiple times. The apt package manager has given me trouble a lot of time, and most Debian based distros are actually based on Ubuntu &amp; follow Ubuntu release cycle. Which means we get an LTS version every 2 years &amp; non LTS version every 6 months. Which mean that we usually get older &amp; outdated packages.</p>
<h2 id="heading-arch-based-distros">Arch based distros</h2>
<p>(My experience from Garuda &amp; Endeavour Linux)</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yxmcp9w3h4an9qz7xl6c.png" alt="Arch based distros" /></p>
<p>Arch based distros are generally for advance users as Arch gives full control over the system. The main benefit of it is the availability of softwares. Everything is available in AUR. It is the most cutting edge distro with the latest softwares. One con that it has is that when tinkering a bit, you can break some stuff, &amp; to fix that you need to be a little tech savy. And I found it a bit buggy as well.</p>
<h2 id="heading-fedora-based-distros">Fedora based distros</h2>
<p>(Me experience from Nobara Linux)</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obtrz523ktkquesqv523.png" alt="Fedora based distros" /></p>
<p>Fedora is my current favourite. It is very stable. And I have faced the least amount of bugs till now. Fedora uses a 6 month release cycle &amp; hence we get a perfect balance between stable, well tested packages &amp; cutting edge softwares. As for the con, I couldn't really find any, however, if I had to nitpick , it would be that the maximum number of softwares online are packaged in deb format which is only supported on linux. however, till dates I have not come across any packages that isn't available on Fedora. However, installing base Fedora has a bit of extra steps after installing. So I prefer Nobara.</p>
<h3 id="heading-a-special-note-on-distrobox">A special note on Distrobox</h3>
<p>If you want to install packages from other distros, you can use distrobox, it basically utilizes podman behind the scenes. You can refer to this itsfoss article for more info: <a target="_blank" href="https://itsfoss.com/distrobox/">https://itsfoss.com/distrobox/</a></p>
<h2 id="heading-my-conclusion">My conclusion</h2>
<p>So if you are a beginner, you can go with any Debian based distro or Nobara. And if you are an advance Linux user &amp; love to tinker around with OS and want the latest packages, prefer Arch. And if you are looking for a stable distro, go with Fedora based (I would suggest Nobara) distros.</p>
]]></content:encoded></item><item><title><![CDATA[5 Awesome (flatpak) Softwares for Linux]]></title><description><![CDATA[Flatpak
Flatpak is a packaging format for linux. And the best part, it is supported on all major linux distros. If you distro doesn't have flatpak installed by default you can go to https://flatpak.org/setup/ and follow the instructions there accordi...]]></description><link>https://blog.rachitkhurana.tech/5-awesome-flatpak-softwares-for-linux</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/5-awesome-flatpak-softwares-for-linux</guid><category><![CDATA[flatpak]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Productivity]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Tue, 15 Nov 2022 07:20:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1668496100951/95aZlKUHQ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-flatpak">Flatpak</h2>
<p>Flatpak is a packaging format for linux. And the best part, it is supported on all major linux distros. If you distro doesn't have flatpak installed by default you can go to <a target="_blank" href="https://flatpak.org/setup/">https://flatpak.org/setup/</a> and follow the instructions there according to your disto. Few other advantage of flatpaks include shared dependencies, permission manager etc. </p>
<h2 id="heading-here-is-a-list-of-pretty-useful-flatpak-softwares-for-linux">Here is a list of pretty useful (flatpak) Softwares for linux.</h2>
<h3 id="heading-1-blankethttpsflathuborgappsdetailscomrafaelmardojaiblanket"><a target="_blank" href="https://flathub.org/apps/details/com.rafaelmardojai.Blanket">1) Blanket</a></h3>
<p>Its a really nice application that plays ambient sound when you need to concentrate or study. It has a lot of options to choice from. </p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vpvseb9a07gnlj5zvisv.png" alt="blanket screenshot" /></p>
<p>To install it, just type the following command in the terminal </p>
<pre><code class="lang-bash">flatpak install flathub com.rafaelmardojai.Blanket
</code></pre>
<h3 id="heading-2-freetubehttpsflathuborgappsdetailsiofreetubeappfreetube"><a target="_blank" href="https://flathub.org/apps/details/io.freetubeapp.FreeTube">2) Freetube</a></h3>
<p>This application can be a bit controversial. Its basically a youtube client. It Provides adfree playback, custom speed, download videos and a lot more features. </p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xfpz2k8imuokoqtg3w3.png" alt="freetube screenshot" />
To install it, just type the following command in the terminal </p>
<pre><code class="lang-bash">flatpak install flathub io.freetubeapp.FreeTube
</code></pre>
<h3 id="heading-3-ktouchhttpsflathuborgappsdetailsorgkdektouch"><a target="_blank" href="https://flathub.org/apps/details/org.kde.ktouch">3) KTouch</a></h3>
<p>This is a really awesome software if you want to learn touch typing. </p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iq7t9l3ggtx5ma1f9dg5.png" alt="Image description" /></p>
<p>To install it, just type the following command in the terminal </p>
<pre><code class="lang-bash">flatpak install flathub org.kde.ktouch
</code></pre>
<h3 id="heading-4-froghttpsflathuborgappsdetailscomgithubtenderowlfrog"><a target="_blank" href="https://flathub.org/apps/details/com.github.tenderowl.frog">4) Frog</a></h3>
<p>Frog is a really nice and accurate OCR software, it also supports qr code.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sh6nx33u973m7olunl69.png" alt="frog screenshot" /></p>
<p>To install it, just type the following command in the terminal </p>
<pre><code class="lang-bash">flatpak install flathub com.github.tenderowl.frog
</code></pre>
<h3 id="heading-5-solanumhttpsflathuborgappsdetailsorggnomesolanum"><a target="_blank" href="https://flathub.org/apps/details/org.gnome.Solanum">5) Solanum</a></h3>
<p>Its a pretty simple applicatiion for pomodoro technique. </p>
<p><code>The Pomodoro Technique was developed in the late 1980s by then university student Francesco Cirillo. Cirillo was struggling to focus on his studies and complete assignments. Feeling overwhelmed, he asked himself to commit to just 10 minutes of focused study time. Encouraged by the challenge, he found a tomato (pomodoro in Italian) shaped kitchen timer, and the Pomodoro technique was born.</code>
^Wikipedia</p>
<p>Pomodoro is a really nice productivity technique. </p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z7rkmjjvgc8mf2bxtfnl.png" alt="Image description" /></p>
<p>To install it, just type the following command in the terminal </p>
<pre><code class="lang-bash">flatpak install flathub org.gnome.Solanum
</code></pre>
<p>These were 5 softwares that I found really Interesting and use on regular basis. 
To discover more flatpak softwares, you can head over to <a target="_blank" href="https://flathub.org/home">Flathub</a>. </p>
]]></content:encoded></item><item><title><![CDATA[My Hacktober Experience]]></title><description><![CDATA[October, also known as Hacktober for devs, is a really awesome month. Hacktoberfest is a very good oppurtunities for beginners to start their open source journey. Open source is a really fun ride to begin. 
I participated in hacktoberfest as well as ...]]></description><link>https://blog.rachitkhurana.tech/my-hacktober-experience</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/my-hacktober-experience</guid><category><![CDATA[hacktoberfest2022]]></category><category><![CDATA[OpenSource Journey]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Sun, 30 Oct 2022 06:16:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1667109772863/9AUyPFr5g.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>October, also known as Hacktober for devs, is a really awesome month. Hacktoberfest is a very good oppurtunities for beginners to start their open source journey. Open source is a really fun ride to begin. 
I participated in hacktoberfest as well as a hackathon this month and also a opensource event. 
This was kind of my first exeprience for all of these.  </p>
<h2 id="heading-hacktoberfest">Hacktoberfest</h2>
<p>This year, it was my first hacktober. I made some basic contributions in few open source repos. Thats the beauty of hacktoberfest. Even beginners are welcome. Even simplest of the simplest contributions are appreciated. Even if most people do it for swags, still its a nice motivation for beginners to start. 
I completed my 4 contribution just in few days and also received the holopin badges. They look pretty cool to be honest. Here is my holopin board.</p>
<p><strong>Live Holopin Board (This may be changed with different badges if viewed at a later date):</strong>
<a target="_blank" href="https://holopin.io/@dilutewater"><img src="https://holopin.me/dilutewater" alt="@dilutewater's Holopin board" /></a></p>
<p><strong>Static version:</strong>
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7sidokei2y8y894bh2od.png" alt="holopin static" /></p>
<h2 id="heading-hackathon">Hackathon</h2>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/scphjmoshztc4mqxysuh.png" alt="Image description" /></p>
<p>So this month, our college organized a hackathon as well. I decided to participate in it. This was my first ever hackathon. It was quite fun and I also learned a lot. I had an awesome team to work with. 
We were not even looking to win any prize this time. However after completing we think we can win the replit track prize. But the results for the track are still not out. We are still waiting for 1it.</p>
<h2 id="heading-delhifoss-event">DelhiFOSS event</h2>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pyk3cckbi5pctrpq20g2.jpg" alt="Image description" /></p>
<p>I also attended the DelhiFOSS event hosted by FOSS United. It was also very very fun and informative. Met many awesone peoples there. Learned a lot. </p>
<p>Attending all these events was really fun. I learned and enjoyed a lot. Met many new people. </p>
<p>You can also follow me on twitter for regular updates.
Twitter: <a target="_blank" href="https://twitter.com/notnotrachit">https://twitter.com/notnotrachit</a></p>
]]></content:encoded></item><item><title><![CDATA[Re-Dcrypt Cryptic Hunt Making]]></title><description><![CDATA[Hello Everyone, firstly I'm very excited to announce that I'm going to organize a cryptic hunt event. Re-Dcrypt Cryptic Hunt on 8ᵗʰ and 9ᵗʰ October. It will be a 48 hours hunt. 
A cryptic hunt is like an online treasure hunt. You need to  use your br...]]></description><link>https://blog.rachitkhurana.tech/re-dcrypt-cryptic-hunt-making</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/re-dcrypt-cryptic-hunt-making</guid><category><![CDATA[webdev]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Django]]></category><category><![CDATA[cryptichunt ]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Fri, 16 Sep 2022 05:38:41 GMT</pubDate><content:encoded><![CDATA[<p>Hello Everyone, firstly I'm very excited to announce that I'm going to organize a cryptic hunt event. Re-Dcrypt Cryptic Hunt on 8ᵗʰ and 9ᵗʰ October. It will be a 48 hours hunt. 
A cryptic hunt is like an online treasure hunt. You need to  use your brain and the internet to reach to a final answer.
There will be awesome prizes for everyone.<br />Register Now at <a target="_blank" href="https://redcrypt.xyz/">https://redcrypt.xyz/</a></p>
<p>Trailer: <a target="_blank" href="https://youtu.be/790S3n_53x4">https://youtu.be/790S3n_53x4</a></p>
<p>Instagram: <a target="_blank" href="https://instagram.com/re.dcrypt">https://instagram.com/re.dcrypt</a></p>
<p>Discord: <a target="_blank" href="https://discord.com/invite/dY8nAT5SPQ">https://discord.com/invite/dY8nAT5SPQ </a></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/790S3n_53x4">https://youtu.be/790S3n_53x4</a></div>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cr4jngluru6lcrvr77on.gif" alt="redcrypt" /></p>
<h2 id="heading-making">Making</h2>
<p>I have been working on the website and the bot from more than 2 months now. I had my exams in between and a lot more things. But I had a lot of fun building the website and the bot. I used Django for the main backend. I even wrote a daily journal while building this. Even tough I'm not into frontend, yet I made a very nice looking website. I'm very proud of it. I also made a trailer with the help of another person. 
I used Notion to store any relevant article I found which could help me in that. I used many saas services.
One thing that really helped me build it even better is noting down ideas when I couldn't work on them. I heard  saying that our brain is not for storing ideas, its for creating ideas. So whenever I got any idea, I noted it down on notion or clickup. And then worked on it aterwards. Otherwise I would have forgotten them. I will make the code opensource after the hunt and will also make a detailed post explaining all the features. And for questions making , I have 2 more friends helping me in that.</p>
<h3 id="heading-sponsorship">Sponsorship</h3>
<p>We got 2 sponsors as of now, Taskade and gen.xyz . If you are interested in sponsoring the event, you can contact me at <code>hunt@redcrypt.xyz</code></p>
]]></content:encoded></item><item><title><![CDATA[8 Chrome extensions I use as a developer]]></title><description><![CDATA[There are many great chrome extensions out there on the chrome web store. And these are the few extensions that I use on daily basis. 


Bitwarden

https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb?h...]]></description><link>https://blog.rachitkhurana.tech/8-chrome-extensions-i-use-as-a-developer</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/8-chrome-extensions-i-use-as-a-developer</guid><category><![CDATA[chrome extension]]></category><category><![CDATA[Productivity]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Fri, 05 Aug 2022 09:53:29 GMT</pubDate><content:encoded><![CDATA[<p>There are many great chrome extensions out there on the chrome web store. And these are the few extensions that I use on daily basis. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659693084547/MoAF5l55S.png" alt="image.png" /></p>
<ul>
<li><strong>Bitwarden</strong></li>
</ul>
<p><a target="_blank" href="https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb?hl=en-US&amp;utm_source=chrome-ntp-launcher">https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb?hl=en-US&amp;utm_source=chrome-ntp-launcher</a></p>
<p>It is one of the best password managers and I use it for storing my password, and some confidential notes etc.</p>
<ul>
<li><strong>Notion Web clipper</strong></li>
</ul>
<p><a target="_blank" href="https://chrome.google.com/webstore/detail/notion-web-clipper/knheggckgoiihginacbkhaalnibhilkk?hl=en-US&amp;utm_source=chrome-ntp-launcher">https://chrome.google.com/webstore/detail/notion-web-clipper/knheggckgoiihginacbkhaalnibhilkk?hl=en-US&amp;utm_source=chrome-ntp-launcher</a></p>
<p>I have been in many situations when I need to bookmark pages/articles. I use notion web clipper instead. I just add that page to my links database. It even saves the page contents in notion directly so I don’t even need to visit that site afterwards</p>
<ul>
<li><strong>Amino live css editor</strong></li>
</ul>
<p><a target="_blank" href="https://chrome.google.com/webstore/detail/amino-css-editor/pbcpfbcibpcbfbmddogfhcijfpboeaaf?hl=en-US&amp;utm_source=chrome-ntp-launcher">https://chrome.google.com/webstore/detail/amino-css-editor/pbcpfbcibpcbfbmddogfhcijfpboeaaf?hl=en-US&amp;utm_source=chrome-ntp-launcher</a></p>
<p>I really like to customise webpages according to my own preference and system theme. This extension helps me do that. </p>
<ul>
<li><strong>DuckDuckGo privacy essentials</strong></li>
</ul>
<p><a target="_blank" href="https://chrome.google.com/webstore/detail/duckduckgo-privacy-essent/bkdgflcldnnnapblkhphbgpggdiikppg?hl=en-US&amp;utm_source=chrome-ntp-launcher">https://chrome.google.com/webstore/detail/duckduckgo-privacy-essent/bkdgflcldnnnapblkhphbgpggdiikppg?hl=en-US&amp;utm_source=chrome-ntp-launcher</a></p>
<p>I have came across sites that ask for email for verification or for newsletters. So I just give a newly created email (<code>@duck.com</code>) and it forwards to my main email. I can even reply to it through that email. And if I feel like its spamming my inbox , I can just disable that email. </p>
<ul>
<li><strong>OSlash</strong></li>
</ul>
<p><a target="_blank" href="https://chrome.google.com/webstore/detail/oslash/gpljeioabgadbidbkcbhjjglpinfhmal?hl=en-US&amp;utm_source=chrome-ntp-launcher">https://chrome.google.com/webstore/detail/oslash/gpljeioabgadbidbkcbhjjglpinfhmal?hl=en-US&amp;utm_source=chrome-ntp-launcher</a></p>
<p>I have started to use this very recently. The best way to describe it will be a speed dial for internet. You can create o-links for the most important pages/ documents that you visit everyday or frequently. After that you can directly go to it by typing <code>o/&lt;short-name&gt;</code> . Its really handy</p>
<ul>
<li><strong>Slapdash</strong></li>
</ul>
<p><a target="_blank" href="https://chrome.google.com/webstore/detail/slapdash/knjkgoighhalckigihppnlnhekplefmd?hl=en-US&amp;utm_source=chrome-ntp-launcher">https://chrome.google.com/webstore/detail/slapdash/knjkgoighhalckigihppnlnhekplefmd?hl=en-US&amp;utm_source=chrome-ntp-launcher</a></p>
<p>This is also a very useful extension. It indexes all you documents and important files from many different services like notion, google docs, google drive etc and provides a single search for all of them.</p>
<ul>
<li><strong>Sponsorblock</strong></li>
</ul>
<p><a target="_blank" href="https://chrome.google.com/webstore/detail/sponsorblock-for-youtube/mnjggcdmjocbbbhaepdhchncahnbgone?hl=en-US&amp;utm_source=chrome-ntp-launcher">https://chrome.google.com/webstore/detail/sponsorblock-for-youtube/mnjggcdmjocbbbhaepdhchncahnbgone?hl=en-US&amp;utm_source=chrome-ntp-launcher</a></p>
<p>This is a really time saving extension, it can automatically skip all the sponsor segment/end credits/intro etc in a youtube video.</p>
<ul>
<li><strong>octotree</strong></li>
</ul>
<p><a target="_blank" href="https://chrome.google.com/webstore/detail/octotree-github-code-tree/bkhaagjahfmjljalopjnoealnfndnagc?hl=en-US&amp;utm_source=chrome-ntp-launcher">https://chrome.google.com/webstore/detail/octotree-github-code-tree/bkhaagjahfmjljalopjnoealnfndnagc?hl=en-US&amp;utm_source=chrome-ntp-launcher</a></p>
<p>This extension is really useful if you use github regularly. It basically adds a code-tree like layout to github.</p>
]]></content:encoded></item><item><title><![CDATA[Good Bye ATOM 👋]]></title><description><![CDATA[So Github has decided to discontinue its ATOM text editor.you can read more about it here:  https://github.blog/2022-06-08-sunsetting-atom/. ATOM will be discontinued on 15th December
In 2018, Microsoft acquired Github, and VS Code is also owned by M...]]></description><link>https://blog.rachitkhurana.tech/good-bye-atom</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/good-bye-atom</guid><category><![CDATA[Atom]]></category><category><![CDATA[Visual Studio Code]]></category><category><![CDATA[programing]]></category><category><![CDATA[IDEs]]></category><category><![CDATA[Text Editors]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Sun, 24 Jul 2022 06:51:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658645462494/96peXheFe.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So Github has decided to discontinue its ATOM text editor.you can read more about it here:  <a target="_blank" href="https://github.blog/2022-06-08-sunsetting-atom/">https://github.blog/2022-06-08-sunsetting-atom/</a>. ATOM will be discontinued on 15th December
In 2018, Microsoft acquired Github, and VS Code is also owned by Microsoft. So we all knew this was eventually going to happen. They won't be maintaining two different softwares for the same purpose. </p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o6wtus1roiajbo2vimoj.png" alt="ATOM logo" /></p>
<h2 id="heading-are-vs-code-and-atom-really-that-similar">Are VS Code and ATOM really that similar?</h2>
<p>Both are code editor, but offer very interesting features for text editing. Both are based on electron. But the main difference was user experience. VS Code is more inclined towards being an IDE, while Atom is more inclined towards being just a text editor for developers. </p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0smsgmpa55t4pqboht8c.png" alt="ATOM or VS Code" />
<sub><sup>Image credit - itsfoss.com</sup></sub></p>
<h2 id="heading-why-use-atom-instead-of-vs-code">Why use ATOM instead of VS Code?</h2>
<p>VS Code is great. But there are many times I just wanted to make some quick edits. At that point I didn't wanted to open VS Code because its quite heave when compared to ATOM due to so many extensions I have installed 😅. I also prefer to use ATOM when working on small projects because ATOM is faster than VS Code. ATOM also supports extensions and they are pretty useful too. But even after installing so many extensions it was still lightweight and faster than VS Code.
ATOM is for people who wanted more than a text editor but still want it lightweight.</p>
<h2 id="heading-what-is-the-future-of-atom">What is the future of ATOM?</h2>
<p>ATOM will be officially discontinued on December 15th. Till then you can use it normally. After that also you can use it but there won't be any updates. You will still be able to use extensions. However I think that the development of extensions will also stop after that. And eventually it will become very outdated. Since ATOM is open source, many forks may emerge but I don't think that they will get the same amount of attention from the community and extension developers. </p>
<h2 id="heading-what-are-the-alternatives">What are the alternatives?</h2>
<p>There are a few good alternatives to ATOM. 
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dqp1umvqwjcb3rho7y4b.png" alt="brackets logo" /> 
First is <a target="_blank" href="https://brackets.io/">Brackets</a> by Adobe. I mainly for frontend developers only. So I didn't want to use it. </p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6iqa5x9bumlf5ji877um.png" alt="sublime text" /></p>
<p>Next is <a target="_blank" href="https://www.sublimetext.com/">Sublime text</a>, Its really good, fast, and easy to use. It also supports various extensions. However, its not free. Most of the features are there in the trial version but the trial version show unlicensed product on the top bar , prompts many times to purchase a license. These small things sometimes makes the experience a little less enjoyable. If you can afford Sublime text, then you should definitely buy and use it. Its really great.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1vlsqhjbxy6ssyeo03rn.png" alt="Kate logo" /></p>
<p>Another one is <a target="_blank" href="https://kate-editor.org/">Kate</a>. The text editor from the developers of KDE plasma. And since I'm using KDE, it works really great for me.(Its cross platform, supports Win, Mac, Linux) Its very customizable, offers many plugins, is very lightweight, has a lot of features. The only thing it lacks is support for third party plugins. But noticing the nature of KDE software, I think it will allow third party plugins soon as well. </p>
<p>For me, I will be switching back and forth between Kate and ATOM as of now. </p>
]]></content:encoded></item><item><title><![CDATA[PWAs: From the perspective of a web developer]]></title><description><![CDATA[Everyone use apps on their phones, but creating an app for each platform can be a little tough. So here comes PWAs. PWA stands for Progressive Web App. They look like normal apps, feels like normal apps, but aren't normal apps, instead they are just ...]]></description><link>https://blog.rachitkhurana.tech/pwas-from-the-perspective-of-a-web-developer</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/pwas-from-the-perspective-of-a-web-developer</guid><category><![CDATA[PWA]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[web application]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Sun, 10 Jul 2022 05:34:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1657431184839/3LSVqvBss.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://user-images.githubusercontent.com/3104648/28352004-a055292c-6c4b-11e7-9c6b-a94cdc2a5458.png" alt="https://user-images.githubusercontent.com/3104648/28352004-a055292c-6c4b-11e7-9c6b-a94cdc2a5458.png" /></p>
<p>Everyone use apps on their phones, but creating an app for each platform can be a little tough. So here comes PWAs. PWA stands for Progressive Web App. They look like normal apps, feels like normal apps, but aren't normal apps, instead they are just a website that runs in a standalone window.</p>
<h2 id="heading-developing-pwas">Developing PWAs</h2>
<p>PWAs are very easy to make,  every responsive website can be turned into a PWA easily. You just need to add the icons, service worker and a manifest file. That's it. </p>
<p>Here are few complete guides for making PWAs:</p>
<p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps">https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps</a></p>
<p><a target="_blank" href="https://web.dev/learn/pwa/">https://web.dev/learn/pwa/</a></p>
<p><a target="_blank" href="https://web.dev/progressive-web-apps/">https://web.dev/progressive-web-apps/</a></p>
<h2 id="heading-app-usage">App Usage</h2>
<p>After that a user can install your PWA app just by visiting your website and installing it via the browser. And then it appears in the app list just like a normal app. It can then be uninstalled like a normal app as well.</p>
<h2 id="heading-benefits-of-pwa">Benefits of PWA</h2>
<ul>
<li><p>Not dependent on any app marketplace</p>
<p>   One benefit of PWAs is that you don't need to use the OSs app marketplace. You won't need to pay the yearly fees to apple for being an app developer. And you won't need to pay to google as well. </p>
</li>
<li><p>Easier to Maintain</p>
<p>  Maintaining a PWA is as simple as maintaining a website. Want to update your PWA? Just update your website. Boom, your app is also updated.</p>
</li>
<li><p>Lightweight Size</p>
<p>  Since PWAs are just websites, the size of PWA is very less, only about a few MBs.</p>
</li>
<li><p>Cross-platform</p>
<p>  You just need to make your PWA once, it will be available on all major platforms like Android, iOS, Windows, Linux, MacOS etc. Provided your website is responsive.</p>
</li>
<li><p>Can even work offline</p>
<p>  You can cache files through service worker and make it even work offline</p>
</li>
</ul>
<p>These were just a few of the benefits of PWAs.</p>
<h2 id="heading-limitations">Limitations</h2>
<ul>
<li><p>No access to key system resources.</p>
<p>  You can only access few things that a website can access. </p>
</li>
<li><p>Competitively less exposure</p>
<p>  Since your app isn’t on play store or app store, you may get less exposore in that aspect, but you can package your PWAs and even publish it there.</p>
</li>
<li><p>Limited functionality</p>
<p>  PWAs have comparatively less functionality when comparing with native apps. </p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>PWAs are great. So if you are just a web developer and have no idea about app development for Android or iOS . you can still create apps for mobiles. And its damn simple. If you can’t afford to hire a app developer, you can create a PWA instead. And if your app is va simple app and don’t require much system APIs then, I would suggest to just stick with PWAs only instead of Native Apps. Its easier and will even consume less space on users device.</p>
]]></content:encoded></item><item><title><![CDATA[Convert Django website to PWA]]></title><description><![CDATA[We can convert a Django website to a PWA (Progressive web app) very easily. 
PWA are web apps that look like a normal native app on the phone or PC. I consider it to be a shortcut for making cross-platform applications

We will be using django-pwa pa...]]></description><link>https://blog.rachitkhurana.tech/convert-django-website-to-pwa</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/convert-django-website-to-pwa</guid><category><![CDATA[Django]]></category><category><![CDATA[Python]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[PWA]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Mon, 27 Jun 2022 16:05:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1656345807848/UibtTFuiD.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We can convert a Django website to a PWA (Progressive web app) very easily. 
PWA are web apps that look like a normal native app on the phone or PC. I consider it to be a shortcut for making cross-platform applications
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uwolf4m6hf8ehawuat48.png" alt="PWA logo" /></p>
<p>We will be using <code>django-pwa</code> package for the same.</p>
<h3 id="heading-installation">Installation</h3>
<ul>
<li>Installing the <code>django-pwa</code> package<pre><code class="lang-bash">pip install django-pwa
</code></pre>
</li>
<li>Add <code>pwa</code> to your list of INSTALLED_APPS in settings.py:</li>
</ul>
<pre><code class="lang-python"><span class="hljs-comment"># project/settings.py</span>
INSTALLED_APPS = [
    ...
    <span class="hljs-string">'pwa'</span>,
    ...
]
</code></pre>
<h3 id="heading-configuration">Configuration</h3>
<ul>
<li>Adding PWA settings to settings.py file</li>
</ul>
<pre><code class="lang-python"><span class="hljs-comment"># project/settings.py</span>

PWA_APP_NAME = <span class="hljs-string">'My App'</span>
PWA_APP_DESCRIPTION = <span class="hljs-string">"My app description"</span>
PWA_APP_THEME_COLOR = <span class="hljs-string">'#0A0302'</span>
PWA_APP_BACKGROUND_COLOR = <span class="hljs-string">'#ffffff'</span>
PWA_APP_DISPLAY = <span class="hljs-string">'standalone'</span>
PWA_APP_SCOPE = <span class="hljs-string">'/'</span>
PWA_APP_ORIENTATION = <span class="hljs-string">'any'</span>
PWA_APP_START_URL = <span class="hljs-string">'/'</span>
PWA_APP_STATUS_BAR_COLOR = <span class="hljs-string">'default'</span>
PWA_APP_ICONS = [
    {
        <span class="hljs-string">'src'</span>: <span class="hljs-string">'/static/images/my_app_icon.png'</span>,
        <span class="hljs-string">'sizes'</span>: <span class="hljs-string">'160x160'</span>
    }
]
PWA_APP_ICONS_APPLE = [
    {
        <span class="hljs-string">'src'</span>: <span class="hljs-string">'/static/images/my_apple_icon.png'</span>,
        <span class="hljs-string">'sizes'</span>: <span class="hljs-string">'160x160'</span>
    }
]
PWA_APP_SPLASH_SCREEN = [
    {
        <span class="hljs-string">'src'</span>: <span class="hljs-string">'/static/images/icons/splash-640x1136.png'</span>,
        <span class="hljs-string">'media'</span>: <span class="hljs-string">'(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)'</span>
    }
]
PWA_APP_DIR = <span class="hljs-string">'ltr'</span>
PWA_APP_LANG = <span class="hljs-string">'en-US'</span>
</code></pre>
<h4 id="heading-making-it-compatible-with-django-4">Making it compatible with Django 4</h4>
<p>Currently <code>django-pwa</code> version 1.0.10 is not compatible with Django 4. So if you are using an earlier version of Django or this package has received updates, you can skip these steps (marked with <code>*</code>).</p>
<ul>
<li>*Make a new folder in the base directory*</li>
</ul>
<p>I named it pwa1</p>
<ul>
<li>*Make a new file urls.py with the following content*</li>
</ul>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> re_path <span class="hljs-keyword">as</span> url

<span class="hljs-keyword">from</span> .views <span class="hljs-keyword">import</span> manifest, service_worker, offline

<span class="hljs-comment"># Serve up serviceworker.js and manifest.json at the root</span>
urlpatterns = [
    url(<span class="hljs-string">r'^serviceworker\.js$'</span>, service_worker, name=<span class="hljs-string">'serviceworker'</span>),
    url(<span class="hljs-string">r'^manifest\.json$'</span>, manifest, name=<span class="hljs-string">'manifest'</span>),
    url(<span class="hljs-string">'^offline/$'</span>, offline, name=<span class="hljs-string">'offline'</span>)
]
</code></pre>
<ul>
<li>Add the following to your project's <code>urls.py</code> file</li>
</ul>
<pre><code class="lang-python">...
urlpatterns=[
    ...
    path(<span class="hljs-string">''</span>, include(<span class="hljs-string">'pwa.urls'</span>)),
    <span class="hljs-comment"># if you used the above method for compatibility then use the following code instead</span>
    <span class="hljs-comment">#path('', include('pwa1.urls')),</span>
    ...
    ]
</code></pre>
<ul>
<li>Make a <code>serviceworker.js</code> file in your static folder with the following content.</li>
</ul>
<pre><code class="lang-js"><span class="hljs-comment">// Base Service Worker implementation.  To use your own Service Worker, set the PWA_SERVICE_WORKER_PATH variable in settings.py</span>

<span class="hljs-keyword">var</span> staticCacheName = <span class="hljs-string">"django-pwa-v"</span> + <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime();
<span class="hljs-keyword">var</span> filesToCache = [
    <span class="hljs-string">'/offline'</span>,
    <span class="hljs-string">'/css/django-pwa-app.css'</span>,
    <span class="hljs-string">'/images/icons/icon-72x72.png'</span>,
    <span class="hljs-string">'/images/icons/icon-96x96.png'</span>,
    <span class="hljs-string">'/images/icons/icon-128x128.png'</span>,
    <span class="hljs-string">'/images/icons/icon-144x144.png'</span>,
    <span class="hljs-string">'/images/icons/icon-152x152.png'</span>,
    <span class="hljs-string">'/images/icons/icon-192x192.png'</span>,
    <span class="hljs-string">'/images/icons/icon-384x384.png'</span>,
    <span class="hljs-string">'/images/icons/icon-512x512.png'</span>,
    <span class="hljs-string">'/static/images/icons/splash-640x1136.png'</span>,
    <span class="hljs-string">'/static/images/icons/splash-750x1334.png'</span>,
    <span class="hljs-string">'/static/images/icons/splash-1242x2208.png'</span>,
    <span class="hljs-string">'/static/images/icons/splash-1125x2436.png'</span>,
    <span class="hljs-string">'/static/images/icons/splash-828x1792.png'</span>,
    <span class="hljs-string">'/static/images/icons/splash-1242x2688.png'</span>,
    <span class="hljs-string">'/static/images/icons/splash-1536x2048.png'</span>,
    <span class="hljs-string">'/static/images/icons/splash-1668x2224.png'</span>,
    <span class="hljs-string">'/static/images/icons/splash-1668x2388.png'</span>,
    <span class="hljs-string">'/static/images/icons/splash-2048x2732.png'</span>
];

<span class="hljs-comment">// Cache on install</span>
self.addEventListener(<span class="hljs-string">"install"</span>, <span class="hljs-function"><span class="hljs-params">event</span> =&gt;</span> {
    <span class="hljs-built_in">this</span>.skipWaiting();
    event.waitUntil(
        caches.open(staticCacheName)
            .then(<span class="hljs-function"><span class="hljs-params">cache</span> =&gt;</span> {
                <span class="hljs-keyword">return</span> cache.addAll(filesToCache);
            })
    )
});

<span class="hljs-comment">// Clear cache on activate</span>
self.addEventListener(<span class="hljs-string">'activate'</span>, <span class="hljs-function"><span class="hljs-params">event</span> =&gt;</span> {
    event.waitUntil(
        caches.keys().then(<span class="hljs-function"><span class="hljs-params">cacheNames</span> =&gt;</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-built_in">Promise</span>.all(
                cacheNames
                    .filter(<span class="hljs-function"><span class="hljs-params">cacheName</span> =&gt;</span> (cacheName.startsWith(<span class="hljs-string">"django-pwa-"</span>)))
                    .filter(<span class="hljs-function"><span class="hljs-params">cacheName</span> =&gt;</span> (cacheName !== staticCacheName))
                    .map(<span class="hljs-function"><span class="hljs-params">cacheName</span> =&gt;</span> caches.delete(cacheName))
            );
        })
    );
});

<span class="hljs-comment">// Serve from Cache</span>
self.addEventListener(<span class="hljs-string">"fetch"</span>, <span class="hljs-function"><span class="hljs-params">event</span> =&gt;</span> {
    event.respondWith(
        caches.match(event.request)
            .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> {
                <span class="hljs-keyword">return</span> response || fetch(event.request);
            })
            .catch(<span class="hljs-function">() =&gt;</span> {
                <span class="hljs-keyword">return</span> caches.match(<span class="hljs-string">'offline'</span>);
            })
    )
});
</code></pre>
<ul>
<li>Load PWA meta in templates
Add the following tags in your <code>base.html</code> file.</li>
</ul>
<pre><code class="lang-html">{% load pwa %}

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    ...
    {% progressive_web_app_meta %}
    ...
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
</code></pre>
<h2 id="heading-thats-all">That's All 🎉</h2>
<p>You can now see an option to install your site as an app in your supported browser on mobile as well as PC</p>
]]></content:encoded></item><item><title><![CDATA[Integrating hCaptcha with Django-allauth]]></title><description><![CDATA[We may face issues when someone uses bots to abuse our system and send automated signup/password reset to random people. So hCaptcha is a really good way to avoid bots. 
Setting Up hCaptcha account

First we need new hCaptcha account. If you don't ha...]]></description><link>https://blog.rachitkhurana.tech/integrating-hcaptcha-with-django-allauth</link><guid isPermaLink="true">https://blog.rachitkhurana.tech/integrating-hcaptcha-with-django-allauth</guid><category><![CDATA[Django]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Rachit Khurana]]></dc:creator><pubDate>Tue, 21 Jun 2022 05:00:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1655786898125/khb0aoRC6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/drcowu51zfe4feeuj7zp.png" alt="Image description" /></p>
<p>We may face issues when someone uses bots to abuse our system and send automated signup/password reset to random people. So hCaptcha is a really good way to avoid bots. </p>
<h2 id="heading-setting-up-hcaptcha-account">Setting Up hCaptcha account</h2>
<ul>
<li>First we need new hCaptcha account. If you don't have an account, then create one at <a target="_blank" href="https://dashboard.hcaptcha.com/signup">https://dashboard.hcaptcha.com/signup</a>. </li>
<li>After that you need to go on your hCaptcha dashboard's sites page at <a target="_blank" href="https://dashboard.hcaptcha.com/sites">https://dashboard.hcaptcha.com/sites</a>.</li>
<li>Then create a new site, you can name it anything you want. After that click on the settings icon next to the site you created. You will see a site key. Copy it and keep it someone. </li>
<li>Go to your account settings at <a target="_blank" href="https://dashboard.hcaptcha.com/settings">https://dashboard.hcaptcha.com/settings</a> and then copy and keep the secret key.</li>
</ul>
<h2 id="heading-installing-hcaptcha">Installing hCaptcha</h2>
<p>We will be using django-hCaptcha package from pypi. </p>
<ul>
<li>Install it using the following command<pre><code class="lang-bash">pip install django-hCaptcha
</code></pre>
</li>
<li>Add “hcaptcha” to your INSTALLED_APPS setting like this:</li>
</ul>
<pre><code class="lang-python"><span class="hljs-comment"># project/settings.py</span>

INSTALLED_APPS = [
    ...
    <span class="hljs-string">'hcaptcha'</span>,
]
</code></pre>
<ul>
<li>Addsitekey and secret key which we kept earlier to your settings.py file</li>
</ul>
<pre><code class="lang-python"><span class="hljs-comment"># project/settings.py</span>

...
HCAPTCHA_SITEKEY = <span class="hljs-string">'&lt;your sitekey&gt;'</span>
HCAPTCHA_SECRET = <span class="hljs-string">'&lt;your secret key&gt;'</span>
...
</code></pre>
<h2 id="heading-add-hcaptcha-to-forms">Add hCaptcha to forms</h2>
<ul>
<li>Extend default allauth forms
I referred to this article by geeksforgeeks for the same: 
<a target="_blank" href="https://www.geeksforgeeks.org/python-extending-and-customizing-django-allauth/">https://www.geeksforgeeks.org/python-extending-and-customizing-django-allauth/</a><ul>
<li>Make forms.py file in any django app folder</li>
</ul>
</li>
</ul>
<pre><code class="lang-python"><span class="hljs-comment"># app/forms.py</span>

<span class="hljs-keyword">from</span> allauth.account.forms <span class="hljs-keyword">import</span> SignupForm, ResetPasswordForm
<span class="hljs-keyword">from</span> hcaptcha.fields <span class="hljs-keyword">import</span> hCaptchaField


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomSignupForm</span>(<span class="hljs-params">SignupForm</span>):</span>
    hcaptcha = hCaptchaField(theme=<span class="hljs-string">'dark'</span>)
    <span class="hljs-comment"># if the order of fields isn't as you expected ,then you can use field_order</span>
    <span class="hljs-comment">#field_order = ['username', 'email', 'password1', 'password2', 'hcaptcha']</span>
    <span class="hljs-comment">#customize this according to your form                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           </span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomForgetPassword</span>(<span class="hljs-params">ResetPasswordForm</span>):</span>
    hcaptcha = hCaptchaField(theme=<span class="hljs-string">'dark'</span>)
</code></pre>
<ul>
<li>Make these as the default forms by declaring them in settings.py file</li>
</ul>
<pre><code class="lang-python"><span class="hljs-comment"># project/settings.py</span>
...
ACCOUNT_FORMS = {
    <span class="hljs-string">'signup'</span>: <span class="hljs-string">'&lt;app&gt;.forms.MyCustomSignupForm'</span>,
    <span class="hljs-string">'reset_password'</span>: <span class="hljs-string">'&lt;app&gt;.forms.CustomForgetPassword'</span>,}
...
</code></pre>
<h2 id="heading-all-done">All Done 🎉</h2>
<h2 id="heading-congrats">Congrats</h2>
]]></content:encoded></item></channel></rss>