<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Rachit Khurana</title>
    <description>The latest articles on Forem by Rachit Khurana (@dilutewater).</description>
    <link>https://forem.com/dilutewater</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F646495%2Fd7413671-f0d6-46c4-8a0a-a5d3c667f68f.jpg</url>
      <title>Forem: Rachit Khurana</title>
      <link>https://forem.com/dilutewater</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dilutewater"/>
    <language>en</language>
    <item>
      <title>Building Jist: An AI-Powered Notification Summarizer with GitHub Copilot CLI</title>
      <dc:creator>Rachit Khurana</dc:creator>
      <pubDate>Sun, 15 Feb 2026 14:12:02 +0000</pubDate>
      <link>https://forem.com/dilutewater/building-jist-an-ai-powered-notification-summarizer-with-github-copilot-cli-4din</link>
      <guid>https://forem.com/dilutewater/building-jist-an-ai-powered-notification-summarizer-with-github-copilot-cli-4din</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-01-21"&gt;GitHub Copilot CLI Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Jist&lt;/strong&gt; is an open-source Android application that intercepts notifications from apps like WhatsApp, Telegram, Gmail, Slack, and more batches them per contact/group/thread and uses LLM APIs to generate concise, intelligent summaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🔔 &lt;strong&gt;Notification Capture&lt;/strong&gt; — Listens to all app notifications via Android's &lt;code&gt;NotificationListenerService&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🤖 &lt;strong&gt;Multi-Model LLM Support&lt;/strong&gt; — OpenAI, Gemini, Claude, OpenRouter, and any OpenAI-compatible API&lt;/li&gt;
&lt;li&gt;⚙️ &lt;strong&gt;Model Selection&lt;/strong&gt; — Configure your preferred LLM provider and model&lt;/li&gt;
&lt;li&gt;📋 &lt;strong&gt;Auto Mode&lt;/strong&gt; — Background summarization of notifications&lt;/li&gt;
&lt;li&gt;🔑 &lt;strong&gt;Bring Your Own Key&lt;/strong&gt; — Users provide their own API keys, no backend needed&lt;/li&gt;
&lt;li&gt;🔒 &lt;strong&gt;Privacy First&lt;/strong&gt; — All processing on-device, only notification text sent to chosen LLM&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Modern UI&lt;/strong&gt; — Material Design 3&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Screen Captures
&lt;/h2&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/mAeuitSsNAU"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fvyfja1qn58y147yr9osz.png" class="article-body-image-wrapper"&gt;&lt;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%2Fvyfja1qn58y147yr9osz.png" alt="Screenshots"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tech Stack:
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;Kotlin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI&lt;/td&gt;
&lt;td&gt;Jetpack Compose, Material Design 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;Room&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  My Experience with GitHub Copilot CLI
&lt;/h2&gt;

&lt;p&gt;Building Jist with GitHub Copilot CLI was an incredible experience. Here's how I leveraged its capabilities throughout development:&lt;/p&gt;

&lt;h3&gt;
  
  
  🎯 Model Selection Strategy
&lt;/h3&gt;

&lt;p&gt;One of the most powerful features of Copilot CLI is the ability to switch between different AI models for different tasks. I developed a mental model for when to use each:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gemini 3 Pro&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;UI/Compose code&lt;/td&gt;
&lt;td&gt;Excellent at visualizing layouts, Material 3 components, and Jetpack Compose patterns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Opus 4.6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Planning &amp;amp; architecture&lt;/td&gt;
&lt;td&gt;Superior reasoning for system design, database schemas, and complex logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GPT-5.2 Codex / Sonnet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;General development&lt;/td&gt;
&lt;td&gt;Balanced for boilerplate, testing, and debugging&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  🤖 Agent Skills
&lt;/h3&gt;

&lt;p&gt;Copilot CLI's has the ability to use skills proper to give more accurate and contextual results, so I installed these skills:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Android Jetpack Compose&lt;/strong&gt;: For building declarative UIs with modern Compose patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Material Design 3&lt;/strong&gt;: For implementing Material You theming, dynamic colors, and expressive components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These skills provided context-aware suggestions specific to Android development, reducing the learning curve significantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔧 MCP Servers
&lt;/h3&gt;

&lt;p&gt;I used Model Context Protocol (MCP) servers to enhance productivity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;File System MCP&lt;/strong&gt;: For navigating the Android project structure and understanding the codebase&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub MCP&lt;/strong&gt;: For checking issues and managing development workflow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Context Providers&lt;/strong&gt;: For Android-specific patterns and best practices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And more..&lt;/p&gt;

&lt;p&gt;These MCPs enabled Copilot to understand project context deeply, resulting in more accurate and relevant suggestions.&lt;/p&gt;

&lt;h3&gt;
  
  
  💻 How It Impacted My Development
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Rapid Prototyping&lt;/strong&gt;: Copilot CLI helped generate boilerplate code, letting me focus on business logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning Android Compose&lt;/strong&gt;: As someone relatively new to Jetpack Compose, asking Copilot about Material 3 components accelerated learning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture Decisions&lt;/strong&gt;: Switched to Opus for planning database schemas and service architectures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging&lt;/strong&gt;: When issues arose, switching to Claude helped trace through complex code flows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI Polish&lt;/strong&gt;: Gemini's strength in visual code helped create polished, modern interfaces&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  📊 Impact on Development
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time Saved&lt;/strong&gt;: Significant reduction in boilerplate code writing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality Improved&lt;/strong&gt;: Better adherence to Jetpack Compose and Material 3 best practices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning Accelerated&lt;/strong&gt;: Fast track understanding of Android architecture components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creativity Boosted&lt;/strong&gt;: Focus on unique features rather than getting stuck on syntax&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Few Challenges &amp;amp; Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Challenge 1: Nested Scrolling in Compose
&lt;/h3&gt;

&lt;p&gt;The onboarding screen crashed due to nested scrollable containers. Copilot CLI helped identify and fix the issue by explaining Compose measurement constraints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 2: Battery Optimization Handling
&lt;/h3&gt;

&lt;p&gt;Different Android OEMs handle battery optimization differently. Used Copilot to research and implement proper guidance for users across Samsung, OnePlus, Xiaomi, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 3: Multi-Model LLM Abstraction
&lt;/h3&gt;

&lt;p&gt;Creating a unified interface for different LLM providers with different APIs was complex. Copilot helped design a clean factory pattern that works seamlessly with OpenAI, Gemini, Claude, and OpenRouter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot CLI transformed my development experience building Jist. The ability to switch between specialized AI models for different tasks, rather than using a one size fits all approach unlocked new levels of productivity and code quality.&lt;/p&gt;

&lt;p&gt;The combination of Copilot CLI's agentic capabilities, MCP servers, and model selection made this complex Android application achievable in a fraction of the time it would have taken otherwise.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Thank you for considering my submission!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/notnotrachit/jist" rel="noopener noreferrer"&gt;github.com/notnotrachit/jist&lt;/a&gt;&lt;/p&gt;




</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>My Portfolio Got a Glow-Up</title>
      <dc:creator>Rachit Khurana</dc:creator>
      <pubDate>Mon, 19 Jan 2026 19:27:33 +0000</pubDate>
      <link>https://forem.com/dilutewater/my-portfolio-got-a-glow-up-1mch</link>
      <guid>https://forem.com/dilutewater/my-portfolio-got-a-glow-up-1mch</guid>
      <description>&lt;h2&gt;
  
  
  My Portfolio Got a Glow-Up (Thanks to Gemini)
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/new-year-new-you-google-ai-2025-12-31"&gt;New Year, New You Portfolio Challenge Presented by Google AI&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;Hello everyone, I'm &lt;strong&gt;Rachit Khurana&lt;/strong&gt;, a Full Stack Developer who loves building things that live on the internet. Currently, I'm an Intern at &lt;a href="https://hyathi.com/" rel="noopener noreferrer"&gt;Hyathi Technologies&lt;/a&gt;, and building &lt;a href="https://bossai.tech/?ref=rachit" rel="noopener noreferrer"&gt;BossAI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm passionate about crafting &lt;strong&gt;scalable web applications&lt;/strong&gt; and exploring new technologies. My journey spans across frontend frameworks like React and Next.js to backend technologies like Django, FastAPI, and Golang. I believe in the philosophy of "FAFO", constantly experimenting and learning by doing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Portfolio
&lt;/h2&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__cloud-run"&gt;
  &lt;iframe height="600px" src="https://notnotrachit-github-io-859373969626.asia-south2.run.app"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;




&lt;p&gt;&lt;a href="https://www.rcht.dev" rel="noopener noreferrer"&gt;Portfolio Link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;p&gt;This portfolio is built with a modern, performance-focused tech stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework&lt;/strong&gt;: &lt;a href="https://tanstack.com/start" rel="noopener noreferrer"&gt;TanStack Start&lt;/a&gt; with React 19 — for blazing-fast SSR and seamless routing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling&lt;/strong&gt;: &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;TailwindCSS 4.0&lt;/a&gt; — for rapid, utility-first styling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Animations&lt;/strong&gt;: &lt;a href="https://www.framer.com/motion/" rel="noopener noreferrer"&gt;Framer Motion&lt;/a&gt; + &lt;a href="https://greensock.com/gsap/" rel="noopener noreferrer"&gt;GSAP&lt;/a&gt; — for smooth, cinematic animations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3D Graphics&lt;/strong&gt;: &lt;a href="https://threejs.org/" rel="noopener noreferrer"&gt;Three.js&lt;/a&gt; with &lt;a href="https://docs.pmnd.rs/react-three-fiber" rel="noopener noreferrer"&gt;@react-three/fiber&lt;/a&gt; — for interactive 3D elements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smooth Scrolling&lt;/strong&gt;: &lt;a href="https://lenis.darkroom.engineering/" rel="noopener noreferrer"&gt;Lenis&lt;/a&gt; — for butter-smooth scroll experiences&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typography&lt;/strong&gt;: &lt;a href="https://fonts.google.com/specimen/Outfit" rel="noopener noreferrer"&gt;Outfit&lt;/a&gt;, &lt;a href="https://fonts.google.com/specimen/Space+Grotesk" rel="noopener noreferrer"&gt;Space Grotesk&lt;/a&gt;, and &lt;a href="https://fonts.google.com/specimen/Syne" rel="noopener noreferrer"&gt;Syne&lt;/a&gt; from Google Fonts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt;: Google Cloud Run — for scalable, containerized hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The entire codebase is open source — &lt;a href="https://github.com/notnotrachit/notnotrachit.github.io" rel="noopener noreferrer"&gt;check it out on GitHub&lt;/a&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  Development Process
&lt;/h3&gt;

&lt;p&gt;I had a previous portfolio built with Next.js (&lt;a href="https://v2.rachitkhurana.tech" rel="noopener noreferrer"&gt;check it out here&lt;/a&gt;), but I wanted something completely fresh — a ground-up redesign that felt modern and unique. So I fed my old portfolio to &lt;strong&gt;Gemini 3 Pro&lt;/strong&gt; in the &lt;strong&gt;Antigravity IDE&lt;/strong&gt; along with this initial prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"This is my portfolio. Change it fully. Make it look modern, and unique yet minimalistic. Make it as unique as possible. I don't want it to look vibe coded. It should feel like a professional company designed it. Feel free to use any third party tools/libraries. Also make it from scratch. I don't wanna use Next.js at all now. Rebuild it using TanStack Start."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(Lol, I know its kind of a funny/weird prompt, but Gemini handled it like a pro)&lt;/p&gt;

&lt;p&gt;From there, everything was built through &lt;strong&gt;iterative prompting&lt;/strong&gt;. I explored multiple aesthetics and design directions with Gemini — trying different color schemes, animation styles, and layouts — until I landed on this cifi inspired, holographic design that felt just right.&lt;/p&gt;

&lt;p&gt;The AI assistance was particularly helpful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generating complex CSS animations and transitions&lt;/li&gt;
&lt;li&gt;Implementing the parallax effects and smooth scrolling behavior&lt;/li&gt;
&lt;li&gt;Debugging tricky edge cases in responsive design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The workflow was incredibly efficient — I would describe what I wanted, Gemini would implement it, and we'd refine it together until it matched my vision.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm Most Proud Of
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Modern, Minimalist Design
&lt;/h3&gt;

&lt;p&gt;I'm really proud of the &lt;strong&gt;modern aesthetic&lt;/strong&gt; I achieved with this portfolio. The design combines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Holographic elements&lt;/strong&gt;: The profile picture has a cyberpunk-inspired glass container with animated borders, scanline effects, and a floating animation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aurora backgrounds&lt;/strong&gt;: Subtle, animated gradient backgrounds that create depth without distraction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Glass morphism&lt;/strong&gt;: Frosted glass effects throughout for that premium, modern feel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smooth micro-animations&lt;/strong&gt;: Every interaction feels polished with carefully crafted transitions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Hidden Easter Eggs
&lt;/h3&gt;

&lt;p&gt;One of the most fun parts of building this portfolio was adding &lt;strong&gt;multiple hidden easter eggs&lt;/strong&gt; throughout the site! With Gemini's help, I was able to quickly implement several fun surprises that reward curious visitors who like to explore and interact with websites.&lt;/p&gt;

&lt;p&gt;I won't spoil the fun by revealing them all here, but I encourage you to visit the portfolio and try to find them yourself! Some involve keyboard interactions, some require a bit of patience, and others are hidden in plain sight. Happy hunting! &lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>googleaichallenge</category>
      <category>portfolio</category>
      <category>gemini</category>
    </item>
    <item>
      <title>Implementing App notifications: The FOSS way</title>
      <dc:creator>Rachit Khurana</dc:creator>
      <pubDate>Sat, 12 Jul 2025 06:16:50 +0000</pubDate>
      <link>https://forem.com/dilutewater/implementing-app-notifications-the-foss-way-lc2</link>
      <guid>https://forem.com/dilutewater/implementing-app-notifications-the-foss-way-lc2</guid>
      <description>&lt;h2&gt;
  
  
  The Beginning: Building My First "Real" App
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;From the start, I had one clear goal: &lt;strong&gt;avoid third-party dependencies wherever possible&lt;/strong&gt;. No BaaS solutions like Supabase, Appwrite, or Firebase. I wanted to build everything myself to truly understand the underlying technologies.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Notification Wall
&lt;/h2&gt;

&lt;p&gt;Then came the next feature: &lt;strong&gt;push notifications&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;A quick Google search seemed to confirm what every developer "knows"—Firebase Cloud Messaging (FCM) is &lt;em&gt;the&lt;/em&gt; solution for mobile notifications. FCM appeared to be the only viable option.&lt;/p&gt;

&lt;p&gt;Reluctantly, I integrated FCM into both my app and backend. It worked.&lt;/p&gt;

&lt;h2&gt;
  
  
  The F-Droid Reality Check
&lt;/h2&gt;

&lt;p&gt;Everything changed when I decided to release my app on &lt;strong&gt;F-Droid&lt;/strong&gt;—the open-source Android app marketplace.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;But this sparked a crucial question: &lt;em&gt;If other apps on F-Droid support notifications, there must be alternatives to FCM, right?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Down the Rabbit Hole: Discovering UnifiedPush
&lt;/h2&gt;

&lt;p&gt;This question sent me deep into research mode. And that's when I stumbled upon something revolutionary: &lt;strong&gt;&lt;a href="https://unifiedpush.org/" rel="noopener noreferrer"&gt;UnifiedPush&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UnifiedPush&lt;/strong&gt; 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.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of forcing all notifications through a single company's servers (like FCM), UnifiedPush lets &lt;strong&gt;users choose their notification provider&lt;/strong&gt;. This was a paradigm shift I hadn't considered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Foundation: WebPush and VAPID
&lt;/h2&gt;

&lt;p&gt;To truly grasp UnifiedPush, I needed to understand how notifications actually work. This led me to discover the open standards that power web notifications:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://tools.ietf.org/html/rfc8030" rel="noopener noreferrer"&gt;WebPush Protocol&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is a &lt;strong&gt;W3C standard&lt;/strong&gt; that defines how push notifications work on the web. It's the foundation that browsers use for notifications.&lt;br&gt;
WebPush is defined by 3 standards: for the transport (RFC8030), for the authorization (VAPID, RFC8292), for the encryption (RFC8291)&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;a href="https://datatracker.ietf.org/doc/html/rfc8292" rel="noopener noreferrer"&gt;VAPID (Voluntary Application Server Identification)&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Public key&lt;/strong&gt;: Identifies your app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private key&lt;/strong&gt;: Signs your messages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's beautiful about this approach is that it's &lt;strong&gt;service-agnostic&lt;/strong&gt;. The same VAPID keys and WebPush messages work whether the user chooses Google's servers, a self-hosted solution, or anything in between.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy by Design&lt;/strong&gt;: Here's a crucial security feature that sets webpush apart—&lt;strong&gt;encryption&lt;/strong&gt;. When your server sends a notification, the message is encrypted using the user webpush keys. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Only your app can decrypt the notification content&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Distributors (ntfy, NextPush, etc.) cannot read your messages&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Even if using FCM as a distributor, Google cannot see your data&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;True privacy regardless of which distributor the user chooses&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is fundamentally different from traditional FCM, where Google's servers can potentially access all notification content. With Webpush  encryption, the distributor is just a secure messenger—they can deliver your encrypted package, but they can't open it.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Mobile Connection
&lt;/h3&gt;

&lt;p&gt;Here's the key insight: &lt;strong&gt;mobile devices can receive WebPush notifications too&lt;/strong&gt;. The same standards that power web notifications work on mobile platforms.&lt;/p&gt;
&lt;h2&gt;
  
  
  How UnifiedPush Works
&lt;/h2&gt;

&lt;p&gt;UnifiedPush elegantly bridges the gap between open standards and mobile notifications:&lt;/p&gt;
&lt;h3&gt;
  
  
  The Flow
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  What Are Distributors?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Distributors&lt;/strong&gt; (or Notification Providers) are apps that run in the background and handle notification delivery. Users can choose from various options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy" rel="noopener noreferrer"&gt;&lt;strong&gt;ntfy&lt;/strong&gt;&lt;/a&gt;: Self-hosted, maximum privacy &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://f-droid.org/en/packages/org.unifiedpush.distributor.sunup/" rel="noopener noreferrer"&gt;&lt;strong&gt;Sunup&lt;/strong&gt;&lt;/a&gt;: Uses Mozilla's Push  Servers&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://play.google.com/store/apps/details?id=org.unifiedpush.distributor.fcm" rel="noopener noreferrer"&gt;&lt;strong&gt;gCompat-UP&lt;/strong&gt;&lt;/a&gt;: Uses Google's infrastructure as a fallback&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom solutions&lt;/strong&gt;: Roll your own&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fus-east-1.tixte.net%2Fuploads%2Fdilutewater.is-from.space%2FScreencast_20250711_202611.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fus-east-1.tixte.net%2Fuploads%2Fdilutewater.is-from.space%2FScreencast_20250711_202611.gif" alt="UnifiedPush Flow" width="582" height="564"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Elegant Solution: Embedded Distributors
&lt;/h2&gt;

&lt;p&gt;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"&lt;/p&gt;

&lt;p&gt;Here's where UnifiedPush gets really clever: &lt;a href="https://unifiedpush.org/news/20250131_push_for_decentralized/#webpush-to-google-services" rel="noopener noreferrer"&gt;&lt;strong&gt;embedded distributor modules&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;UnifiedPush provides an embedded distributor that your app can use internally. When using this embedded module:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your app registers for notifications directly with FCM endpoints&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No Firebase project or configuration required&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No Firebase libraries needed&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;FCM natively supports WebPush and VAPID standards&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means you can send notifications to your app using direct FCM endpoints without any Firebase setup—just pure WebPush with VAPID authentication.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Best of Both Worlds
&lt;/h3&gt;

&lt;p&gt;My implementation strategy became clear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero UX friction&lt;/strong&gt; for mainstream users&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full choice and privacy&lt;/strong&gt; for power users&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;F-Droid compatibility&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Implementation Reality
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Server-Side Changes
&lt;/h3&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate VAPID key pairs&lt;/li&gt;
&lt;li&gt;Use WebPush protocol for sending notifications&lt;/li&gt;
&lt;li&gt;Handle subscription management&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Mobile App Integration
&lt;/h3&gt;

&lt;p&gt;On the React Native side, replacing FCM with UnifiedPush was not exactly smooth for me. The &lt;a href="https://github.com/juandjara/expo-unified-push" rel="noopener noreferrer"&gt;&lt;code&gt;expo-unified-push&lt;/code&gt;&lt;/a&gt; library provided a cleaner API than Firebase's implementation, with better debugging capabilities and more predictable behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Debugging Nightmare (And Its Embarrassingly Simple Solution)
&lt;/h3&gt;

&lt;p&gt;However, I hit a frustrating wall.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Desperate Debugging Journey&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spent countless hours debugging the UnifiedPush library source code&lt;/li&gt;
&lt;li&gt;Tried different distributors, thinking it was distributor-specific&lt;/li&gt;
&lt;li&gt;Even &lt;strong&gt;forked the &lt;code&gt;expo-unified-push&lt;/code&gt; repository&lt;/strong&gt; and made custom modifications&lt;/li&gt;
&lt;li&gt;Used my own version of the library as the npm package instead&lt;/li&gt;
&lt;li&gt;Tested various permission configurations and background processing settings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="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" class="article-body-image-wrapper"&gt;&lt;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" width="800" height="402"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Me debugging for hours&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The False Victory&lt;/strong&gt;: 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Humbling Reality&lt;/strong&gt;: 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The actual issue&lt;/strong&gt;: The notification &lt;code&gt;id&lt;/code&gt; field format.&lt;/p&gt;

&lt;p&gt;I had been either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Omitting the &lt;code&gt;id&lt;/code&gt; field entirely, or
&lt;/li&gt;
&lt;li&gt;Using hexadecimal IDs (like MongoDB ObjectIds or UUIDs)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The solution&lt;/strong&gt;: UnifiedPush library requires notification IDs to be &lt;strong&gt;numeric only&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="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" class="article-body-image-wrapper"&gt;&lt;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" width="498" height="373"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Me realizing the bug was just using wrong ID format&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Lesson&lt;/strong&gt;: 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.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Community That Made All the Difference
&lt;/h3&gt;

&lt;p&gt;Throughout this debugging nightmare, I wasn't struggling alone. The &lt;strong&gt;UnifiedPush community on Matrix&lt;/strong&gt; was incredibly supportive and patient with my questions.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The human side of open source&lt;/strong&gt;: 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Results: Better Than Expected
&lt;/h2&gt;

&lt;h3&gt;
  
  
  User Experience Wins
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mainstream users&lt;/strong&gt;: Zero change in experience—notifications "just work"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy-conscious users&lt;/strong&gt;: Full control over notification routing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Degoogled device users&lt;/strong&gt;: Finally have access to full app functionality&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The iOS Reality: Apple's Walled Garden
&lt;/h2&gt;

&lt;p&gt;Now, let's address the elephant in the room: &lt;strong&gt;iOS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;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).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Current iOS Situation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All iOS notifications must go through Apple's APNs servers&lt;/li&gt;
&lt;li&gt;No alternative notification distributors allowed&lt;/li&gt;
&lt;li&gt;Users cannot choose their notification provider&lt;/li&gt;
&lt;li&gt;Apps distributed outside the App Store (sideloaded) still require APNs for notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;I will soon be releasing my app on F-Droid (Hopefully)&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://element.io/" rel="noopener noreferrer"&gt;Element&lt;/a&gt;, &lt;a href="https://tusky.app/" rel="noopener noreferrer"&gt;Tusky&lt;/a&gt;, and &lt;a href="https://fluffychat.im/" rel="noopener noreferrer"&gt;FluffyChat&lt;/a&gt; all adopting this approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Fellow Developers
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The future of mobile notifications doesn't have to be controlled by Big Tech. We can build something better—something that puts users first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://unifiedpush.org/news/20250131_push_for_decentralized/" rel="noopener noreferrer"&gt;https://unifiedpush.org/news/20250131_push_for_decentralized/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://unifiedpush.org/" rel="noopener noreferrer"&gt;https://unifiedpush.org/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developer.chrome.com/blog/web-push-interop-wins" rel="noopener noreferrer"&gt;https://developer.chrome.com/blog/web-push-interop-wins&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Want to follow my journey building privacy-first mobile apps? Connect with me or check out my other projects!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>mobile</category>
      <category>android</category>
    </item>
    <item>
      <title>Vibe Coding an entire game, Maze Trials</title>
      <dc:creator>Rachit Khurana</dc:creator>
      <pubDate>Sun, 11 May 2025 19:11:17 +0000</pubDate>
      <link>https://forem.com/dilutewater/vibe-coding-an-entire-game-maze-trials-42h1</link>
      <guid>https://forem.com/dilutewater/vibe-coding-an-entire-game-maze-trials-42h1</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/aws-amazon-q-v2025-04-30"&gt;Amazon Q Developer "Quack The Code" Challenge&lt;/a&gt;: That's Entertainment!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built a 3D Maze Game inspired by the Maze Runner series using web technologies. The game puts players in a mysterious research facility where they must navigate through a maze while battling an infection and avoiding dangerous creatures called "Grievers."&lt;/p&gt;

&lt;h3&gt;
  
  
  Game Features:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Immersive 3D Environment&lt;/strong&gt;: A fully navigable maze with dynamic walls that shift in darkness&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compelling Storyline&lt;/strong&gt;: Players uncover the mystery behind the maze and their own identity through collectible story notes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Survival Elements&lt;/strong&gt;: Players must manage their infection level, health, and stamina while searching for serum vials&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Day/Night Cycle&lt;/strong&gt;: The environment changes as time passes, with increased danger at night&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enemy&lt;/strong&gt;: Grievers hunt the player, especially in darkness&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cinematic Sequences&lt;/strong&gt;: Story-driven cutscenes that reveal the narrative&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atmospheric Sound Design&lt;/strong&gt;: Dynamic audio that enhances the tense atmosphere&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Technical Highlights:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Built with Three.js for 3D rendering&lt;/li&gt;
&lt;li&gt;Custom collision detection system&lt;/li&gt;
&lt;li&gt;Dynamic lighting and environmental effects&lt;/li&gt;
&lt;li&gt;Procedurally generated maze layout&lt;/li&gt;
&lt;li&gt;Optimized performance for smooth gameplay&lt;/li&gt;
&lt;li&gt;Responsive UI with health, stamina, and infection indicators&lt;/li&gt;
&lt;li&gt;Integrated sound system with spatial audio&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;You can try out the game at &lt;a href="https://mazetrials.rachitkhurana.tech/" rel="noopener noreferrer"&gt;mazetrials.rachitkhurana.tech&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/W-c9bBz0O40"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Repository
&lt;/h2&gt;

&lt;p&gt;The full source code is available on GitHub: &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/notnotrachit" rel="noopener noreferrer"&gt;
        notnotrachit
      &lt;/a&gt; / &lt;a href="https://github.com/notnotrachit/mazekiller" rel="noopener noreferrer"&gt;
        mazekiller
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How I Used Amazon Q Developer
&lt;/h2&gt;

&lt;p&gt;I used Amazon Q both as a CLI as well as a VSCode Extension. &lt;br&gt;
Amazon Q Developer was instrumental in creating this project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Game Architecture Design&lt;/strong&gt;: I used Amazon Q to help design the overall architecture of the game, including the component structure and how different systems would interact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Three.js Implementation&lt;/strong&gt;: Amazon Q provided guidance on implementing Three.js features like lighting, camera controls, and collision detection. It helped me optimize the rendering pipeline for better performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging Complex Issues&lt;/strong&gt;: When I encountered issues with the player movement and collision detection, Amazon Q helped identify the root causes and suggested fixes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sound Management System&lt;/strong&gt;: Amazon Q helped me design and implement the sound system that handles ambient sounds, music, and spatial audio effects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Story Implementation&lt;/strong&gt;: Amazon Q assisted in creating the cinematic sequence system and how to integrate the narrative elements into the gameplay.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Optimization&lt;/strong&gt;: When the game started experiencing frame rate drops, Amazon Q suggested several optimization techniques like frustum culling and staggered updates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI Development&lt;/strong&gt;: Amazon Q provided guidance on creating responsive UI elements that update based on player status.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most valuable aspect of using Amazon Q was how it helped me understand complex game development concepts and implement them efficiently. It suggested best practices for game architecture that made the code more maintainable and performant. When I got stuck on technical challenges, Amazon Q provided clear explanations and sample code that helped me overcome obstacles quickly.&lt;/p&gt;

&lt;p&gt;For example, when implementing the dynamic wall movement system, Amazon Q suggested a pattern for updating the collision grid that I wouldn't have thought of on my own. This made the feature much more robust and eliminated several bugs I was experiencing.&lt;/p&gt;

&lt;p&gt;Overall, Amazon Q Developer acted as both a coding assistant and a mentor throughout the development process, significantly accelerating my progress and improving the quality of the final game.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>awschallenge</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a RAG with Supabase Vector &amp; OpenAI</title>
      <dc:creator>Rachit Khurana</dc:creator>
      <pubDate>Mon, 16 Sep 2024 12:04:49 +0000</pubDate>
      <link>https://forem.com/dilutewater/building-a-rag-with-supabase-vector-openai-2ag2</link>
      <guid>https://forem.com/dilutewater/building-a-rag-with-supabase-vector-openai-2ag2</guid>
      <description>&lt;p&gt;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 &lt;strong&gt;Retrieval-Augmented Generation (RAG)&lt;/strong&gt; 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 &lt;strong&gt;Supabase Vector&lt;/strong&gt; and &lt;strong&gt;Azure OpenAI&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is RAG??
&lt;/h2&gt;

&lt;p&gt;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. &lt;strong&gt;Retrieval-Augmented Generation (RAG)&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fgelwnztt3mp2ezgj07se.png" class="article-body-image-wrapper"&gt;&lt;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%2Fgelwnztt3mp2ezgj07se.png" alt="RAG" width="673" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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 &lt;strong&gt;semantic search&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s Build an Image-Based RAG
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Uploading and Storing the Image&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We begin by uploading an image and storing it in &lt;strong&gt;Supabase Storage&lt;/strong&gt;. Using the following code, we handle the image upload and return a publicly accessible URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;upload_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img_type&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BytesIO&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PNG&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;images&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getvalue&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content-type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;img_type&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;images&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get_public_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2. Generating an Image Description&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Here’s the code for generating that description:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_image_description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AZURE_OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a helpful assistant.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Generate a description for this image:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}}]}]}&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;choices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This provides a meaningful textual description of the image, which we use in the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Creating Embeddings&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With the description ready, we convert it into vector embeddings using Azure OpenAI. These embeddings are crucial for enabling search functionality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_embeddings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AZURE_OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text-embedding-3-small&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;embedding&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code transforms the image description into a vector embedding, making it searchable.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Saving the Embedding&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We store these embeddings in &lt;strong&gt;Supabase Vector&lt;/strong&gt;, allowing us to efficiently search through them later.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;vector&lt;/code&gt; extension.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_embedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_or_create_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;docs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dimension&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1536&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vectors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;})]&lt;/span&gt;
    &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The whole upload workflow will be like the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Ftxhnar1639eqqmps42e8.png" class="article-body-image-wrapper"&gt;&lt;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%2Ftxhnar1639eqqmps42e8.png" alt="Upload flow" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. Querying the Images&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query_images&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_embeddings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;docs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include_metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The vector search identifies the most similar image based on its embeddings, and the corresponding URL is returned.&lt;/p&gt;

&lt;p&gt;And the whole query workflow will be like the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2F2e0s2zhe5aaf1nyz10i3.png" class="article-body-image-wrapper"&gt;&lt;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%2F2e0s2zhe5aaf1nyz10i3.png" alt="Retrival flow" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Adding a Simple UI with Streamlit&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;You can find the whole code on my GitHub repository: &lt;a href="https://github.com/notnotrachit/Sample-Rag" rel="noopener noreferrer"&gt;https://github.com/notnotrachit/Sample-Rag&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By using &lt;strong&gt;Supabase Vector&lt;/strong&gt; and &lt;strong&gt;Azure OpenAI&lt;/strong&gt;, 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.&lt;/p&gt;

&lt;p&gt;Git Repo: &lt;a href="https://github.com/notnotrachit/Sample-Rag" rel="noopener noreferrer"&gt;https://github.com/notnotrachit/Sample-Rag&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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: &lt;a href="https://www.canva.com/design/DAGOzSBkY4U/9lxkf7dNpDSvY_0nZSqD8Q/view?utm_content=DAGOzSBkY4U&amp;amp;utm_campaign=designshare&amp;amp;utm_medium=link&amp;amp;utm_source=editor" rel="noopener noreferrer"&gt;Slides Link&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>supabase</category>
      <category>azure</category>
      <category>openai</category>
    </item>
    <item>
      <title>Deploy Django to Azure - The Easy Way</title>
      <dc:creator>Rachit Khurana</dc:creator>
      <pubDate>Thu, 11 Jul 2024 12:21:55 +0000</pubDate>
      <link>https://forem.com/dilutewater/deploy-django-to-azure-the-easy-way-2h1n</link>
      <guid>https://forem.com/dilutewater/deploy-django-to-azure-the-easy-way-2h1n</guid>
      <description>&lt;p&gt;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. &lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Azure account&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don’t have an azure account yet, no issues, you can signup for free and get 200USD credits for the first month &lt;a href="https://azure.microsoft.com/free/?wt.mc_id=studentamb_285271" rel="noopener noreferrer"&gt;here&lt;/a&gt; . &lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://azure.microsoft.com/free/students/?wt.mc_id=studentamb_285271" rel="noopener noreferrer"&gt;here&lt;/a&gt;. (Can be renewed annually as long as you are a student)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosted database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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 &lt;a href="http://neon.tech" rel="noopener noreferrer"&gt;neon.tech&lt;/a&gt; as well. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A django project ofcourse (😆)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this blog, I will be using my demo app, which is in this repository: &lt;a href="https://github.com/notnotrachit/django_todolist_demo_sample" rel="noopener noreferrer"&gt;https://github.com/notnotrachit/django_todolist_demo_sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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. &lt;br&gt;
You can refer to django’s docs for the same: &lt;a href="https://docs.djangoproject.com/en/5.0/ref/databases" rel="noopener noreferrer"&gt;https://docs.djangoproject.com/en/5.0/ref/databases&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are still facing issues, kindly let me know, I will make another blog regarding the same. &lt;/p&gt;

&lt;h2&gt;
  
  
  Lets Deploy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Make a GitHub repository
&lt;/h3&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;h3&gt;
  
  
  2) Head over to Azure Portal
&lt;/h3&gt;

&lt;p&gt;Go to the azure portal’s home page at:  &lt;a href="https://portal.azure.com/#home?wt.mc_id=studentamb_285271" rel="noopener noreferrer"&gt;https://portal.azure.com/#home&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fjbfa7vsx7xn7w0z6hdpt.png" class="article-body-image-wrapper"&gt;&lt;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%2Fjbfa7vsx7xn7w0z6hdpt.png" alt="Azure Portal Homescreen" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;h3&gt;
  
  
  3) Creating an App Service
&lt;/h3&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;To create a service, search for 'App Service' in the top search bar and click on it. &lt;/p&gt;

&lt;p&gt;&lt;a href="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%2F52gd0xvu5ety3slvz6ir.png" class="article-body-image-wrapper"&gt;&lt;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%2F52gd0xvu5ety3slvz6ir.png" alt="Azure search bar" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fam3rotexth6gydobq0kz.png" class="article-body-image-wrapper"&gt;&lt;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%2Fam3rotexth6gydobq0kz.png" alt="Azure app service" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might see an empty list. &lt;/p&gt;

&lt;p&gt;Now you need to click on &lt;code&gt;Create&lt;/code&gt; and then select &lt;code&gt;Web App&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;After that a long form type page will open up.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2F2ksdamg88mhvg7mrrc4d.png" class="article-body-image-wrapper"&gt;&lt;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%2F2ksdamg88mhvg7mrrc4d.png" alt="Create app service" width="800" height="1496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first field is for the subscription. It will most likely be prefilled. If not, select your subscription from the dropdown.&lt;/p&gt;

&lt;p&gt;Next is the resource group. You can leave it for now; it will be automatically created once we assign a name.&lt;/p&gt;

&lt;p&gt;Now, we need to set a name for our web app. This name needs to be globally unique. &lt;br&gt;
In publish option, leave code as selected. &lt;/p&gt;

&lt;p&gt;In the Runtime Stack, select Python 3.10 or higher&lt;br&gt;
Next you can select the region or leave it at the default as well. &lt;/p&gt;

&lt;p&gt;Next, you will see under Pricing plan that a new Linux plan has already been created for you. &lt;br&gt;
You can now select the pricing plan according to your needs. I am selecting Basic B1 for now. &lt;/p&gt;

&lt;p&gt;Your final page will look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2F5uemn4gyhxzt40xzo1ua.png" class="article-body-image-wrapper"&gt;&lt;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%2F5uemn4gyhxzt40xzo1ua.png" alt="Create app service final" width="781" height="1543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we need to go to the deployment tab. &lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fvpi93fxnrq7njcr43vnq.png" class="article-body-image-wrapper"&gt;&lt;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%2Fvpi93fxnrq7njcr43vnq.png" alt="Deployment" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you first need to enable Continuous deployment. &lt;br&gt;
After enabling that, you need to Authorize your GitHub account by logging into your account. &lt;/p&gt;

&lt;p&gt;Once you authorize that, you need to select the repository and branch.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fju42b42r0ipcrskulrze.png" class="article-body-image-wrapper"&gt;&lt;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%2Fju42b42r0ipcrskulrze.png" alt="Deployment tab final" width="800" height="989"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now click on &lt;code&gt;Review + create&lt;/code&gt; . &lt;br&gt;
You will be taken to the final page where you can review everything. &lt;br&gt;
Finally, you can click on &lt;code&gt;Create&lt;/code&gt; now. &lt;/p&gt;

&lt;p&gt;Now it will takes few minutes to deploy your application on the cloud. &lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fhgusyopxpvnofprifs88.png" class="article-body-image-wrapper"&gt;&lt;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%2Fhgusyopxpvnofprifs88.png" alt="Deployment in process" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the deployment has been done, you will see a page like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2F7uhw5i3vopnqo4bd4sgd.png" class="article-body-image-wrapper"&gt;&lt;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%2F7uhw5i3vopnqo4bd4sgd.png" alt="Deployment done" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now click on &lt;code&gt;Go to resource&lt;/code&gt; . &lt;br&gt;
It will take few seconds to load. After all data has been loaded, you will be able to see the domain. &lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fo3kk7uy4415cp6kbczzj.png" class="article-body-image-wrapper"&gt;&lt;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%2Fo3kk7uy4415cp6kbczzj.png" alt="Resource Page" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can try visiting it, but you will be greeted with an error. &lt;br&gt;
Don’t worry, we will solve that as well. &lt;/p&gt;

&lt;p&gt;The error is mainly because we haven’t really allowed our application to run on this domain. &lt;br&gt;
To allow that, we would need to add this domain in our settings file. &lt;/p&gt;

&lt;h3&gt;
  
  
  4) Making Required Changes
&lt;/h3&gt;

&lt;p&gt;We will now go to our editor and open the &lt;code&gt;settings.py&lt;/code&gt; file. &lt;br&gt;
Find &lt;code&gt;ALLOWED_HOSTS&lt;/code&gt; 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. &lt;br&gt;
Now, we need to add our domain in that list. &lt;/p&gt;

&lt;p&gt;Kinda like this: &lt;code&gt;ALLOWED_HOSTS = ["rachit-todo.azurewebsites.net"]&lt;/code&gt; &lt;br&gt;
But make sure you enter your webapp’s domain. &lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fx3bferxxot1khdm988mk.png" class="article-body-image-wrapper"&gt;&lt;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%2Fx3bferxxot1khdm988mk.png" alt="GitHub Actions" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations 🎉, You have succesfully deployed your Django Web App to Azure. 🎉&lt;/p&gt;

&lt;p&gt;Give yourself a pat on the back &lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fd6d3p4r1htbuhrplmd21.gif" class="article-body-image-wrapper"&gt;&lt;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%2Fd6d3p4r1htbuhrplmd21.gif" alt="https://i.imgur.com/brtcekW.gif" width="500" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope you find this blog helpful. &lt;br&gt;
Feel free to write any doubts in the comments. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>django</category>
      <category>cloud</category>
      <category>azure</category>
    </item>
    <item>
      <title>Top 5 Must-Have Tools for Linux Users</title>
      <dc:creator>Rachit Khurana</dc:creator>
      <pubDate>Tue, 02 Jul 2024 11:20:55 +0000</pubDate>
      <link>https://forem.com/dilutewater/top-5-must-have-tools-for-linux-users-1hge</link>
      <guid>https://forem.com/dilutewater/top-5-must-have-tools-for-linux-users-1hge</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  1) Zoxide (&lt;code&gt;z&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;So you might be wondering what exactly is zoxide ? According to the developer, its “A smarter cd command”.&lt;/p&gt;

&lt;p&gt;Lemme explain it with example, so for example you want to go to a project directory named &lt;code&gt;webapp1234&lt;/code&gt; , and its inside a GitHub directory in the Documents directory.&lt;/p&gt;

&lt;p&gt;So with cd, you either need to use the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;Documents/
&lt;span class="nb"&gt;cd &lt;/span&gt;Github/
&lt;span class="nb"&gt;cd &lt;/span&gt;webapp1234/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or you can use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;Documents/GitHub/webapp1234/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but with zoxide, you can do this with a simple simple command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;z webapp1234
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and you will be in the webapp directory.&lt;br&gt;&lt;br&gt;
Isn’t this cool?&lt;/p&gt;

&lt;p&gt;You can check it out at: &lt;a href="https://github.com/ajeetdsouza/zoxide" rel="noopener noreferrer"&gt;https://github.com/ajeetdsouza/zoxide&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Wakapi
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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: &lt;a href="https://github.com/muety/wakapi?tab=readme-ov-file#-client-setup" rel="noopener noreferrer"&gt;https://github.com/muety/wakapi?tab=readme-ov-file#-client-setup&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My dashboard of the last 6 months:&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fhxb1ot738hjfca7e2k1q.png" class="article-body-image-wrapper"&gt;&lt;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%2Fhxb1ot738hjfca7e2k1q.png" alt="Wakapi" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Ollama + OpenWebUI
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;So that’s where ollama comes in. Ollama basically allows you to run open source models directly on your laptop.&lt;/p&gt;

&lt;p&gt;Checkout ollama at: &lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;https://ollama.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have ollama installed, you can install any open source model from the ollama library. You can checkout the library at: &lt;a href="https://ollama.com/library" rel="noopener noreferrer"&gt;https://ollama.com/library&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would suggest you to download llama3 and phi3. These 2 are really capable models.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenWebUI
&lt;/h3&gt;

&lt;p&gt;OpenWebUI is basically a web interface for ollama. It’s interface is very familiar and similar to ChatGPT.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fh5ijx4wwlhpehwdw8tm3.gif" class="article-body-image-wrapper"&gt;&lt;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%2Fh5ijx4wwlhpehwdw8tm3.gif" alt="OpenWebUI" width="1920" height="1080"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  4) Fish Shell
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;itsFOSS also published an amazing article a while back on Fish Shell, you can check it out at:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://itsfoss.com/fish-shell-features/" rel="noopener noreferrer"&gt;https://itsfoss.com/fish-shell-features/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In short, fish shell has some really amazing features like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Syntax highlighting&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auto Suggestions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easier path navigation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Interactive history search&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and much more…&lt;/p&gt;

&lt;h2&gt;
  
  
  5) distrobox
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;You can check it out at: &lt;a href="https://github.com/89luca89/distrobox" rel="noopener noreferrer"&gt;https://github.com/89luca89/distrobox&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fgcn7h7fgjfuk9ahpguex.png" class="article-body-image-wrapper"&gt;&lt;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%2Fgcn7h7fgjfuk9ahpguex.png" alt="Distrobox" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, my main host OS is fedora, however, I have install multiple OS in containers using distrobox.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>productivity</category>
      <category>tools</category>
      <category>programming</category>
    </item>
    <item>
      <title>Let's Learn Django #6: Using Database &amp; Admin Panel</title>
      <dc:creator>Rachit Khurana</dc:creator>
      <pubDate>Sat, 22 Jul 2023 20:31:01 +0000</pubDate>
      <link>https://forem.com/dilutewater/lets-learn-django-6-using-database-admin-panel-2m8</link>
      <guid>https://forem.com/dilutewater/lets-learn-django-6-using-database-admin-panel-2m8</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction to Django databases&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Django supports many relational databases like SQLite, MySQL, Postgres etc.&lt;/p&gt;

&lt;p&gt;By default, Django uses SQLite, but feel free to use any according to your preference/use case.&lt;/p&gt;

&lt;p&gt;We will also be using SQLite in this blog.&lt;/p&gt;

&lt;p&gt;To know more about how to use different databases, check out the following Django documentation: &lt;a href="https://docs.djangoproject.com/en/4.2/ref/databases/" rel="noopener noreferrer"&gt;https://docs.djangoproject.com/en/4.2/ref/databases/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What are models?
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrations
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set Up DB
&lt;/h2&gt;

&lt;p&gt;By default, Django uses SQLite database, and hence we won’t change it for now. The first command that we need to run is :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Every time you change something in your model, you need to make the migrations again to make changes to the database tables.&lt;/p&gt;

&lt;p&gt;For that, we can run the following commands to make migrations and apply changes to the db structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py makemigrations
python manage.py migrate

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command &lt;code&gt;makemigrations&lt;/code&gt; will create a new migration file in the migrations directory for every model that has changed. The second command &lt;code&gt;migrate&lt;/code&gt; 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Django ORM
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Models
&lt;/h2&gt;

&lt;p&gt;In order to create models, we need to define a Python class that extends Django's &lt;code&gt;Model&lt;/code&gt; class. Each attribute of the class represents a field in the database table. Django provides a variety of fields like &lt;code&gt;CharField&lt;/code&gt;, &lt;code&gt;IntegerField&lt;/code&gt;, &lt;code&gt;DateField&lt;/code&gt;, &lt;code&gt;DateTimeField&lt;/code&gt;, etc. that we can use to define our model's fields. We can also define relationships between models using fields like &lt;code&gt;ForeignKey&lt;/code&gt;, &lt;code&gt;ManyToManyField&lt;/code&gt;, and &lt;code&gt;OneToOneField&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For eg. lets create a sample model for our &lt;code&gt;triviaquiz&lt;/code&gt; app in &lt;code&gt;/quiz/models.py&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TriviaQuestion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;question_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pub_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;date published&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;option1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;option2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;option3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;option4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;question_text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Now to use this, we need to add this model to our database.&lt;/p&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py makemigrations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new migration file , which includes the changes we made to the &lt;code&gt;TriviaQuestion&lt;/code&gt; model. Next, we apply the migration using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create the &lt;code&gt;triviaquestion&lt;/code&gt; table in the database. Now to easily edit the data, we will also add this model in the &lt;code&gt;admin.py&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;admin.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TriviaQuestion&lt;/span&gt;

&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TriviaQuestion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will display the question text and the date it was published in the admin interface for the TriviaQuestion model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Django Admin
&lt;/h2&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py createsuperuser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 &lt;a href="http://localhost:8000/admin" rel="noopener noreferrer"&gt;&lt;code&gt;localhost:8000/admin&lt;/code&gt;&lt;/a&gt; in our browser and logging in with the superuser credentials.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>django</category>
      <category>beginners</category>
      <category>python</category>
    </item>
    <item>
      <title>Let's Learn Django #5 Django Template</title>
      <dc:creator>Rachit Khurana</dc:creator>
      <pubDate>Wed, 21 Jun 2023 18:23:14 +0000</pubDate>
      <link>https://forem.com/dilutewater/lets-learn-django-5-django-template-53b0</link>
      <guid>https://forem.com/dilutewater/lets-learn-django-5-django-template-53b0</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Django templating is very powerful. It supports a large number of tags like if, for, cycle etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basics:
&lt;/h3&gt;

&lt;p&gt;We display the variables we passed using double curly brackets&lt;br&gt;&lt;br&gt;
Like this: &lt;code&gt;{{ variable_name }}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And we use Django template tags using a pair of curly brackets &amp;amp; percent sign.&lt;br&gt;&lt;br&gt;
Like this: &lt;code&gt;{% if age&amp;gt;18 %}Adult{% else %}Child{% endif %}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To use filters, we add a pipe symbol in front of the variable.&lt;br&gt;&lt;br&gt;
Like this: &lt;code&gt;{{ name|length }}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we will have a look at the common template tags in Django&lt;/p&gt;
&lt;h2&gt;
  
  
  Template Tags
&lt;/h2&gt;
&lt;h3&gt;
  
  
  if tag
&lt;/h3&gt;

&lt;p&gt;If tag is a pretty simple tag used to add a condition to the template content.&lt;br&gt;&lt;br&gt;
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.&lt;br&gt;&lt;br&gt;
Do note that we also need to add an endif tag when we are done with the condition.&lt;br&gt;&lt;br&gt;
For eg.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My name is &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;{{name}}&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        {% if name|length &lt;span class="err"&gt;&amp;lt;&lt;/span&gt; 5 %}
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My name is short&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        {% elif name|length &lt;span class="err"&gt;&amp;lt;&lt;/span&gt; 10 %}
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My name is long&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        {% else %}
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My name is very long&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        {% endif %}
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My age is &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;{{age}}&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  for Tag
&lt;/h3&gt;

&lt;p&gt;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.&lt;br&gt;&lt;br&gt;
For eg:&lt;/p&gt;

&lt;p&gt;For this, I passed a basic list from the views.py file like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rachit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;
    &lt;span class="n"&gt;Interests&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Coding&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Reading&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Gaming&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hello.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Interests&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Interests&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the template will contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;{% load static %}
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'style.css' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My name is &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;{{name}}&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My age is &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;{{age}}&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt; Interests: &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
            {% for interest in Interests %}
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;{{interest}}&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            {% endfor %}
        &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  extends and block tag
&lt;/h3&gt;

&lt;p&gt;These 2 tags are generally used together. If we want to create a base template &amp;amp; then put data or other HTML elements inside it using a different file, we use these tags.&lt;br&gt;&lt;br&gt;
First, we will add a block tag in the base file &amp;amp; then extend that base file to another file, &amp;amp; use the block tag to put more HTML elements in it.&lt;br&gt;&lt;br&gt;
For eg. I will create a new &lt;code&gt;base.html&lt;/code&gt; file with the following content making use of the block tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;{% load static %}
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'style.css' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Django Tutorial&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Hi there! This is a Django tutorial.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        {% block content %}
        {% endblock content %}
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will edit &lt;code&gt;hello.html&lt;/code&gt; to extend this &amp;amp; place more content in the content block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;{% extends 'base.html' %}
{% block content %}
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt; Welcome to the home page!&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{% endblock %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows us to reuse templates &amp;amp; follow the DRY(Don't repeat yourself) principle.&lt;/p&gt;

&lt;h3&gt;
  
  
  include Tag
&lt;/h3&gt;

&lt;p&gt;Now what if we need to add a simple component to the current file without extending the base file in that component file?&lt;br&gt;&lt;br&gt;
That's where the include tag comes in.&lt;br&gt;&lt;br&gt;
Using it is pretty straightforward. Let's add a header component to our &lt;code&gt;base.html&lt;/code&gt; file&lt;br&gt;&lt;br&gt;
For that, we will create a new file with the header component. I am going to name it &lt;code&gt;header.html&lt;/code&gt; and add a simple marquee to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;marquee&amp;gt;&lt;/span&gt;
Welcome to this django tutorial !
&lt;span class="nt"&gt;&amp;lt;/marquee&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, to include it in &lt;code&gt;base.html&lt;/code&gt;, we will use the include tag like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;{% load static %}
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'style.css' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        {% include 'header.html' %}
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Django Tutorial&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Hi there! This is a Django tutorial.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        {% block content %}
        {% endblock content %}
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also helps us in following in DRY principle.&lt;br&gt;&lt;br&gt;
These were the main tags we will use while building any web apps. Apart from this, there are a lot more template tags &amp;amp; filters in Django. To know more about them, I suggest reading the following Django docs: &lt;a href="https://docs.djangoproject.com/en/4.2/ref/templates/builtins/" rel="noopener noreferrer"&gt;https://docs.djangoproject.com/en/4.2/ref/templates/builtins/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Let's Learn Django #4 Using templates &amp; static files</title>
      <dc:creator>Rachit Khurana</dc:creator>
      <pubDate>Sat, 17 Jun 2023 10:51:09 +0000</pubDate>
      <link>https://forem.com/dilutewater/lets-learn-django-4-using-templates-static-files-15c9</link>
      <guid>https://forem.com/dilutewater/lets-learn-django-4-using-templates-static-files-15c9</guid>
      <description>&lt;p&gt;We have already seen how to write our first view in the previous blogs. In this blog, we will explore how to use &amp;amp; render templates.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are templates?
&lt;/h3&gt;

&lt;p&gt;Templates are simply HTML files that we can render as a response to a URL/view.&lt;br&gt;&lt;br&gt;
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.&lt;br&gt;&lt;br&gt;
We will explore it in detail in the next blog&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting up templates folder
&lt;/h3&gt;

&lt;p&gt;Setting up a templates folder is quite easy. First, we will create a new folder in the base directory with the name &lt;code&gt;templates&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Next, we need to tell Django that we will be using this folder for placing all our templates.&lt;/p&gt;

&lt;p&gt;For that, we all navigate to our settings.py file. There is a list named &lt;code&gt;TEMPLATES&lt;/code&gt; &amp;amp; it will have a JSON object with a field named &lt;code&gt;DIRS&lt;/code&gt; that contain an empty list. We just need to add &lt;code&gt;templates&lt;/code&gt; (the name of our folder) to it.&lt;br&gt;&lt;br&gt;
Finally, it should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;TEMPLATES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;BACKEND&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.template.backends.django.DjangoTemplates&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DIRS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;templates&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;APP_DIRS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OPTIONS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;context_processors&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.template.context_processors.debug&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.template.context_processors.request&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth.context_processors.auth&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages.context_processors.messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is all we need to do to set up templates.&lt;br&gt;&lt;br&gt;
Now we will see how to use templates.&lt;/p&gt;
&lt;h3&gt;
  
  
  Rendering templates
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;br&gt;&lt;br&gt;
First, we will create a new HTML file in the templates directory with the name &lt;code&gt;hello.html&lt;/code&gt;&lt;br&gt;&lt;br&gt;
You can then add any HTML page design you want.&lt;br&gt;&lt;br&gt;
I will go with a simple one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My name is &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;Rachit Khurana&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will return this template when the user goes to the index page.&lt;br&gt;&lt;br&gt;
For that, we will navigate to &lt;code&gt;views.py&lt;/code&gt; where we defined a hello function that gets called when the user goes to the index page.&lt;br&gt;&lt;br&gt;
We will then use &lt;code&gt;render&lt;/code&gt; function from &lt;code&gt;django.shortcuts&lt;/code&gt; to render this template.&lt;br&gt;&lt;br&gt;
The &lt;code&gt;render&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;views.py&lt;/code&gt; code will look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.shortcuts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;

&lt;span class="c1"&gt;# Create your views here.
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hello.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we run the server &amp;amp; go to &lt;a href="http://127.0.0.1:8000/" rel="noopener noreferrer"&gt;http://127.0.0.1:8000/&lt;/a&gt;, we will be able to see this as an HTML-rendered page. Awesome right?  &lt;/p&gt;

&lt;p&gt;However, do note that you won't be able to create CSS or JS files in the templates folder &amp;amp; use those in the HTML file.&lt;br&gt;&lt;br&gt;
This is because Django only takes the HTML file, &amp;amp; returns the rendered file directly. It doesn't take the CSS &amp;amp; JS files. To use separate CSS &amp;amp; JS files, we need to serve them as static files.&lt;br&gt;&lt;br&gt;
We will now see how to serve static files.&lt;/p&gt;
&lt;h2&gt;
  
  
  Static Files
&lt;/h2&gt;

&lt;p&gt;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.  &lt;/p&gt;

&lt;p&gt;To set up static files, we will create a new folder named &lt;code&gt;static&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Now we need to tell Django to use this folder for serving static files. For that, we will add the following line to the &lt;code&gt;settings.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;STATICFILES_DIRS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;BASE_DIR&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;static&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;STATICFILES_DIRS&lt;/code&gt; is a list where you specify the directory paths where Django should look for static files.&lt;/p&gt;

&lt;p&gt;That's it. Now whatever file we store in the static folder will be available at &lt;a href="http://127.0.0.1:8000/static/&amp;lt;filename" rel="noopener noreferrer"&gt;http://127.0.0.1:8000/static/&amp;amp;lt;filename&lt;/a&gt;&amp;gt;.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Using static files inside templates
&lt;/h3&gt;

&lt;p&gt;Now, let's create a simple CSS file with the name &lt;code&gt;style.css&lt;/code&gt;. I will be using a pretty simple CSS file for demonstration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ca1c1c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;aqua&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will use this in our &lt;code&gt;hello.html&lt;/code&gt; file by making use of the static tag. First, we will import it &amp;amp; then use it as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;{% load static %}
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'style.css' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My name is &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;Rachit Khurana&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when we run the server &amp;amp; go to &lt;a href="http://127.0.0.1:8000/" rel="noopener noreferrer"&gt;http://127.0.0.1:8000/&lt;/a&gt; we will see the new HTML page with the CSS.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fic6jwu44o7ekl9b8v3am.png" class="article-body-image-wrapper"&gt;&lt;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%2Fic6jwu44o7ekl9b8v3am.png" alt="homepage" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations, you know know how to render an HTML template &amp;amp; use static files. But what if we need to pass an argument from the code to the template?&lt;br&gt;&lt;br&gt;
We can also do that easily. Let's take a look at how to do that.&lt;/p&gt;
&lt;h3&gt;
  
  
  Passing arguments to the template
&lt;/h3&gt;

&lt;p&gt;We can easily pass variables to the template to render.&lt;br&gt;&lt;br&gt;
For eg, I want to pass my name &amp;amp; age to the template. We will go to the &lt;code&gt;views.py&lt;/code&gt; file &amp;amp; declare these variables in the function.&lt;br&gt;&lt;br&gt;
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.&lt;br&gt;&lt;br&gt;
The final code will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.shortcuts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;

&lt;span class="c1"&gt;# Create your views here.
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rachit Khurana&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hello.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can use these variables in the template &lt;code&gt;hello.html&lt;/code&gt; by wrapping them with double curly brackets like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;{% load static %}
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'style.css' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My name is &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;{{name}}&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My age is &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;{{age}}&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;{{name}}&lt;/code&gt; will get replaced by the value of &lt;code&gt;name&lt;/code&gt; we have passed to the template. Now if we try to run the server &amp;amp; go to &lt;a href="http://127.0.0.1:8000/" rel="noopener noreferrer"&gt;http://127.0.0.1:8000/&lt;/a&gt; we can see the new rendered HTML page with those variables.&lt;/p&gt;

&lt;p&gt;Like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fc0ggpdbt8n0kolmqg11b.png" class="article-body-image-wrapper"&gt;&lt;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%2Fc0ggpdbt8n0kolmqg11b.png" alt="homepage" width="652" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can not only pass string or int values, but we can also pass lists, tuples, dictionaries etc.  &lt;/p&gt;

&lt;p&gt;Congratulations, you now know how to render templates, serve static files &amp;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.&lt;/p&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Let's Learn Django #3 Writing our first view</title>
      <dc:creator>Rachit Khurana</dc:creator>
      <pubDate>Thu, 15 Jun 2023 12:30:25 +0000</pubDate>
      <link>https://forem.com/dilutewater/lets-learn-django-3-writing-our-first-view-ldl</link>
      <guid>https://forem.com/dilutewater/lets-learn-django-3-writing-our-first-view-ldl</guid>
      <description>&lt;p&gt;By now, we have seen how to initialise our project and the overview of different files in a Django project.&lt;br&gt;&lt;br&gt;
Now, we will write out the first view/page.  &lt;/p&gt;
&lt;h3&gt;
  
  
  Creating the First View - Hello World!
&lt;/h3&gt;

&lt;p&gt;Let's start by creating a simple view that will return a simple Hello World text.&lt;/p&gt;

&lt;p&gt;For that, we first need to tell Django to include our app (the app that we created before using the &lt;code&gt;django-admin startapp command&lt;/code&gt;) in the project.&lt;br&gt;&lt;br&gt;
We will open the &lt;code&gt;settings.py&lt;/code&gt; file. There would be a list named &lt;code&gt;INSTALLED_APPS&lt;/code&gt; . We just need to add our app name to that file. This allows Django to recognize and include your app in the project.&lt;br&gt;&lt;br&gt;
Somewhat like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.admin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sessions&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.staticfiles&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quiz&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;quiz&lt;/code&gt; is the name of the app I created before.&lt;/p&gt;

&lt;p&gt;Now, we will create a function that will take the request as a parameter &amp;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.&lt;br&gt;&lt;br&gt;
We will create this function in &lt;code&gt;quiz/views.py&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Since we want to return plain text in the HTTP response, we will import it here.&lt;br&gt;&lt;br&gt;
HttpResponse is used to return plain text in the HTTP response. &lt;code&gt;django.shortcuts&lt;/code&gt; already provide us with many methods through which we can return data.&lt;/p&gt;

&lt;p&gt;The file will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.shortcuts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;

&lt;span class="c1"&gt;# Create your views here.
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello World!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now to map this function to the home URL, we will edit the &lt;code&gt;urls.py&lt;/code&gt; file.&lt;br&gt;&lt;br&gt;
&lt;code&gt;urls.py&lt;/code&gt; file already contains a list by the name of &lt;code&gt;urlpatterns&lt;/code&gt;. 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 &lt;code&gt;quiz.views&lt;/code&gt; here.&lt;/p&gt;

&lt;p&gt;Our views.py file should look something like this now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;quiz.views&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;admin/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quiz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;name&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;Awesome, we have made our first view. Now to test it, we will run it using the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py runserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start the Django server &amp;amp; will serve it to the local host.&lt;/p&gt;

&lt;p&gt;And now, when we go to &lt;a href="http://127.0.0.1:8000/" rel="noopener noreferrer"&gt;http://127.0.0.1:8000/&lt;/a&gt; we will see Hello World! on that page 🎉&lt;/p&gt;

&lt;p&gt;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!&lt;/p&gt;

&lt;p&gt;In the next blog, we will explore more about how to use templates. &lt;/p&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Let's Learn Django #2 File Structure</title>
      <dc:creator>Rachit Khurana</dc:creator>
      <pubDate>Wed, 14 Jun 2023 18:39:02 +0000</pubDate>
      <link>https://forem.com/dilutewater/lets-learn-django-2-file-structure-2hcg</link>
      <guid>https://forem.com/dilutewater/lets-learn-django-2-file-structure-2hcg</guid>
      <description>&lt;p&gt;After initialising a Django project, we can see several files. Don't worry, this blog will explain all of them in detail.&lt;/p&gt;

&lt;p&gt;The general file structure of Django looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;├── [appname]&lt;/span&gt;
&lt;span class="s"&gt;│   ├── admin.py&lt;/span&gt;
&lt;span class="s"&gt;│   ├── apps.py&lt;/span&gt;
&lt;span class="s"&gt;│   ├── __init__.py&lt;/span&gt;
&lt;span class="s"&gt;│   ├── migrations&lt;/span&gt;
&lt;span class="s"&gt;│   │   └── __init__.py&lt;/span&gt;
&lt;span class="s"&gt;│   ├── models.py&lt;/span&gt;
&lt;span class="s"&gt;│   └── views.py&lt;/span&gt;
&lt;span class="s"&gt;├── [projectname]&lt;/span&gt;
&lt;span class="s"&gt;│   ├── __init__.py&lt;/span&gt;
&lt;span class="s"&gt;│   ├── asgi.py&lt;/span&gt;
&lt;span class="s"&gt;│   ├── settings.py&lt;/span&gt;
&lt;span class="s"&gt;│   ├── urls.py&lt;/span&gt;
&lt;span class="s"&gt;│   └── wsgi.py&lt;/span&gt;
&lt;span class="s"&gt;└── manage.py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here [appname] represents the name of the app you have created &amp;amp; [projectname] represents your project name.&lt;/p&gt;

&lt;p&gt;Now, let's go over each file one by one.&lt;/p&gt;

&lt;h3&gt;
  
  
  manage.py
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  settings.py
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  urls.py
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  asgi.py &amp;amp; wsgi.py
&lt;/h3&gt;

&lt;p&gt;ASGI stands for Asynchronous Server Gateway Interface &amp;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  views.py
&lt;/h3&gt;

&lt;p&gt;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;amp; class-based views. They are used to define what needs to be done &amp;amp; what needs to be returned when a specific URL is called.&lt;br&gt;&lt;br&gt;
We can return a JSON response, A HTTP response, a rendered template or anything we want.&lt;/p&gt;

&lt;h3&gt;
  
  
  models.py
&lt;/h3&gt;

&lt;p&gt;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;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  app.py
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  admin.py
&lt;/h3&gt;

&lt;p&gt;This file is used to register our app &amp;amp; models in the admin panel. So that we can easily edit data in the admin panel. We can also customise the looks &amp;amp; behaviour of the app so that it looks &amp;amp; behaves as we want in the admin panel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrations folder
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;With this, we have covered the basics of most of the important Django files that we would need while building a web app.&lt;br&gt;&lt;br&gt;
In the next blog, we will cover how to make url routes &amp;amp; views for them in the urls.py &amp;amp; views.py files respectively.&lt;/p&gt;

&lt;p&gt;I hope this blog series is helping you learn Django.&lt;/p&gt;

&lt;p&gt;Follow my journey on Twitter: &lt;a href="https://twitter.com/notnotrachit" rel="noopener noreferrer"&gt;@notnotrachit&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>python</category>
      <category>django</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
