<?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: Documendous</title>
    <description>The latest articles on Forem by Documendous (@documendous).</description>
    <link>https://forem.com/documendous</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%2F1428645%2Fe53ecdaa-57e5-47ca-828e-eeb8a788da05.png</url>
      <title>Forem: Documendous</title>
      <link>https://forem.com/documendous</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/documendous"/>
    <language>en</language>
    <item>
      <title>Django, React, and Docker Walk Into a Bar — Only Nginx Gets Served</title>
      <dc:creator>Documendous</dc:creator>
      <pubDate>Thu, 29 May 2025 12:02:21 +0000</pubDate>
      <link>https://forem.com/documendous/django-react-and-docker-walk-into-a-bar-only-nginx-gets-served-pcf</link>
      <guid>https://forem.com/documendous/django-react-and-docker-walk-into-a-bar-only-nginx-gets-served-pcf</guid>
      <description>&lt;p&gt;&lt;strong&gt;Subtitle: Or, how I lost my patience debugging staticfiles in production and came out stronger for it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So you want Django REST Framework in the back, React in the front, and everything neatly dockerized like a perfect startup pitch deck. Great. But once you drop Gunicorn, Nginx, and Vite into the pot, what you get is less a gourmet app stack and more a soup of HTTP 400s, 403s, and 404s.&lt;/p&gt;

&lt;p&gt;I recently went through the joyless gauntlet of getting Django admin to load properly behind a React/Nginx frontend in Docker. Here’s what worked — and all the dumb mistakes I made along the way so you don’t have to.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 The Setup (a.k.a. “This Should Just Work, Right?”)
&lt;/h2&gt;

&lt;p&gt;Here's what I started with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Django&lt;/code&gt; backend with Django REST Framework and &lt;code&gt;gunicorn&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;React&lt;/code&gt; frontend built with Vite&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Docker Compose&lt;/code&gt; for everything&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Nginx&lt;/code&gt; acting as the single entry point in production&lt;/li&gt;
&lt;li&gt;Static and media volumes shared between Django and Nginx&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My Docker Compose looked 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="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./magsite_backend&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile.prod&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gunicorn magsite_backend.wsgi:application --bind 0.0.0.0:8000&lt;/span&gt;
    &lt;span class="na"&gt;expose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;8000&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;static_volume:/home/magsite_backend/web/staticfiles&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;media_volume:/home/magsite_backend/web/mediafiles&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env.prod&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;

  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:16&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;prod_postgres_data:/var/lib/postgresql/data/&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env.prod.db&lt;/span&gt;

  &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./magsite-ui&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile.prod&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;80:80&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;web&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;static_volume:/home/magsite_backend/web/staticfiles&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;media_volume:/home/magsite_backend/web/mediafiles&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;static_volume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;media_volume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;prod_postgres_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🪵 Step 1: Static Files Are Real, But Nobody Believes in Them
&lt;/h2&gt;

&lt;p&gt;Everything built. Containers were up. Admin page loaded.&lt;/p&gt;

&lt;p&gt;But CSS? Not so much. The page looked like early 2000s Craigslist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Diagnosis:&lt;/strong&gt; Django’s &lt;code&gt;collectstatic&lt;/code&gt; was dumping files into &lt;code&gt;STATIC_ROOT&lt;/code&gt;, but Nginx wasn’t serving them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The screw-up:&lt;/strong&gt; I had set:&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;staticfiles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;STATIC_ROOT&lt;/span&gt; &lt;span class="o"&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;staticfiles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Classic rookie move. Django won’t let you collect static files into the same place it reads them from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Nuke &lt;code&gt;STATICFILES_DIRS&lt;/code&gt; entirely unless you actually have extra static folders outside your apps. Then:&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;STATIC_ROOT&lt;/span&gt; &lt;span class="o"&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;staticfiles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🚧 Step 2: Nginx Serves Nothing
&lt;/h2&gt;

&lt;p&gt;My Nginx config had this gem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/static/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://web:8000/static/&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 works great in dev. In production? Gunicorn doesn’t serve static files. It’s a web server, not your butler.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Replace that with a direct file alias:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/static/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;/home/magsite_backend/web/staticfiles/&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;And while you're at it, do the same for &lt;code&gt;/media/&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔐 Step 3: Hello Darkness My Old Friend (403 CSRF Errors)
&lt;/h2&gt;

&lt;p&gt;So now the admin &lt;strong&gt;loads&lt;/strong&gt; and I try logging in — only to be met by Django’s infamous CSRF slap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The issue:&lt;/strong&gt; Nginx wasn't forwarding all the headers Django expects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Update &lt;code&gt;/admin/&lt;/code&gt; and &lt;code&gt;/api/&lt;/code&gt; proxy blocks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bonus fix:&lt;/strong&gt; In &lt;code&gt;settings.py&lt;/code&gt;, trust your reverse proxy:&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;CSRF_TRUSTED_ORIGINS&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;http://localhost&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;h2&gt;
  
  
  🧱 Step 4: Bad Request (400) — Django’s Favorite Passive Aggression
&lt;/h2&gt;

&lt;p&gt;Turns out even if your containers are hugging each other lovingly over an internal Docker network, Django still throws a tantrum if the &lt;code&gt;Host&lt;/code&gt; header doesn’t match what's in &lt;code&gt;ALLOWED_HOSTS&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt;&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;ALLOWED_HOSTS&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;localhost&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;127.0.0.1&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;Or, if you’re still debugging:&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;ALLOWED_HOSTS&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;*&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;Yes, it’s insecure. So is walking barefoot into prod. You’ll put shoes on later.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Recap: Make It Work Every Time
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Your key config checkpoints:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;code&gt;STATIC_ROOT&lt;/code&gt; is not in &lt;code&gt;STATICFILES_DIRS&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;collectstatic&lt;/code&gt; writes to a volume that Nginx can access&lt;/li&gt;
&lt;li&gt;✅ Nginx uses &lt;code&gt;alias&lt;/code&gt; for static/media, not &lt;code&gt;proxy_pass&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ Nginx forwards critical headers (&lt;code&gt;Host&lt;/code&gt;, &lt;code&gt;X-Forwarded-*&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;ALLOWED_HOSTS&lt;/code&gt; includes what’s actually hitting Django&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;CSRF_TRUSTED_ORIGINS&lt;/code&gt; includes your Nginx URL&lt;/li&gt;
&lt;li&gt;✅ Browser cache cleared (or just use Incognito)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Django and React can co-exist in Docker with Nginx, but they do so reluctantly. Like British roommates who share a flat but text each other from separate rooms.&lt;/p&gt;

&lt;p&gt;If you're going this route for your own project or your boss's next pie-in-the-sky full-stack SPA, expect to spend some time unraveling these little devops lies.&lt;/p&gt;

&lt;p&gt;You're welcome.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;#django&lt;/code&gt; &lt;code&gt;#react&lt;/code&gt; &lt;code&gt;#docker&lt;/code&gt; &lt;code&gt;#nginx&lt;/code&gt; &lt;code&gt;#webdev&lt;/code&gt; &lt;code&gt;#csrf&lt;/code&gt; &lt;code&gt;#fullstack&lt;/code&gt;&lt;/p&gt;




</description>
    </item>
    <item>
      <title>🔐 How to Use Email as the Username in Django (The Right Way)</title>
      <dc:creator>Documendous</dc:creator>
      <pubDate>Tue, 08 Apr 2025 11:25:32 +0000</pubDate>
      <link>https://forem.com/documendous/how-to-use-email-as-the-username-in-django-the-right-way-5g43</link>
      <guid>https://forem.com/documendous/how-to-use-email-as-the-username-in-django-the-right-way-5g43</guid>
      <description>&lt;p&gt;Using email instead of a username for login is more user-friendly and often preferred in modern applications. Django supports this, but it requires a custom user model. Here's how to set it up cleanly and correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Step 1: Create a Custom User Model
&lt;/h2&gt;

&lt;p&gt;In your &lt;code&gt;core/models.py&lt;/code&gt; (or any appropriate app), define a user model using &lt;code&gt;AbstractBaseUser&lt;/code&gt; and &lt;code&gt;PermissionsMixin&lt;/code&gt;:&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.auth.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;AbstractBaseUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;BaseUserManager&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;PermissionsMixin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&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;UserManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseUserManager&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;create_user&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="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;extra_fields&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Email is required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;normalize_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;extra_fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;user&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_superuser&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="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;extra_fields&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;extra_fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;is_staff&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="n"&gt;extra_fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;is_superuser&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="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="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;extra_fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbstractBaseUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PermissionsMixin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;email&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;EmailField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique&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="n"&gt;full_name&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;150&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;phone_number&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;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blank&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="n"&gt;is_active&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;BooleanField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&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="n"&gt;is_staff&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;BooleanField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UserManager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;USERNAME_FIELD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;REQUIRED_FIELDS&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;full_name&lt;/span&gt;&lt;span class="sh"&gt;"&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;email&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ✅ Step 2: Point Django to Your New User Model
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;settings.py&lt;/code&gt;:&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;AUTH_USER_MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;core.AppUser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure this is set &lt;strong&gt;before&lt;/strong&gt; running any migrations.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Step 3: Create and Apply Migrations
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;This sets up your database using the email field as the login ID.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Step 4: Use &lt;code&gt;get_user_model()&lt;/code&gt; Everywhere
&lt;/h2&gt;

&lt;p&gt;Avoid importing &lt;code&gt;User&lt;/code&gt; directly. Use this in views, tests, and signals:&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.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_user_model&lt;/span&gt;

&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example usage in tests:&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;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;testpass&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;h2&gt;
  
  
  ✅ Step 5: Create Superuser with Email
&lt;/h2&gt;

&lt;p&gt;When creating a superuser via script or CLI, use:&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;span class="nt"&gt;--email&lt;/span&gt; admin@example.com &lt;span class="nt"&gt;--full_name&lt;/span&gt; &lt;span class="s2"&gt;"Admin"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you use &lt;code&gt;--noinput&lt;/code&gt;, pass in the &lt;code&gt;--email&lt;/code&gt; and &lt;code&gt;--full_name&lt;/code&gt; values explicitly in your script.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Done
&lt;/h2&gt;

&lt;p&gt;You now have a Django project where email is the unique identifier for login. This setup is clean, minimal, and aligns with real-world authentication flows.&lt;/p&gt;

</description>
      <category>django</category>
      <category>authentication</category>
      <category>modeling</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Fully Remove Docker Volumes (Even When They Persist)</title>
      <dc:creator>Documendous</dc:creator>
      <pubDate>Mon, 10 Mar 2025 13:53:50 +0000</pubDate>
      <link>https://forem.com/documendous/how-to-fully-remove-docker-volumes-even-when-they-persist-47j</link>
      <guid>https://forem.com/documendous/how-to-fully-remove-docker-volumes-even-when-they-persist-47j</guid>
      <description>&lt;p&gt;Docker makes it easy to manage containers, but cleaning up unused resources—especially volumes—can sometimes be tricky. If you've run &lt;code&gt;docker system prune --volumes -f&lt;/code&gt; but still see volumes when you run &lt;code&gt;docker volume ls&lt;/code&gt;, this guide will help you fully remove them.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Check for Running Containers
&lt;/h3&gt;

&lt;p&gt;Before removing volumes, ensure that no running or stopped containers are using them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If no containers are listed, proceed to the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Remove Stopped Containers
&lt;/h3&gt;

&lt;p&gt;Even stopped containers can hold onto volumes. Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps &lt;span class="nt"&gt;-aq&lt;/span&gt; | xargs &lt;span class="nt"&gt;-r&lt;/span&gt; docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there are no containers, this command does nothing because of the &lt;code&gt;-r&lt;/code&gt; flag in &lt;code&gt;xargs&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Remove Unused Volumes
&lt;/h3&gt;

&lt;p&gt;Now, try pruning all &lt;strong&gt;unused&lt;/strong&gt; volumes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume prune &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Force Remove All Volumes
&lt;/h3&gt;

&lt;p&gt;If some volumes still persist, force delete them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; | xargs &lt;span class="nt"&gt;-r&lt;/span&gt; docker volume &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Check for Docker Compose Dependencies
&lt;/h3&gt;

&lt;p&gt;If you're using Docker Compose, some volumes might still be referenced. Ensure all services are shut down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose down &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For older versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose down &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Verify Volumes Are Gone
&lt;/h3&gt;

&lt;p&gt;Finally, check if any volumes remain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;If volumes still persist after these steps, they may have been created using a different storage driver or defined outside of Docker’s normal management. In that case, you may need to manually remove them from the host system. Let me know if you run into any issues!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hybrid Compact Block Spacing: A Practical Coding Format for Readability and Refactoring</title>
      <dc:creator>Documendous</dc:creator>
      <pubDate>Wed, 05 Mar 2025 13:19:33 +0000</pubDate>
      <link>https://forem.com/documendous/hybrid-compact-block-spacing-a-practical-coding-format-for-readability-and-refactoring-51kp</link>
      <guid>https://forem.com/documendous/hybrid-compact-block-spacing-a-practical-coding-format-for-readability-and-refactoring-51kp</guid>
      <description>&lt;p&gt;Writing clean and maintainable code is an art. While many developers adhere to established style guides, some find that customizing their formatting can improve readability and even expose opportunities for refactoring. One such approach is what I call &lt;strong&gt;Hybrid Compact Block Spacing&lt;/strong&gt; (or you could call it Harlin's Compact Block Spacing -- Harlin is my first name :-D).&lt;/p&gt;

&lt;p&gt;This technique blends compact formatting for simple statements with block spacing for multi-line code, creating a structured and efficient layout that enhances both readability and maintainability.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Hybrid Compact Block Spacing?
&lt;/h2&gt;

&lt;p&gt;Hybrid Compact Block Spacing is a &lt;strong&gt;hybrid approach&lt;/strong&gt; to formatting code that balances &lt;strong&gt;compactness&lt;/strong&gt; and &lt;strong&gt;readability&lt;/strong&gt; by following these key principles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Single-line statements remain contiguous&lt;/strong&gt; – Simple, short statements are kept together without unnecessary line breaks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-line statements are spaced apart&lt;/strong&gt; – Complex or multi-line expressions are given their own section with whitespace before and after, except when they begin a block within a function.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTML attributes, especially class lists, follow an indented multi-line format&lt;/strong&gt; – Keeping long attribute values structured without unnecessary extra lines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No excessive blank lines in HTML between elements&lt;/strong&gt; – Keeps the markup tight but readable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If an HTML element's start and end can fit on one line, keep it that way&lt;/strong&gt; – Avoid unnecessary line breaks for simple elements.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Why Use This Spacing Style?
&lt;/h2&gt;

&lt;p&gt;This formatting approach has multiple benefits, particularly for developers who prioritize &lt;strong&gt;readability, maintainability, and refactoring efficiency&lt;/strong&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Improves Code Readability&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Compact code reduces unnecessary scrolling while keeping logic easy to follow.&lt;/li&gt;
&lt;li&gt;Multi-line statements stand out, making complex operations easier to understand.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Encourages Refactoring&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Blocks of code that take up too much space naturally indicate where a function might be extracted.&lt;/li&gt;
&lt;li&gt;Helps spot redundant or overly complex code sections more quickly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Enhances Debugging &amp;amp; Collaboration&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easier for developers to trace logic without excessive line breaks.&lt;/li&gt;
&lt;li&gt;New contributors can quickly distinguish between simple operations and heavier logic.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Python Example&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here’s how Hybrid Compact Block Spacing applies to Python:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Without Hybrid Compact Block Spacing (Messy Formatting)&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_users&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_active&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_permission&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;user_data&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;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;user&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;email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&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="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;log_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Processed users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;With Hybrid Compact Block Spacing&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_users&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_active&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_permission&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;user_data&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;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;user&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;email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&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="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;log_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Processed users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;HTML Example&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here’s how this method applies to HTML and CSS class formatting:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Without Hybrid Compact Block Spacing (Messy Formatting)&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-white rounded shadow p-6"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center gap-2 mb-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'ui:features' 'docrepox' %}"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center gap-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h3&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"font-bold text-gray-800 underline"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; SECURITY &lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"material-symbols-outlined"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; privacy_tip &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-gray-600"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"material-symbols-outlined"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"font-size: 22px !important;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; verified &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; Your data is safe.
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;With Hybrid Compact Block Spacing&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-white rounded shadow p-6"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center gap-2 mb-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'ui:features' 'docrepox' %}"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center gap-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h3&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"font-bold text-gray-800 underline"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;SECURITY&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"material-symbols-outlined"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        privacy_tip
      &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-gray-600"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"material-symbols-outlined"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"font-size: 22px !important;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      verified
    &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; Your data is safe with modern encryption and user controls. &lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"material-symbols-outlined"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"font-size: 22px !important;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      verified
    &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; Fine-grained access controls to keep your data private.
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  When to Use Hybrid Compact Block Spacing
&lt;/h2&gt;

&lt;p&gt;This approach works best in situations where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code readability is a priority but you want to avoid unnecessary vertical space.&lt;/li&gt;
&lt;li&gt;You frequently refactor your code and need a structure that highlights complex logic.&lt;/li&gt;
&lt;li&gt;HTML attributes (like &lt;code&gt;class&lt;/code&gt;) are long and need structured indentation.&lt;/li&gt;
&lt;li&gt;A multi-line statement inside a function is not the first thing in a block; otherwise, no extra blank line is needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It may not be ideal for teams that follow strict style guides that enforce line-break-heavy formatting, but it can be a great &lt;strong&gt;personal formatting style&lt;/strong&gt; for developers who like &lt;strong&gt;clean, structured&lt;/strong&gt; code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Hybrid Compact Block Spacing is an efficient way to &lt;strong&gt;organize your code&lt;/strong&gt;, making it &lt;strong&gt;more readable, maintainable, and easier to refactor&lt;/strong&gt;. It’s not a widely recognized style (yet), but if you find it useful, consider adopting it in your workflow.&lt;/p&gt;

&lt;p&gt;What do you think about this formatting style? Do you use a similar approach? Let’s discuss in the comments!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Stop Icons from Moving When Your Page Loads</title>
      <dc:creator>Documendous</dc:creator>
      <pubDate>Sun, 16 Feb 2025 17:03:23 +0000</pubDate>
      <link>https://forem.com/documendous/stop-icons-from-moving-when-your-page-loads-5o</link>
      <guid>https://forem.com/documendous/stop-icons-from-moving-when-your-page-loads-5o</guid>
      <description>&lt;p&gt;Have you ever seen your icons flicker or move when your page loads? This happens because the browser loads the icon font a little later, making things shift around. Here’s how to keep the icons in place and make them appear smoothly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Does This Happen?
&lt;/h2&gt;

&lt;p&gt;Material Icons and Symbols use &lt;strong&gt;web fonts&lt;/strong&gt;, which don’t load right away. Instead, the browser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leaves a blank space or shows temporary text where the icon should be.&lt;/li&gt;
&lt;li&gt;Loads the font in the background.&lt;/li&gt;
&lt;li&gt;Puts the icon in place once the font is ready, causing a sudden change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some people use &lt;code&gt;visibility: hidden;&lt;/code&gt; to hide icons until they load, but this makes them &lt;strong&gt;disappear completely&lt;/strong&gt; and causes layout changes. Instead, using &lt;code&gt;opacity: 0;&lt;/code&gt; keeps the space reserved so the page looks smoother.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Fix: Use &lt;code&gt;opacity&lt;/code&gt; Instead of &lt;code&gt;visibility&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Update Your CSS&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Change your CSS to use &lt;code&gt;opacity: 0&lt;/code&gt; so that the icons are invisible at first but don’t move things around:&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="c"&gt;/* Icons are hidden but still take up space */&lt;/span&gt;
&lt;span class="nc"&gt;.material-icons-outlined&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.material-symbols-outlined&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;opacity&lt;/span&gt; &lt;span class="m"&gt;0.2s&lt;/span&gt; &lt;span class="n"&gt;ease-in-out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Fade them in once the page is ready */&lt;/span&gt;
&lt;span class="nc"&gt;.material-icons-loaded&lt;/span&gt; &lt;span class="nc"&gt;.material-icons-outlined&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.material-icons-loaded&lt;/span&gt; &lt;span class="nc"&gt;.material-symbols-outlined&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&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;h3&gt;
  
  
  &lt;strong&gt;2. Update Your JavaScript&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Once the page loads, add a class to make the icons visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;material-icons-loaded&lt;/span&gt;&lt;span class="dl"&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;This makes the icons fade in smoothly instead of appearing suddenly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;What Happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;visibility: hidden;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The icon disappears completely, which can cause things to move.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;opacity: 0;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The icon stays in place but is invisible at first, preventing movement.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Using &lt;code&gt;opacity&lt;/code&gt; means your icons won’t suddenly pop in and push things around.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bonus Tip: Load the Font Faster
&lt;/h2&gt;

&lt;p&gt;To make sure icons appear even faster, you can &lt;strong&gt;preload&lt;/strong&gt; the font so the browser gets it earlier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&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;"preload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/static/material_fonts/icons/material_icon.woff2"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"font"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"font/woff2"&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;&lt;span class="nt"&gt;&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;"preload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/static/material_fonts/symbols/material_symbols.woff2"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"font"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"font/woff2"&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps the browser load the font before it’s needed, reducing the delay.&lt;/p&gt;




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

&lt;p&gt;By using &lt;code&gt;opacity: 0&lt;/code&gt; instead of &lt;code&gt;visibility: hidden&lt;/code&gt;, you can stop your icons from shifting around when they load. This small trick makes your page look better and feel smoother.&lt;/p&gt;

&lt;p&gt;Try it out and see the difference!&lt;/p&gt;

</description>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Remove a Stubborn Docker Volume</title>
      <dc:creator>Documendous</dc:creator>
      <pubDate>Mon, 03 Feb 2025 13:40:51 +0000</pubDate>
      <link>https://forem.com/documendous/how-to-remove-a-stubborn-docker-volume-peb</link>
      <guid>https://forem.com/documendous/how-to-remove-a-stubborn-docker-volume-peb</guid>
      <description>&lt;p&gt;Sometimes, you try to delete a Docker volume and get an error like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Error response from daemon: remove &amp;lt;volume_name&amp;gt;: volume is &lt;span class="k"&gt;in &lt;/span&gt;use
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means something is still using the volume, and Docker won’t let you remove it. Here’s how to fix that.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Find Out What’s Using the Volume
&lt;/h2&gt;

&lt;p&gt;First, check which containers are still using the volume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;--filter&lt;/span&gt; &lt;span class="nv"&gt;volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;volume_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will show you any containers that are still linked to it.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Stop and Remove the Containers
&lt;/h2&gt;

&lt;p&gt;If a container is using the volume, you need to stop and delete it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker stop &amp;lt;container_id&amp;gt;
docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &amp;lt;container_id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeat this for each container in the list.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Remove the Volume
&lt;/h2&gt;

&lt;p&gt;Once no containers are using it, delete the volume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &amp;lt;volume_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, it should be gone.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Clean Up Extra Volumes (Optional)
&lt;/h2&gt;

&lt;p&gt;If you have old volumes you don’t need anymore, clean them up with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume prune &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This removes all unused volumes to free up space.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Check That It’s Gone
&lt;/h2&gt;

&lt;p&gt;To make sure the volume is deleted, list all volumes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it’s not in the list, you’re all set!&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;If you can’t delete a volume, it’s probably still connected to a container. Just stop and remove the container, then try again. This keeps your setup clean and running smoothly.&lt;/p&gt;

&lt;p&gt;Hope this helps!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Convert Audible AAX Files to MP3 for Free</title>
      <dc:creator>Documendous</dc:creator>
      <pubDate>Mon, 20 Jan 2025 01:27:14 +0000</pubDate>
      <link>https://forem.com/documendous/how-to-convert-audible-aax-files-to-mp3-for-free-p20</link>
      <guid>https://forem.com/documendous/how-to-convert-audible-aax-files-to-mp3-for-free-p20</guid>
      <description>&lt;p&gt;Audible audiobooks come in &lt;strong&gt;AAX format&lt;/strong&gt;, which won’t play on many devices. If you want to convert an &lt;strong&gt;AAX file to MP3&lt;/strong&gt;, you need to extract the &lt;strong&gt;activation bytes&lt;/strong&gt; and use &lt;strong&gt;ffmpeg&lt;/strong&gt; to convert the file. Here’s how to do it using free tools.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Install Python and Audible CLI&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You’ll need a tool to grab your &lt;strong&gt;activation bytes&lt;/strong&gt;, which are needed to unlock AAX files.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install Python&lt;/strong&gt; if you don’t have it.&lt;/li&gt;
&lt;li&gt;Open a terminal and install Audible CLI:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   pip &lt;span class="nb"&gt;install &lt;/span&gt;audible-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Log In to Audible&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Since AAX files are linked to your Audible account, you have to sign in.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start the setup process:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   python &lt;span class="nt"&gt;-m&lt;/span&gt; audible_cli quickstart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Enter your Audible login details when prompted:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   Please enter your amazon username: [your_email@example.com]
   Please enter your amazon password: 
   Repeat for confirmation: 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;If you have two-factor authentication, enter the OTP:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   2FA is activated for this account.
   Please enter OTP Code: 123456
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After logging in, your credentials will be saved for future use.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Get Your Activation Bytes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Next, you need to grab your &lt;strong&gt;activation bytes&lt;/strong&gt; to unlock the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; audible_cli activation-bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see a 16-character code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Fetching activation bytes from Audible server
Save activation bytes to file
xxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy this code—you’ll need it for the next step.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 4: Convert AAX to MP3 Using ffmpeg&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now, use &lt;strong&gt;ffmpeg&lt;/strong&gt; to turn the file into an MP3.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install ffmpeg if you don’t have it:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg  &lt;span class="c"&gt;# Ubuntu&lt;/span&gt;
   brew &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg  &lt;span class="c"&gt;# macOS&lt;/span&gt;
   choco &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg  &lt;span class="c"&gt;# Windows (Chocolatey)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Convert the AAX file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   ffmpeg &lt;span class="nt"&gt;-activation_bytes&lt;/span&gt; YOUR_ACTIVATION_KEY &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"yourfile.aax"&lt;/span&gt; &lt;span class="nt"&gt;-vn&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;:a libmp3lame &lt;span class="nt"&gt;-q&lt;/span&gt;:a 4 &lt;span class="s2"&gt;"output.mp3"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;YOUR_ACTIVATION_KEY&lt;/code&gt; with the code you got earlier and &lt;code&gt;yourfile.aax&lt;/code&gt; with your file’s name.&lt;/p&gt;

&lt;p&gt;Once done, you’ll have an &lt;strong&gt;MP3 file&lt;/strong&gt; that works anywhere.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Wrapping Up&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With these simple steps, you can convert Audible AAX files to MP3 and listen to your audiobooks on any device. This method is free, doesn’t require extra software, and works on &lt;strong&gt;Windows, macOS, and Linux&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you run into issues or know a better way, drop a comment below!&lt;/p&gt;

</description>
      <category>audible</category>
      <category>aws</category>
      <category>mp3</category>
      <category>audiobooks</category>
    </item>
    <item>
      <title>Using Django Fixtures with Foreign Keys Without Hardcoded IDs</title>
      <dc:creator>Documendous</dc:creator>
      <pubDate>Thu, 16 Jan 2025 22:13:20 +0000</pubDate>
      <link>https://forem.com/documendous/using-django-fixtures-with-foreign-keys-without-hardcoded-ids-1pa0</link>
      <guid>https://forem.com/documendous/using-django-fixtures-with-foreign-keys-without-hardcoded-ids-1pa0</guid>
      <description>&lt;p&gt;When working with Django, fixtures make it easy to load sample data into your database. But if you hardcode foreign key IDs, your fixtures can break when IDs change or if you move data between databases.&lt;/p&gt;

&lt;p&gt;A better way is to use &lt;strong&gt;natural keys&lt;/strong&gt;, which let you reference foreign keys by meaningful values instead of numeric IDs.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why Avoid Hardcoded IDs in Fixtures?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Hardcoding primary keys in fixtures can cause problems like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data mismatches across different databases.&lt;/li&gt;
&lt;li&gt;Fixtures breaking when IDs change.&lt;/li&gt;
&lt;li&gt;Extra work managing relationships manually.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Natural keys solve this by letting Django look up relationships dynamically.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Setting Up Natural Keys in Django&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To use natural keys, you need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Define a &lt;code&gt;natural_key()&lt;/code&gt; method&lt;/strong&gt; in the related model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a custom manager&lt;/strong&gt; to fetch objects using the natural key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the natural key in your fixture&lt;/strong&gt; instead of a numeric ID.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Define a Natural Key in the Related Model&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;models.py&lt;/code&gt;, add a &lt;code&gt;natural_key()&lt;/code&gt; method to the model that is referenced by a foreign key.&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;CategoryManager&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;Manager&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;get_by_natural_key&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="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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&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="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Category&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;name&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;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unique&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="n"&gt;objects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CategoryManager&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;natural_key&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="nf"&gt;return &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="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you reference categories by name instead of ID in fixtures.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Create a Fixture Using Natural Keys&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of using numeric IDs, reference foreign keys by their natural key.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Fixture Example (Using Numeric IDs – Old Approach)&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shop.category"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"pk"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"fields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Electronics"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shop.product"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"fields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Smartphone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Fixture Example (Using Natural Keys – Improved Approach)&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shop.category"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"fields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Electronics"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shop.product"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"fields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Smartphone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Electronics"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Django will automatically look up the category by name instead of using an ID.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Load the Fixtures&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Once your fixture is ready, load it with:&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 loaddata your_fixture.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Django will use &lt;code&gt;get_by_natural_key()&lt;/code&gt; to match foreign keys.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Are Natural Keys Mandatory?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;No. If you define a &lt;code&gt;natural_key()&lt;/code&gt;, Django still lets you use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Numeric IDs&lt;/strong&gt; (old approach).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural keys&lt;/strong&gt; (more flexible).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can mix both as needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;When Should You Use Natural Keys?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Use natural keys if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You want fixtures that work across different databases.&lt;/li&gt;
&lt;li&gt;Your model has a unique field (like &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;slug&lt;/code&gt;, or &lt;code&gt;name&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;You don’t want to track numeric IDs manually.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stick with numeric IDs if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your model doesn’t have a unique natural identifier.&lt;/li&gt;
&lt;li&gt;You’re working with small, static datasets.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Using natural keys in Django fixtures keeps your data more flexible and easier to manage. Instead of relying on IDs that may change, Django will look up relationships dynamically, making your fixtures more reliable.&lt;/p&gt;

&lt;p&gt;Try using natural keys in your Django project to simplify your fixtures and avoid unnecessary headaches.&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
    </item>
    <item>
      <title>How to Get Back a Lost Git Branch</title>
      <dc:creator>Documendous</dc:creator>
      <pubDate>Thu, 16 Jan 2025 12:19:52 +0000</pubDate>
      <link>https://forem.com/documendous/how-to-get-back-a-lost-git-branch-18ml</link>
      <guid>https://forem.com/documendous/how-to-get-back-a-lost-git-branch-18ml</guid>
      <description>&lt;p&gt;Losing a feature branch in Git can be frustrating, but there’s usually a way to recover it. Whether it was deleted, force-pushed, or just seems to have disappeared, here’s how to bring it back.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Check Git Reflog
&lt;/h2&gt;

&lt;p&gt;Git keeps track of changes to your branches with &lt;code&gt;git reflog&lt;/code&gt;. This can help find lost commits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git reflog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look through the list to find the commit hash where your work was last intact.&lt;/p&gt;

&lt;p&gt;Once you’ve found the right commit, you can restore it.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Restore Your Work
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Option 1: Create a new branch from the lost commit
&lt;/h3&gt;

&lt;p&gt;Use the commit hash from &lt;code&gt;reflog&lt;/code&gt; to make a new branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; recovery-branch &amp;lt;commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your work is back in a safe place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: Reset your branch
&lt;/h3&gt;

&lt;p&gt;If your feature branch still exists but is missing changes, you can reset it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; &amp;lt;commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Be careful:&lt;/strong&gt; This will erase any changes since that commit.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Check the Remote Repository
&lt;/h2&gt;

&lt;p&gt;If the branch was changed or deleted on the remote, check for lost commits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git fsck &lt;span class="nt"&gt;--lost-found&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this shows lost commits, you can inspect them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git show &amp;lt;commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the branch was force-pushed, you might still find its history:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git reflog origin/feature-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Merge or Push Your Changes Back
&lt;/h2&gt;

&lt;p&gt;Once you’ve recovered your work, you can merge it back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git checkout feature-branch
 git merge recovery-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, if the branch was deleted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git branch feature-branch recovery-branch
 git checkout feature-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then push it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git push origin feature-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;p&gt;Git keeps track of more than you might think, so there’s usually a way to recover lost work. The key is to act quickly and check &lt;code&gt;reflog&lt;/code&gt; before assuming your work is gone. &lt;/p&gt;

&lt;p&gt;Have you ever lost a branch and brought it back? Let me know how you did it!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How ChatGPT Can Help You Maintain Code Quality Without Gold Plating</title>
      <dc:creator>Documendous</dc:creator>
      <pubDate>Tue, 14 Jan 2025 12:21:19 +0000</pubDate>
      <link>https://forem.com/documendous/how-chatgpt-can-help-you-maintain-code-quality-without-gold-plating-10bp</link>
      <guid>https://forem.com/documendous/how-chatgpt-can-help-you-maintain-code-quality-without-gold-plating-10bp</guid>
      <description>&lt;p&gt;As developers, we all want to write code that works well and is easy to maintain. But sometimes, in trying to make our work perfect, we end up doing too much – a problem known as &lt;strong&gt;gold plating&lt;/strong&gt;. This happens when you add features or complexity that nobody asked for or really needs. While it might feel like you're improving things, you're often just wasting time and making the code harder to work with.&lt;/p&gt;

&lt;p&gt;Instead of doing extra for the sake of it, it’s better to focus on writing good, solid code that meets the actual needs of the project. In this article, we’ll look at how ChatGPT can help you stay focused, work efficiently, and avoid falling into the gold plating trap.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Gold Plating?
&lt;/h2&gt;

&lt;p&gt;Gold plating means adding extra features or complexity that go beyond what’s required. It often comes from wanting to impress others or future-proof the code. But there are downsides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wasted Time&lt;/strong&gt;: You spend time on things that don’t really matter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Harder to Understand&lt;/strong&gt;: The code becomes more complicated and harder for others to follow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Losing Focus&lt;/strong&gt;: You can end up distracted from the original goal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Higher Costs&lt;/strong&gt;: All this extra work takes more time and money.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  A Smarter Way to Code
&lt;/h2&gt;

&lt;p&gt;Instead of overdoing it, focus on getting the basics right. Write code that works, is easy to read, and can grow with the project. Here are a few simple tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep your code clear and organized.&lt;/li&gt;
&lt;li&gt;Don’t add anything that isn’t needed.&lt;/li&gt;
&lt;li&gt;Follow simple rules like &lt;strong&gt;Keep It Simple&lt;/strong&gt; or &lt;strong&gt;Don’t Repeat Yourself&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Refactor your code later to clean it up, but only when it’s necessary.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How ChatGPT Can Help
&lt;/h2&gt;

&lt;p&gt;ChatGPT is a great partner for improving your workflow and avoiding unnecessary complexity. Here are some specific ways to use it effectively:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Review Your Code for Simplicity and Clarity&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ask for feedback on variable and function names&lt;/strong&gt;: Paste a snippet of your code and ask ChatGPT if the names you’ve used are clear and descriptive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check if your code is easy to read&lt;/strong&gt;: Share a function or file and ask ChatGPT to identify parts that might be confusing or overly complex.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get advice on structure&lt;/strong&gt;: Ask if your code could benefit from splitting into smaller functions, classes, or separate components (e.g., in Django, whether to create a new app).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Debug More Effectively&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Paste error messages and related code, and ask ChatGPT to help identify the root cause and suggest fixes.&lt;/li&gt;
&lt;li&gt;Use ChatGPT to find common mistakes in the code you’ve written, especially if something isn’t working as expected.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Focus on Meeting Requirements&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Share the goals of your task and ask ChatGPT to help ensure you’re sticking to them.&lt;/li&gt;
&lt;li&gt;Get help identifying unnecessary features you might be tempted to add but don’t actually need.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Refactor Without Overthinking&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Once your code is working, ask ChatGPT to suggest ways to simplify it. For example:

&lt;ul&gt;
&lt;li&gt;Are there parts of the code that are repeated and could be consolidated?&lt;/li&gt;
&lt;li&gt;Are there better ways to handle error checking or logging?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Improve Testing and Validation&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ask for test case suggestions to ensure your code works as expected.&lt;/li&gt;
&lt;li&gt;Get help setting up tools like pytest or writing unit tests for specific parts of your code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;Learn Better Practices While You Work&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Have ChatGPT explain coding principles in the context of your code. For example:

&lt;ul&gt;
&lt;li&gt;“Does this code follow the Single Responsibility Principle?”&lt;/li&gt;
&lt;li&gt;“How can I make this function more reusable?”&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Use ChatGPT to learn about best practices for the language or framework you’re using.&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  A Practical Coding Workflow
&lt;/h2&gt;

&lt;p&gt;Here’s a simple process you can follow to keep your work on track and your code in good shape:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Work on One Thing at a Time&lt;/strong&gt;: Focus on the feature, bug fix, or update you’re tackling. Use tools like GitHub Issues or Jira to track your progress.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get It Working First&lt;/strong&gt;: Make sure the code works and solves the problem. Don’t worry about perfection yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go Back and Review&lt;/strong&gt;: Once it works, step back and check your work:

&lt;ul&gt;
&lt;li&gt;Did you name things clearly?&lt;/li&gt;
&lt;li&gt;Is everything where it belongs?&lt;/li&gt;
&lt;li&gt;Would it make sense to split some of the work into separate files or components?&lt;/li&gt;
&lt;li&gt;Could this code cause problems later?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask ChatGPT for a Final Review&lt;/strong&gt;: Use ChatGPT to review the code with fresh eyes and spot anything you might have missed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This way, you’ll deliver something functional quickly while still ensuring your code is clean and easy to manage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Adding too much to your code can cause more harm than good. Instead, focus on writing code that does what it needs to do and does it well. ChatGPT can be a helpful tool for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reviewing and improving your code.&lt;/li&gt;
&lt;li&gt;Keeping you focused on your goals.&lt;/li&gt;
&lt;li&gt;Teaching you better ways to write clean, maintainable code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember, great code isn’t about doing more. It’s about doing what’s needed in the best way possible. What are your favorite ways to keep your code simple and effective? Share your tips in the comments below!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Run a Script Before Debugging Your Django App in VSCode</title>
      <dc:creator>Documendous</dc:creator>
      <pubDate>Sat, 04 Jan 2025 14:53:29 +0000</pubDate>
      <link>https://forem.com/documendous/run-a-script-before-debugging-your-django-app-in-vscode-475b</link>
      <guid>https://forem.com/documendous/run-a-script-before-debugging-your-django-app-in-vscode-475b</guid>
      <description>&lt;p&gt;You know what’s annoying? Debugging a Django app and realizing, halfway through, that you forgot to reset your database or run migrations. It’s repetitive, it’s boring, and worst of all, it’s easy to forget. Why not let your tools handle it for you? If you’re using Visual Studio Code, you can set things up so your script runs automatically every time you start the debugger.&lt;/p&gt;

&lt;p&gt;Here’s how to do it—quick and simple.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Let’s say you’ve got a little shell script called &lt;code&gt;setup.sh&lt;/code&gt; that preps your environment:&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="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate

&lt;span class="nb"&gt;sudo &lt;/span&gt;su - postgres &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"dropdb docrepo"&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;su - postgres &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"createdb docrepo -O admin"&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;docrepo
python manage.py migrate
&lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This resets the database and runs migrations. Great. But you’re tired of running it manually every time you debug. Why should you have to remember something a computer could do for you?&lt;/p&gt;




&lt;h3&gt;
  
  
  The Solution: Automate It with VSCode
&lt;/h3&gt;

&lt;p&gt;The trick here is to hook your script into VSCode’s debugging workflow using &lt;code&gt;tasks.json&lt;/code&gt; and &lt;code&gt;launch.json&lt;/code&gt;. With just a little setup, you can have your script run automatically before the debugger starts.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 1: Define the Task
&lt;/h3&gt;

&lt;p&gt;First, you need to tell VSCode how to run your script. Open (or create) &lt;code&gt;.vscode/tasks.json&lt;/code&gt; and add this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Run Pre-Debug Script"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./setup.sh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"presentation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"reveal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"problemMatcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s what’s going on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;"label"&lt;/code&gt;: The name of this task. You’ll refer to it in the next step.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"command"&lt;/code&gt;: Path to your script. Make sure it’s executable (&lt;code&gt;chmod +x setup.sh&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"presentation"&lt;/code&gt;: Controls how the output is displayed. Set it to &lt;code&gt;"always"&lt;/code&gt; so you can see what’s happening.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 2: Connect the Task to the Debugger
&lt;/h3&gt;

&lt;p&gt;Next, wire this task into your debugger configuration. Open &lt;code&gt;.vscode/launch.json&lt;/code&gt; and edit the Django debugger settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"configurations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Python Debugger: Django"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"program"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/docrepo/manage.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"runserver"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"--noreload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"--nothreading"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"django"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"justMyCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"autoStartBrowser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"PYTHONPATH"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/docrepo"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"preLaunchTask"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Run Pre-Debug Script"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;"preLaunchTask"&lt;/code&gt;: This tells the debugger to run your &lt;code&gt;setup.sh&lt;/code&gt; task before it starts.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"args"&lt;/code&gt;: The arguments passed to Django’s &lt;code&gt;runserver&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--noreload&lt;/code&gt;: Disables Django’s auto-reloading feature so your script doesn’t run twice.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--nothreading&lt;/code&gt;: Disables multi-threading, which makes debugging simpler and less unpredictable.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 3: Test It
&lt;/h3&gt;

&lt;p&gt;Now for the fun part. Open the Debug panel in VSCode, select the &lt;code&gt;"Python Debugger: Django"&lt;/code&gt; configuration, and hit &lt;code&gt;F5&lt;/code&gt;. Here’s what should happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your &lt;code&gt;setup.sh&lt;/code&gt; script runs. You’ll see the output in the terminal.&lt;/li&gt;
&lt;li&gt;Once the script finishes, the Django development server starts, ready for debugging.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If something doesn’t work, check the terminal output. Most issues are permissions-related (e.g., make sure your script is executable with &lt;code&gt;chmod +x setup.sh&lt;/code&gt;).&lt;/p&gt;




&lt;h3&gt;
  
  
  Why This Is Better
&lt;/h3&gt;

&lt;p&gt;This setup is simple, clear, and doesn’t waste your time. Instead of juggling multiple terminals or trying to remember yet another manual step, you let your tools handle it for you. Debugging should be about solving problems in your app, not about fighting your workflow.&lt;/p&gt;

&lt;p&gt;If you’re wondering why &lt;code&gt;--noreload&lt;/code&gt; and &lt;code&gt;--nothreading&lt;/code&gt; are here, it’s because Django’s auto-reloading and threading features can cause weird behavior when running setup tasks. Turning them off gives you a consistent, predictable environment—exactly what you want when debugging.&lt;/p&gt;




&lt;h3&gt;
  
  
  That’s It
&lt;/h3&gt;

&lt;p&gt;No fluff, no unnecessary complexity. Now your debugger does exactly what you need, every time. Automation like this frees you up to focus on the real work. Isn’t that what good tools are supposed to do?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Getting the Most Out of AI with this Simple Method</title>
      <dc:creator>Documendous</dc:creator>
      <pubDate>Mon, 30 Dec 2024 14:11:58 +0000</pubDate>
      <link>https://forem.com/documendous/getting-the-most-out-of-ai-with-this-simple-method-469j</link>
      <guid>https://forem.com/documendous/getting-the-most-out-of-ai-with-this-simple-method-469j</guid>
      <description>&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%2Fu5acsowpd3jfeox60rh1.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%2Fu5acsowpd3jfeox60rh1.png" alt="Image description" width="800" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Artificial Intelligence (AI) is a powerful tool that can help with tasks like writing, coding, and more. To get the best results, though, you need to know how to talk to it in the right way. After using AI for a while, I’ve come up with an easy method to make it more helpful and reliable for any type of work.&lt;/p&gt;

&lt;p&gt;Here’s the step-by-step process I use to get the most out of AI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Start with a Clear Role&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%2F7k2q0zsvdpfhomwvaqdv.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%2F7k2q0zsvdpfhomwvaqdv.png" alt="Image description" width="800" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you ask AI for help, begin by telling it what role it should take. Think of it like assigning it a job. For example:&lt;br&gt;
“You are a software engineer with expertise in Python and Django.”&lt;/p&gt;

&lt;p&gt;This helps the AI understand how to approach your question. When it knows its role, it can give you better answers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Give Useful Background Information&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%2Fqkxxnqpqvzq0iwdyiqry.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%2Fqkxxnqpqvzq0iwdyiqry.png" alt="Image description" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI works best when it has enough details to do its job. Give it some background, like who the audience is, what your project is about, or what result you want. For instance, if you’re writing a blog post, explain who will read it and what they should learn.&lt;/p&gt;

&lt;p&gt;It’s okay if you don’t include every single detail. The AI can ask for more if it needs to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Be Clear About What You Want&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%2Fmnuen1pyr5ib8ngwiplr.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%2Fmnuen1pyr5ib8ngwiplr.png" alt="Image description" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Say exactly what you need in a simple way. Don’t be vague. For example, instead of saying, “Help me with Django,” try:&lt;br&gt;
“Write a short explanation of how Django handles database migrations.”&lt;/p&gt;

&lt;p&gt;The clearer your request, the better the AI will understand and respond.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Let AI Ask Questions&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%2Fplilyd83lnyetlc7fxb8.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%2Fplilyd83lnyetlc7fxb8.png" alt="Image description" width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Allow the AI to ask you follow-up questions. This creates a back-and-forth conversation, which is especially helpful for more detailed or complicated tasks.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;“Write a step-by-step guide for setting up a basic Django project. If you need more details, feel free to ask.”&lt;/p&gt;

&lt;p&gt;This way, you don’t have to think of everything ahead of time. The AI can help fill in the gaps as you go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How This Method Works in Real Life&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here are some examples of how you can use this method for different tasks:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Code Review&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Request:&lt;/p&gt;

&lt;p&gt;“You are a senior developer. Review this Django view for performance and readability. Suggest any improvements, and let me know if anything needs clarification.”&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Writing Marketing Content&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Request:&lt;/p&gt;

&lt;p&gt;“You are a marketing copywriter. Create a social media post about our app’s new feature that cuts load times in half. Let me know if you need more context about our audience.”&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Creating a Work Process&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Request:&lt;/p&gt;

&lt;p&gt;“You are a project manager. Write steps for how our team should handle bug reports during a software project. If you need more details about our current process, just ask.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Method Works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This method is simple because it focuses on clarity and context. By giving AI the right information upfront, you avoid the frustration of getting answers that don’t make sense or aren’t helpful.&lt;/p&gt;

&lt;p&gt;Think of your interaction with AI as teamwork. You don’t expect perfect answers right away. Instead, you work with the AI to refine its response until it’s just right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use It for Anything&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The best part of this method is that it works with any AI tool, not just ChatGPT. Whether you’re writing, coding, or planning, following these steps will help you get better results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Give It a Try&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’ve been having trouble getting what you need from AI, try this simple method. It’s easy to use, works for almost any task, and makes AI a more reliable partner. Once you get the hang of it, you’ll find that working with AI becomes smoother and more productive.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
